11// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*
22/* exported WindowMenuManager */
33
4- const { GLib, Meta, St, Gtk } = imports . gi ;
4+ const { Clutter , GLib, Meta, St, Gtk } = imports . gi ;
55
6- const BoxPointer = imports . ui . boxpointer ;
76const Main = imports . ui . main ;
87const PopupMenu = imports . ui . popupMenu ;
9- const Lang = imports . lang ;
108const CheckBox = imports . ui . checkBox ;
119const RadioButton = imports . ui . radioButton ;
1210
13- var LeftOrnamentedMenuItem = class LeftOrnamentedMenuItem extends PopupMenu . PopupBaseMenuItem {
14- _init ( text , params ) {
11+ var BaseMnemonicMenuItem = class BaseMnemonicMenuItem extends PopupMenu . PopupBaseMenuItem {
12+ _init ( label , params ) {
1513 super . _init . call ( this , params ) ;
1614
15+ this . mnemonicInit ( label ) ;
16+ }
17+
18+ mnemonicInit ( label ) {
19+ this . origLabel = label ;
20+ this . plain = null ;
21+ this . mnemonized = null ;
22+ this . showing_mnemonic = false ;
23+ }
24+
25+ _setLabels ( ) {
26+ let markup = null ;
27+ let plain = null ;
28+ let mnemonic = undefined ;
29+ let title_pieces = this . origLabel . split ( "_" ) ;
30+
31+ if ( title_pieces . length === 2 ) {
32+ this . mnemonic = title_pieces [ 1 ] [ 0 ] . toLowerCase ( ) ;
33+ this . mnemonized = `${ title_pieces [ 0 ] } <u>${ title_pieces [ 1 ] [ 0 ] } </u>${ title_pieces [ 1 ] . substring ( 1 ) } ` ;
34+ this . plain = `${ title_pieces [ 0 ] } ${ title_pieces [ 1 ] } ` ;
35+ } else {
36+ this . plain = this . origLabel ;
37+ this . mnemonized = this . origLabel ;
38+ }
39+
40+ this . label . clutter_text . set_markup ( this . plain ) ;
41+ }
42+
43+ toggleMnemonic ( ) {
44+ if ( ! this . showing_mnemonic ) {
45+ this . label . clutter_text . set_markup ( this . mnemonized ) ;
46+ this . showing_mnemonic = true ;
47+ } else {
48+ this . label . clutter_text . set_markup ( this . plain ) ;
49+ this . showing_mnemonic = false ;
50+ }
51+
52+ this . label . clutter_text . queue_relayout ( ) ;
53+ }
54+ }
55+
56+ var MnemonicLeftOrnamentedMenuItem = class MnemonicLeftOrnamentedMenuItem extends BaseMnemonicMenuItem {
57+ _init ( label , params ) {
58+ super . _init . call ( this , label , params ) ;
59+
1760 this . _ornament = new St . Bin ( ) ;
1861 this . _icon = new St . Icon ( { style_class : 'popup-menu-icon' , icon_type : St . IconType . SYMBOLIC } ) ;
1962
2063 this . _ornament . child = this . _icon ;
2164 this . _ornament . child . _delegate = this . _ornament ;
2265 this . addActor ( this . _ornament , { span : 1 } ) ;
2366
24- this . label = new St . Label ( { text : text } ) ;
67+ this . label = new St . Label ( ) ;
2568 this . addActor ( this . label ) ;
2669 this . actor . label_actor = this . label ;
2770
28- }
29-
30- setLabel ( label ) {
31- this . label . set_text ( label ) ;
71+ this . _setLabels ( ) ;
3272 }
3373
3474 setIcon ( icon_name ) {
@@ -71,6 +111,20 @@ var LeftOrnamentedMenuItem = class LeftOrnamentedMenuItem extends PopupMenu.Popu
71111 }
72112}
73113
114+ var MnemonicSubMenuMenuItem = class MnemonicSubMenuMenuItem extends PopupMenu . PopupSubMenuMenuItem {
115+ _init ( label , params ) {
116+ super . _init . call ( this , label ) ;
117+ BaseMnemonicMenuItem . prototype . mnemonicInit . call ( this , label ) ;
118+
119+ // to help align with left side ornaments
120+ let filler = new St . Icon ( { style_class : 'popup-menu-icon' , icon_type : St . IconType . SYMBOLIC } ) ;
121+ this . addActor ( filler , { span : 1 , position : 0 } ) ;
122+
123+ this . _setLabels ( ) ;
124+ }
125+ }
126+ MnemonicSubMenuMenuItem . prototype . toggleMnemonic = BaseMnemonicMenuItem . prototype . toggleMnemonic ;
127+ MnemonicSubMenuMenuItem . prototype . _setLabels = BaseMnemonicMenuItem . prototype . _setLabels ;
74128
75129var WindowMenu = class extends PopupMenu . PopupMenu {
76130 constructor ( window , sourceActor ) {
@@ -81,17 +135,53 @@ var WindowMenu = class extends PopupMenu.PopupMenu {
81135 Main . uiGroup . add_actor ( this . actor ) ;
82136 this . actor . hide ( ) ;
83137
138+ this . actor . connect ( 'key-press-event' , this . _windowMenuKeypress . bind ( this ) ) ;
139+
140+ this . _items = [ ] ;
84141 this . _buildMenu ( window ) ;
85142 }
86143
144+ _windowMenuKeypress ( actor , event ) {
145+ if ( this . _onKeyPressEvent ( actor , event ) === Clutter . EVENT_STOP ) {
146+ return Clutter . EVENT_STOP ;
147+ }
148+
149+ if ( event . get_key_symbol ( ) === Clutter . KEY_Alt_R || event . get_key_symbol ( ) === Clutter . KEY_Alt_L ) {
150+ let items = this . _getMenuItems ( ) ;
151+
152+ for ( let item of this . _items ) {
153+ if ( item . mnemonic !== undefined ) {
154+ item . toggleMnemonic ( ) ;
155+ }
156+ }
157+ return Clutter . EVENT_STOP ;
158+ }
159+
160+ let items = this . _getMenuItems ( ) ;
161+ for ( let item of this . _items ) {
162+ if ( ! item . sensitive ) {
163+ continue ;
164+ }
165+
166+ if ( item . mnemonic != undefined && item . mnemonic [ 0 ] === String . fromCharCode ( event . get_key_symbol ( ) ) . toLowerCase ( ) ) {
167+ item . activate ( event ) ;
168+ return Clutter . EVENT_STOP ;
169+ }
170+ }
171+
172+ return Clutter . EVENT_PROPAGATE ;
173+ }
174+
87175 addAction ( to_menu , title , callback ) {
88- let menuItem = new LeftOrnamentedMenuItem ( title ) ;
176+ let menuItem = new MnemonicLeftOrnamentedMenuItem ( title ) ;
89177 to_menu . addMenuItem ( menuItem ) ;
90178
91179 menuItem . connect ( 'activate' , ( o , event ) => {
92180 callback ( event ) ;
93181 } ) ;
94182
183+ this . _items . push ( menuItem ) ;
184+
95185 return menuItem ;
96186 }
97187
@@ -100,7 +190,9 @@ var WindowMenu = class extends PopupMenu.PopupMenu {
100190
101191 let item ;
102192
103- item = this . addAction ( this , _ ( "Minimize" ) , ( ) => {
193+ // Translators: If a language-specific mnemonic doesn't make sense, add one after the label itself:
194+ // i.e. <translated>(_n). See https://github.com/linuxmint/muffin/blob/b9a6f3fe43e/po .po files
195+ item = this . addAction ( this , _ ( "Mi_nimize" ) , ( ) => {
104196 window . minimize ( ) ;
105197 } ) ;
106198 item . setIcon ( "window-minimize-symbolic" ) ;
@@ -109,39 +201,51 @@ var WindowMenu = class extends PopupMenu.PopupMenu {
109201 item . setSensitive ( false ) ;
110202
111203 if ( window . get_maximized ( ) ) {
112- item = this . addAction ( this , _ ( "Unmaximize" ) , ( ) => {
204+ // Translators: If a language-specific mnemonic doesn't make sense, add one after the label itself:
205+ // i.e. <translated>(_n). See https://github.com/linuxmint/muffin/blob/b9a6f3fe43e/po .po files
206+ item = this . addAction ( this , _ ( "Unma_ximize" ) , ( ) => {
113207 window . unmaximize ( Meta . MaximizeFlags . BOTH ) ;
114208 } ) ;
115209 } else {
116- item = this . addAction ( this , _ ( "Maximize" ) , ( ) => {
210+ // Translators: If a language-specific mnemonic doesn't make sense, add one after the label itself:
211+ // i.e. <translated>(_n). See https://github.com/linuxmint/muffin/blob/b9a6f3fe43e/po .po files
212+ item = this . addAction ( this , _ ( "Ma_ximize" ) , ( ) => {
117213 window . maximize ( Meta . MaximizeFlags . BOTH ) ;
118214 } ) ;
119215 item . setIcon ( "window-maximize-symbolic" ) ;
120216 }
121217 if ( ! window . can_maximize ( ) )
122218 item . setSensitive ( false ) ;
123219
124- item = this . addAction ( this , _ ( "Move" ) , event => {
220+ // Translators: If a language-specific mnemonic doesn't make sense, add one after the label itself:
221+ // i.e. <translated>(_n). See https://github.com/linuxmint/muffin/blob/b9a6f3fe43e/po .po files
222+ item = this . addAction ( this , _ ( "_Move" ) , event => {
125223 this . _grabAction ( window , Meta . GrabOp . KEYBOARD_MOVING , event . get_time ( ) ) ;
126224 } ) ;
127225 if ( ! window . allows_move ( ) )
128226 item . setSensitive ( false ) ;
129227
130- item = this . addAction ( this , _ ( "Resize" ) , event => {
228+ // Translators: If a language-specific mnemonic doesn't make sense, add one after the label itself:
229+ // i.e. <translated>(_n). See https://github.com/linuxmint/muffin/blob/b9a6f3fe43e/po .po files
230+ item = this . addAction ( this , _ ( "_Resize" ) , event => {
131231 this . _grabAction ( window , Meta . GrabOp . KEYBOARD_RESIZING_UNKNOWN , event . get_time ( ) ) ;
132232 } ) ;
133233 if ( ! window . allows_resize ( ) )
134234 item . setSensitive ( false ) ;
135235
136236 if ( ! window . titlebar_is_onscreen ( ) && type != Meta . WindowType . DOCK && type != Meta . WindowType . DESKTOP ) {
237+ // Translators: If a language-specific mnemonic doesn't make sense, add one after the label itself:
238+ // i.e. <translated>(_n). See https://github.com/linuxmint/muffin/blob/b9a6f3fe43e/po .po files
137239 this . addAction ( this , _ ( "Move Titlebar Onscreen" ) , ( ) => {
138240 window . shove_titlebar_onscreen ( ) ;
139241 } ) ;
140242 }
141243
142244 this . addMenuItem ( new PopupMenu . PopupSeparatorMenuItem ( ) ) ;
143245
144- item = this . addAction ( this , _ ( "Always on Top" ) , ( ) => {
246+ // Translators: If a language-specific mnemonic doesn't make sense, add one after the label itself:
247+ // i.e. <translated>(_n). See https://github.com/linuxmint/muffin/blob/b9a6f3fe43e/po .po files
248+ item = this . addAction ( this , _ ( "Always on _Top" ) , ( ) => {
145249 if ( window . is_above ( ) )
146250 window . unmake_above ( ) ;
147251 else
@@ -161,12 +265,14 @@ var WindowMenu = class extends PopupMenu.PopupMenu {
161265 window . is_on_primary_monitor ( ) ) ) {
162266 let isSticky = window . is_on_all_workspaces ( ) ;
163267
164- this . sticky_action = this . addAction ( this , _ ( "Always on Visible Workspace" ) , ( ) => {
165- log ( "stick" ) ;
268+ // Translators: If a language-specific mnemonic doesn't make sense, add one after the label itself:
269+ // i.e. <translated>(_n). See https://github.com/linuxmint/muffin/blob/b9a6f3fe43e/po .po files
270+ this . sticky_action = this . addAction ( this , _ ( "_Always on Visible Workspace" ) , ( ) => {
166271 window . stick ( ) ;
167272 } ) ;
168- this . unsticky_action = this . addAction ( this , _ ( "Only on This Workspace" ) , ( ) => {
169- log ( "unstick" ) ;
273+ // Translators: If a language-specific mnemonic doesn't make sense, add one after the label itself:
274+ // i.e. <translated>(_n). See https://github.com/linuxmint/muffin/blob/b9a6f3fe43e/po .po files
275+ this . unsticky_action = this . addAction ( this , _ ( "_Only on This Workspace" ) , ( ) => {
170276 window . unstick ( ) ;
171277 } ) ;
172278 this . sticky_action . setOrnament ( PopupMenu . OrnamentType . DOT , isSticky ) ;
@@ -177,17 +283,48 @@ var WindowMenu = class extends PopupMenu.PopupMenu {
177283 this . unsticky_action . setSensitive ( false ) ;
178284 }
179285
180- let ws_sub = new PopupMenu . PopupSubMenuMenuItem ( _ ( "Move to Another Workspace" ) ) ;
181- let filler = new St . Icon ( { style_class : 'popup-menu-icon' , icon_type : St . IconType . SYMBOLIC } ) ;
182- ws_sub . addActor ( filler , { span : 1 , position : 0 } ) ;
183-
286+ // Translators: If a language-specific mnemonic doesn't make sense, add one after the label itself:
287+ // i.e. <translated>(_n). See https://github.com/linuxmint/muffin/blob/b9a6f3fe43e/po .po files
288+ let ws_sub = new MnemonicSubMenuMenuItem ( _ ( "Move to Another _Workspace" ) ) ;
184289 this . addMenuItem ( ws_sub ) ;
290+ this . _items . push ( ws_sub ) ;
185291
186292 let curr_index = window . get_workspace ( ) . index ( ) ;
293+ let used_nums = { } ;
294+ let name = null ;
295+
187296 for ( let i = 0 ; i < global . workspace_manager . get_n_workspaces ( ) ; i ++ ) {
188- let j = i ;
189- let name = Main . workspace_names [ i ] ? Main . workspace_names [ i ] : Main . _makeDefaultWorkspaceName ( i ) ;
190- item = this . addAction ( ws_sub . menu , name , ( ) => window . change_workspace ( global . workspace_manager . get_workspace_by_index ( j ) ) )
297+ if ( used_nums [ i + 1 ] ) {
298+ continue ;
299+ }
300+
301+ let name = Main . workspace_names [ i ] ;
302+
303+ if ( name === undefined || name === '' ) {
304+ name = Main . getWorkspaceName ( i ) ;
305+ }
306+
307+ let end = name . substring ( name . length - 2 ) . replace ( "_" , "" ) ;
308+ let number = parseInt ( end ) ;
309+
310+ if ( ! isNaN ( number ) && used_nums [ number ] == undefined ) {
311+ if ( number == 10 ) {
312+ name = name . replace ( "10" , "1_0" ) ;
313+ used_nums [ 10 ] = true ;
314+ }
315+ else
316+ if ( number < 10 ) {
317+ name = name . replace ( number . toString ( ) , "_" + number . toString ( ) ) ;
318+ used_nums [ number ] = true ;
319+ }
320+ }
321+ else
322+ {
323+ name = `${ name } (_${ i + 1 } )`
324+ used_nums [ i + 1 ] = true ;
325+ }
326+
327+ item = this . addAction ( ws_sub . menu , name , ( ) => window . change_workspace ( global . workspace_manager . get_workspace_by_index ( i ) ) )
191328
192329 if ( i == curr_index )
193330 item . setSensitive ( false ) ;
@@ -196,7 +333,9 @@ var WindowMenu = class extends PopupMenu.PopupMenu {
196333
197334 this . addMenuItem ( new PopupMenu . PopupSeparatorMenuItem ( ) ) ;
198335
199- item = this . addAction ( this , _ ( "Close" ) , event => {
336+ // Translators: If a language-specific mnemonic doesn't make sense, add one after the label itself:
337+ // i.e. <translated>(_n). See https://github.com/linuxmint/muffin/blob/b9a6f3fe43e/po .po files
338+ item = this . addAction ( this , _ ( "_Close" ) , event => {
200339 window . delete ( event . get_time ( ) ) ;
201340 } ) ;
202341 item . setIcon ( "window-close-symbolic" ) ;
0 commit comments