1 /* winmenu.c - command menu for windows
3 * Window Maker window manager
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include <X11/Xutil.h>
31 #include <X11/XKBlib.h>
33 #include "WindowMaker.h"
39 #include "application.h"
43 #include "workspace.h"
44 #include "winspector.h"
52 static WMenu
*makeWorkspaceMenu(WScreen
*scr
);
53 static WMenu
*makeOptionsMenu(WScreen
*scr
);
54 static WMenu
*makeMaximizeMenu(WScreen
*scr
);
57 * Define the Menu entry that will be present in the Window menu
59 * The order of this list defines the order in which they will appear;
60 * make sure to keep the structure below aligned with the list because
61 * the constant index is used in many places.
82 WMenu
*(*generate_submenu
)(WScreen
*scr
);
83 } window_menu_entries
[] = {
84 [MC_MAXIMIZE
] = { N_("Maximize"), NULL
},
85 [MC_OTHERMAX
] = { N_("Other maximization"), makeMaximizeMenu
},
86 [MC_MINIATURIZE
] = { N_("Miniaturize"), NULL
},
87 [MC_SHADE
] = { N_("Shade"), NULL
},
88 [MC_HIDE
] = { N_("Hide"), NULL
},
89 [MC_MOVERESIZE
] = { N_("Resize/Move"), NULL
},
90 [MC_SELECT
] = { N_("Select"), NULL
},
91 [MC_CHANGEWKSPC
] = { N_("Move To"), makeWorkspaceMenu
},
92 [MC_PROPERTIES
] = { N_("Attributes..."), NULL
},
93 [MC_OPTIONS
] = { N_("Options"), makeOptionsMenu
},
94 [MC_RELAUNCH
] = { N_("Launch"), NULL
},
95 [MC_CLOSE
] = { N_("Close"), NULL
},
96 [MC_KILL
] = { N_("Kill"), NULL
}
100 * Defines the menu entries for the Options sub-menu
102 * These options will be placed at the beginning of the menu, the rest will
103 * be populated with the Window Shortcut possibilities
112 static const char *const menu_options_entries
[] = {
113 [WO_KEEP_ON_TOP
] = N_("Keep on top"),
114 [WO_KEEP_AT_BOTTOM
] = N_("Keep at bottom"),
115 [WO_OMNIPRESENT
] = N_("Omnipresent")
119 * Defines the menu entries for the Other maximization sub-menu
121 static const struct {
122 unsigned int indicator
;
124 unsigned int shortcut_idx
;
126 } menu_maximize_entries
[] = {
127 { MI_SNAP_V
, N_("Vertical"), WKBD_VMAXIMIZE
, MAX_VERTICAL
},
128 { MI_SNAP_H
, N_("Horizontal"), WKBD_HMAXIMIZE
, MAX_HORIZONTAL
},
129 { MI_CENTRAL
, N_("Central"), WKBD_CENTRAL
, MAX_CENTRAL
},
130 { MI_SNAP_LH
, N_("Left half"), WKBD_LHMAXIMIZE
, MAX_VERTICAL
| MAX_LEFTHALF
},
131 { MI_SNAP_RH
, N_("Right half"), WKBD_RHMAXIMIZE
, MAX_VERTICAL
| MAX_RIGHTHALF
},
132 { MI_SNAP_TH
, N_("Top half"), WKBD_THMAXIMIZE
, MAX_HORIZONTAL
| MAX_TOPHALF
},
133 { MI_SNAP_BH
, N_("Bottom half"), WKBD_BHMAXIMIZE
, MAX_HORIZONTAL
| MAX_BOTTOMHALF
},
134 { MI_SNAP_TL
, N_("Top left"), WKBD_LTCMAXIMIZE
, MAX_LEFTHALF
| MAX_TOPHALF
},
135 { MI_SNAP_TR
, N_("Top right"), WKBD_RTCMAXIMIZE
, MAX_RIGHTHALF
| MAX_TOPHALF
},
136 { MI_SNAP_BL
, N_("Bottom left"), WKBD_LBCMAXIMIZE
, MAX_LEFTHALF
| MAX_BOTTOMHALF
},
137 { MI_SNAP_BR
, N_("Bottom right"), WKBD_RBCMAXIMIZE
, MAX_RIGHTHALF
| MAX_BOTTOMHALF
},
138 { MI_SNAP_TILED
, N_("Tiled"), WKBD_MAXIMUS
, MAX_MAXIMUS
}
141 static void updateOptionsMenu(WMenu
* menu
, WWindow
* wwin
);
143 static void execWindowOptionCommand(WMenu
* menu
, WMenuEntry
* entry
)
145 WWindow
*wwin
= (WWindow
*) entry
->clientdata
;
147 /* Parameter not used, but tell the compiler that it is ok */
150 switch (entry
->order
) {
152 if (wwin
->frame
->core
->stacking
->window_level
!= WMFloatingLevel
)
153 ChangeStackingLevel(wwin
->frame
->core
, WMFloatingLevel
);
155 ChangeStackingLevel(wwin
->frame
->core
, WMNormalLevel
);
158 case WO_KEEP_AT_BOTTOM
:
159 if (wwin
->frame
->core
->stacking
->window_level
!= WMSunkenLevel
)
160 ChangeStackingLevel(wwin
->frame
->core
, WMSunkenLevel
);
162 ChangeStackingLevel(wwin
->frame
->core
, WMNormalLevel
);
166 wWindowSetOmnipresent(wwin
, !wwin
->flags
.omnipresent
);
171 static void execMaximizeCommand(WMenu
* menu
, WMenuEntry
* entry
)
173 WWindow
*wwin
= (WWindow
*) entry
->clientdata
;
175 /* Parameter not used, but tell the compiler that it is ok */
178 handleMaximize(wwin
, menu_maximize_entries
[entry
->order
].maxim_direction
);
181 static void updateUnmaximizeShortcut(WMenuEntry
* entry
, int flags
)
185 switch (flags
& (MAX_HORIZONTAL
| MAX_VERTICAL
| MAX_LEFTHALF
| MAX_RIGHTHALF
| MAX_TOPHALF
| MAX_BOTTOMHALF
| MAX_MAXIMUS
| MAX_CENTRAL
)) {
187 key
= WKBD_HMAXIMIZE
;
191 key
= WKBD_VMAXIMIZE
;
198 case MAX_LEFTHALF
| MAX_VERTICAL
:
199 key
= WKBD_LHMAXIMIZE
;
202 case MAX_RIGHTHALF
| MAX_VERTICAL
:
203 key
= WKBD_RHMAXIMIZE
;
206 case MAX_TOPHALF
| MAX_HORIZONTAL
:
207 key
= WKBD_THMAXIMIZE
;
210 case MAX_BOTTOMHALF
| MAX_HORIZONTAL
:
211 key
= WKBD_BHMAXIMIZE
;
214 case MAX_LEFTHALF
| MAX_TOPHALF
:
215 key
= WKBD_LTCMAXIMIZE
;
218 case MAX_RIGHTHALF
| MAX_TOPHALF
:
219 key
= WKBD_RTCMAXIMIZE
;
222 case MAX_LEFTHALF
| MAX_BOTTOMHALF
:
223 key
= WKBD_LBCMAXIMIZE
;
226 case MAX_RIGHTHALF
| MAX_BOTTOMHALF
:
227 key
= WKBD_RBCMAXIMIZE
;
239 entry
->rtext
= GetShortcutKey(wKeyBindings
[key
]);
242 static void execMenuCommand(WMenu
* menu
, WMenuEntry
* entry
)
244 WWindow
*wwin
= (WWindow
*) entry
->clientdata
;
247 CloseWindowMenu(menu
->frame
->screen_ptr
);
249 switch (entry
->order
) {
251 /* send delete message */
252 wClientSendProtocol(wwin
, w_global
.atom
.wm
.delete_window
,
253 w_global
.timestamp
.last_event
);
258 if (wPreferences
.dont_confirm_kill
259 || wMessageDialog(menu
->frame
->screen_ptr
, _("Kill Application"),
261 ("This will kill the application.\nAny unsaved changes will be lost.\nPlease confirm."),
262 _("Yes"), _("No"), NULL
) == WAPRDefault
) {
263 if (!wwin
->flags
.destroyed
)
270 if (wwin
->flags
.miniaturized
) {
271 wDeiconifyWindow(wwin
);
273 if (wwin
->protocols
.MINIATURIZE_WINDOW
) {
274 wClientSendProtocol(wwin
, w_global
.atom
.gnustep
.wm_miniaturize_window
,
275 w_global
.timestamp
.last_event
);
277 wIconifyWindow(wwin
);
283 if (wwin
->flags
.maximized
)
284 wUnmaximizeWindow(wwin
);
286 wMaximizeWindow(wwin
, MAX_VERTICAL
| MAX_HORIZONTAL
,
287 wGetHeadForWindow(wwin
));
291 if (wwin
->flags
.shaded
)
292 wUnshadeWindow(wwin
);
298 if (!wwin
->flags
.miniaturized
)
299 wSelectWindow(wwin
, !wwin
->flags
.selected
);
301 wIconSelect(wwin
->icon
);
305 wKeyboardMoveResizeWindow(wwin
);
309 wShowInspectorForWindow(wwin
);
313 (void) RelaunchWindow(wwin
);
317 wapp
= wApplicationOf(wwin
->main_window
);
318 wHideApplication(wapp
);
323 static void switchWSCommand(WMenu
* menu
, WMenuEntry
* entry
)
325 WWindow
*wwin
= (WWindow
*) entry
->clientdata
;
327 /* Parameter not used, but tell the compiler that it is ok */
330 wSelectWindow(wwin
, False
);
331 wWindowChangeWorkspace(wwin
, entry
->order
);
334 static void makeShortcutCommand(WMenu
* menu
, WMenuEntry
* entry
)
336 WWindow
*wwin
= (WWindow
*) entry
->clientdata
;
337 WScreen
*scr
= wwin
->screen_ptr
;
338 int index
= entry
->order
- wlengthof(menu_options_entries
);
340 /* Parameter not used, but tell the compiler that it is ok */
343 if (scr
->shortcutWindows
[index
]) {
344 WMFreeArray(scr
->shortcutWindows
[index
]);
345 scr
->shortcutWindows
[index
] = NULL
;
348 if (wwin
->flags
.selected
&& scr
->selected_windows
) {
349 scr
->shortcutWindows
[index
] = WMDuplicateArray(scr
->selected_windows
);
350 /*WMRemoveFromArray(scr->shortcutWindows[index], wwin);
351 WMInsertInArray(scr->shortcutWindows[index], 0, wwin); */
353 scr
->shortcutWindows
[index
] = WMCreateArray(4);
354 WMAddToArray(scr
->shortcutWindows
[index
], wwin
);
357 wSelectWindow(wwin
, !wwin
->flags
.selected
);
360 wSelectWindow(wwin
, !wwin
->flags
.selected
);
364 static void updateWorkspaceMenu(WMenu
* menu
)
366 WScreen
*scr
= menu
->frame
->screen_ptr
;
367 char title
[MAX_WORKSPACENAME_WIDTH
+ 1];
371 for (i
= 0; i
< scr
->workspace_count
; i
++) {
372 if (i
< menu
->entry_no
) {
374 entry
= menu
->entries
[i
];
375 if (strcmp(entry
->text
, scr
->workspaces
[i
]->name
) != 0) {
377 strncpy(title
, scr
->workspaces
[i
]->name
, MAX_WORKSPACENAME_WIDTH
);
378 title
[MAX_WORKSPACENAME_WIDTH
] = 0;
379 menu
->entries
[i
]->text
= wstrdup(title
);
380 menu
->entries
[i
]->rtext
= GetShortcutKey(wKeyBindings
[WKBD_MOVE_WORKSPACE1
+ i
]);
381 menu
->flags
.realized
= 0;
384 strncpy(title
, scr
->workspaces
[i
]->name
, MAX_WORKSPACENAME_WIDTH
);
385 title
[MAX_WORKSPACENAME_WIDTH
] = 0;
387 entry
= wMenuAddCallback(menu
, title
, switchWSCommand
, NULL
);
388 entry
->rtext
= GetShortcutKey(wKeyBindings
[WKBD_MOVE_WORKSPACE1
+ i
]);
390 menu
->flags
.realized
= 0;
393 /* workspace shortcut labels */
394 if (i
/ 10 == scr
->current_workspace
/ 10)
395 entry
->rtext
= GetShortcutKey(wKeyBindings
[WKBD_MOVE_WORKSPACE1
+ (i
% 10)]);
400 if (!menu
->flags
.realized
)
404 static void updateMakeShortcutMenu(WMenu
* menu
, WWindow
* wwin
)
406 WMenu
*smenu
= menu
->cascades
[menu
->entries
[MC_OPTIONS
]->cascade
];
414 for (i
= wlengthof(menu_options_entries
); i
< smenu
->entry_no
; i
++) {
415 int shortcutNo
= i
- wlengthof(menu_options_entries
);
416 WMenuEntry
*entry
= smenu
->entries
[i
];
417 WMArray
*shortSelWindows
= wwin
->screen_ptr
->shortcutWindows
[shortcutNo
];
419 snprintf(buffer
, sizeof(buffer
), _("Set Shortcut %i"), shortcutNo
+ 1);
421 if (!shortSelWindows
) {
422 entry
->flags
.indicator_on
= 0;
424 entry
->flags
.indicator_on
= 1;
425 if (WMCountInArray(shortSelWindows
, wwin
))
426 entry
->flags
.indicator_type
= MI_DIAMOND
;
428 entry
->flags
.indicator_type
= MI_CHECK
;
431 if (strcmp(buffer
, entry
->text
) != 0) {
433 entry
->text
= wstrdup(buffer
);
434 smenu
->flags
.realized
= 0;
437 kcode
= wKeyBindings
[WKBD_WINDOW1
+ shortcutNo
].keycode
;
442 tmp
= GetShortcutKey(wKeyBindings
[WKBD_WINDOW1
+ shortcutNo
]);
444 if (entry
->rtext
!= NULL
) {
445 /* There was a shortcut, but there is no more */
448 smenu
->flags
.realized
= 0;
450 } else if (entry
->rtext
== NULL
) {
451 /* There was no shortcut, but there is one now */
453 smenu
->flags
.realized
= 0;
454 } else if (strcmp(tmp
, entry
->rtext
) != 0) {
455 /* There was a shortcut, but it has changed */
458 smenu
->flags
.realized
= 0;
460 /* There was a shortcut but it did not change */
463 wMenuSetEnabled(smenu
, i
, True
);
465 wMenuSetEnabled(smenu
, i
, False
);
469 smenu
->flags
.realized
= 0;
472 entry
->clientdata
= wwin
;
474 if (!smenu
->flags
.realized
)
478 static void updateOptionsMenu(WMenu
* menu
, WWindow
* wwin
)
480 WMenu
*smenu
= menu
->cascades
[menu
->entries
[MC_OPTIONS
]->cascade
];
482 /* keep on top check */
483 smenu
->entries
[WO_KEEP_ON_TOP
]->clientdata
= wwin
;
484 smenu
->entries
[WO_KEEP_ON_TOP
]->flags
.indicator_on
=
485 (wwin
->frame
->core
->stacking
->window_level
== WMFloatingLevel
) ? 1 : 0;
486 wMenuSetEnabled(smenu
, WO_KEEP_ON_TOP
, !wwin
->flags
.miniaturized
);
487 smenu
->entries
[WO_KEEP_ON_TOP
]->rtext
= GetShortcutKey(wKeyBindings
[WKBD_KEEP_ON_TOP
]);
489 /* keep at bottom check */
490 smenu
->entries
[WO_KEEP_AT_BOTTOM
]->clientdata
= wwin
;
491 smenu
->entries
[WO_KEEP_AT_BOTTOM
]->flags
.indicator_on
=
492 (wwin
->frame
->core
->stacking
->window_level
== WMSunkenLevel
) ? 1 : 0;
493 wMenuSetEnabled(smenu
, WO_KEEP_AT_BOTTOM
, !wwin
->flags
.miniaturized
);
494 smenu
->entries
[WO_KEEP_AT_BOTTOM
]->rtext
= GetShortcutKey(wKeyBindings
[WKBD_KEEP_AT_BOTTOM
]);
496 /* omnipresent check */
497 smenu
->entries
[WO_OMNIPRESENT
]->clientdata
= wwin
;
498 smenu
->entries
[WO_OMNIPRESENT
]->flags
.indicator_on
= IS_OMNIPRESENT(wwin
);
499 smenu
->entries
[WO_OMNIPRESENT
]->rtext
= GetShortcutKey(wKeyBindings
[WKBD_OMNIPRESENT
]);
501 smenu
->flags
.realized
= 0;
505 static void updateMaximizeMenu(WMenu
* menu
, WWindow
* wwin
)
507 WMenu
*smenu
= menu
->cascades
[menu
->entries
[MC_OTHERMAX
]->cascade
];
510 for (i
= 0; i
< smenu
->entry_no
; i
++) {
511 smenu
->entries
[i
]->clientdata
= wwin
;
512 smenu
->entries
[i
]->rtext
= GetShortcutKey(wKeyBindings
[menu_maximize_entries
[i
].shortcut_idx
]);
515 smenu
->flags
.realized
= 0;
519 static WMenu
*makeWorkspaceMenu(WScreen
* scr
)
523 menu
= wMenuCreate(scr
, NULL
, False
);
525 wwarning(_("could not create submenu for window menu"));
529 updateWorkspaceMenu(menu
);
532 * The Workspace Menu is made visible in the screen structure because
533 * it is updated when there is a change on workspaces. This was done
534 * to be efficient, avoiding re-generating completely the window menu
535 * and its sub-menus every time it is needed.
537 scr
->workspace_submenu
= menu
;
542 static WMenu
*makeOptionsMenu(WScreen
* scr
)
548 menu
= wMenuCreate(scr
, NULL
, False
);
550 wwarning(_("could not create submenu for window menu"));
554 for (i
= 0; i
< wlengthof(menu_options_entries
); i
++) {
555 entry
= wMenuAddCallback(menu
, _(menu_options_entries
[i
]), execWindowOptionCommand
, NULL
);
556 entry
->flags
.indicator
= 1;
557 entry
->flags
.indicator_type
= MI_CHECK
;
560 for (i
= 0; i
< MAX_WINDOW_SHORTCUTS
; i
++) {
561 entry
= wMenuAddCallback(menu
, "", makeShortcutCommand
, NULL
);
562 entry
->flags
.indicator
= 1;
568 static WMenu
*makeMaximizeMenu(WScreen
* scr
)
574 menu
= wMenuCreate(scr
, NULL
, False
);
576 wwarning(_("could not create submenu for window menu"));
580 for (i
= 0; i
< wlengthof(menu_maximize_entries
); i
++) {
581 entry
= wMenuAddCallback(menu
, _(menu_maximize_entries
[i
].label
), execMaximizeCommand
, NULL
);
582 entry
->flags
.indicator
= entry
->flags
.indicator_on
= 1;
583 entry
->flags
.indicator_type
= menu_maximize_entries
[i
].indicator
;
589 static WMenu
*createWindowMenu(WScreen
* scr
)
594 menu
= wMenuCreate(scr
, NULL
, False
);
596 for (i
= 0; i
< wlengthof(window_menu_entries
); i
++) {
599 entry
= wMenuAddCallback(menu
, _(window_menu_entries
[i
].label
),
600 (window_menu_entries
[i
].generate_submenu
== NULL
)?execMenuCommand
:NULL
,
602 if (window_menu_entries
[i
].generate_submenu
!= NULL
) {
605 submenu
= window_menu_entries
[i
].generate_submenu(scr
);
606 wMenuEntrySetCascade(menu
, entry
, submenu
);
613 void CloseWindowMenu(WScreen
* scr
)
615 if (scr
->window_menu
) {
616 if (scr
->window_menu
->flags
.mapped
)
617 wMenuUnmap(scr
->window_menu
);
619 if (scr
->window_menu
->entries
[0]->clientdata
) {
620 WWindow
*wwin
= (WWindow
*) scr
->window_menu
->entries
[0]->clientdata
;
622 wwin
->flags
.menu_open_for_me
= 0;
624 scr
->window_menu
->entries
[0]->clientdata
= NULL
;
628 static void updateMenuForWindow(WMenu
* menu
, WWindow
* wwin
)
630 WApplication
*wapp
= wApplicationOf(wwin
->main_window
);
631 WScreen
*scr
= wwin
->screen_ptr
;
634 updateOptionsMenu(menu
, wwin
);
635 updateMaximizeMenu(menu
, wwin
);
637 updateMakeShortcutMenu(menu
, wwin
);
639 wMenuSetEnabled(menu
, MC_HIDE
, wapp
!= NULL
&& !WFLAGP(wapp
->main_window_desc
, no_appicon
));
641 wMenuSetEnabled(menu
, MC_CLOSE
, (wwin
->protocols
.DELETE_WINDOW
&& !WFLAGP(wwin
, no_closable
)));
643 if (wwin
->flags
.miniaturized
) {
644 static char *text
= NULL
;
646 text
= _("Deminiaturize");
648 menu
->entries
[MC_MINIATURIZE
]->text
= text
;
650 static char *text
= NULL
;
652 text
= _("Miniaturize");
654 menu
->entries
[MC_MINIATURIZE
]->text
= text
;
657 wMenuSetEnabled(menu
, MC_MINIATURIZE
, !WFLAGP(wwin
, no_miniaturizable
));
659 if (wwin
->flags
.maximized
) {
660 static char *text
= NULL
;
662 text
= _("Unmaximize");
664 menu
->entries
[MC_MAXIMIZE
]->text
= text
;
665 updateUnmaximizeShortcut(menu
->entries
[MC_MAXIMIZE
], wwin
->flags
.maximized
);
667 static char *text
= NULL
;
669 text
= _("Maximize");
671 menu
->entries
[MC_MAXIMIZE
]->text
= text
;
672 menu
->entries
[MC_MAXIMIZE
]->rtext
= GetShortcutKey(wKeyBindings
[WKBD_MAXIMIZE
]);
674 wMenuSetEnabled(menu
, MC_MAXIMIZE
, IS_RESIZABLE(wwin
));
676 wMenuSetEnabled(menu
, MC_MOVERESIZE
, IS_RESIZABLE(wwin
)
677 && !wwin
->flags
.miniaturized
);
679 if (wwin
->flags
.shaded
) {
680 static char *text
= NULL
;
684 menu
->entries
[MC_SHADE
]->text
= text
;
686 static char *text
= NULL
;
690 menu
->entries
[MC_SHADE
]->text
= text
;
693 wMenuSetEnabled(menu
, MC_SHADE
, !WFLAGP(wwin
, no_shadeable
)
694 && !wwin
->flags
.miniaturized
);
696 if (wwin
->flags
.selected
) {
697 static char *text
= NULL
;
699 text
= _("Deselect");
701 menu
->entries
[MC_SELECT
]->text
= text
;
703 static char *text
= NULL
;
707 menu
->entries
[MC_SELECT
]->text
= text
;
710 wMenuSetEnabled(menu
, MC_CHANGEWKSPC
, !IS_OMNIPRESENT(wwin
));
712 if (!wwin
->flags
.inspector_open
) {
713 wMenuSetEnabled(menu
, MC_PROPERTIES
, True
);
715 wMenuSetEnabled(menu
, MC_PROPERTIES
, False
);
718 /* Update shortcut labels except for (Un)Maximize which is
719 * handled separately.
721 menu
->entries
[MC_MINIATURIZE
]->rtext
= GetShortcutKey(wKeyBindings
[WKBD_MINIATURIZE
]);
722 menu
->entries
[MC_SHADE
]->rtext
= GetShortcutKey(wKeyBindings
[WKBD_SHADE
]);
723 menu
->entries
[MC_HIDE
]->rtext
= GetShortcutKey(wKeyBindings
[WKBD_HIDE
]);
724 menu
->entries
[MC_MOVERESIZE
]->rtext
= GetShortcutKey(wKeyBindings
[WKBD_MOVERESIZE
]);
725 menu
->entries
[MC_SELECT
]->rtext
= GetShortcutKey(wKeyBindings
[WKBD_SELECT
]);
726 menu
->entries
[MC_RELAUNCH
]->rtext
= GetShortcutKey(wKeyBindings
[WKBD_RELAUNCH
]);
727 menu
->entries
[MC_CLOSE
]->rtext
= GetShortcutKey(wKeyBindings
[WKBD_CLOSE
]);
729 /* set the client data of the entries to the window */
730 for (i
= 0; i
< menu
->entry_no
; i
++) {
731 menu
->entries
[i
]->clientdata
= wwin
;
734 for (i
= 0; i
< scr
->workspace_submenu
->entry_no
; i
++) {
735 scr
->workspace_submenu
->entries
[i
]->clientdata
= wwin
;
736 if (i
== scr
->current_workspace
)
737 wMenuSetEnabled(scr
->workspace_submenu
, i
, False
);
739 wMenuSetEnabled(scr
->workspace_submenu
, i
, True
);
742 menu
->flags
.realized
= 0;
746 static WMenu
*open_window_menu_core(WWindow
*wwin
)
748 WScreen
*scr
= wwin
->screen_ptr
;
751 wwin
->flags
.menu_open_for_me
= 1;
753 if (!scr
->window_menu
) {
754 scr
->window_menu
= createWindowMenu(scr
);
756 /* hack to save some memory allocation/deallocation */
757 wfree(scr
->window_menu
->entries
[MC_MINIATURIZE
]->text
);
758 wfree(scr
->window_menu
->entries
[MC_MAXIMIZE
]->text
);
759 wfree(scr
->window_menu
->entries
[MC_SHADE
]->text
);
760 wfree(scr
->window_menu
->entries
[MC_SELECT
]->text
);
762 updateWorkspaceMenu(scr
->workspace_submenu
);
765 menu
= scr
->window_menu
;
766 if (menu
->flags
.mapped
) {
768 if (menu
->entries
[0]->clientdata
== wwin
)
772 updateMenuForWindow(menu
, wwin
);
777 static void prepare_menu_position(WMenu
*menu
, int *x
, int *y
)
781 rect
= wGetRectForHead(menu
->frame
->screen_ptr
,
782 wGetHeadForPointerLocation(menu
->frame
->screen_ptr
));
783 if (*x
< rect
.pos
.x
- menu
->frame
->core
->width
/ 2)
784 *x
= rect
.pos
.x
- menu
->frame
->core
->width
/ 2;
789 void OpenWindowMenu(WWindow
*wwin
, int x
, int y
, int keyboard
)
793 menu
= open_window_menu_core(wwin
);
797 /* Specific menu position */
798 x
-= menu
->frame
->core
->width
/ 2;
799 if (x
+ menu
->frame
->core
->width
> wwin
->frame_x
+ wwin
->frame
->core
->width
)
800 x
= wwin
->frame_x
+ wwin
->frame
->core
->width
- menu
->frame
->core
->width
;
801 if (x
< wwin
->frame_x
)
804 /* Common menu position */
805 prepare_menu_position(menu
, &x
, &y
);
807 if (!wwin
->flags
.internal_window
)
808 wMenuMapAt(menu
, x
, y
, keyboard
);
811 void OpenWindowMenu2(WWindow
*wwin
, int x
, int y
, int keyboard
)
815 WScreen
*scr
= wwin
->screen_ptr
;
817 menu
= open_window_menu_core(wwin
);
821 /* Specific menu position */
822 for (i
= 0; i
< scr
->workspace_submenu
->entry_no
; i
++) {
823 scr
->workspace_submenu
->entries
[i
]->clientdata
= wwin
;
824 wMenuSetEnabled(scr
->workspace_submenu
, i
, True
);
827 x
-= menu
->frame
->core
->width
/ 2;
829 /* Common menu position */
830 prepare_menu_position(menu
, &x
, &y
);
832 if (!wwin
->flags
.internal_window
)
833 wMenuMapAt(menu
, x
, y
, keyboard
);
836 void OpenMiniwindowMenu(WWindow
* wwin
, int x
, int y
)
840 menu
= open_window_menu_core(wwin
);
844 x
-= menu
->frame
->core
->width
/ 2;
846 wMenuMapAt(menu
, x
, y
, False
);
849 void DestroyWindowMenu(WScreen
*scr
)
851 if (scr
->window_menu
) {
852 scr
->window_menu
->entries
[MC_MINIATURIZE
]->text
= NULL
;
853 scr
->window_menu
->entries
[MC_MAXIMIZE
]->text
= NULL
;
854 scr
->window_menu
->entries
[MC_SHADE
]->text
= NULL
;
855 scr
->window_menu
->entries
[MC_SELECT
]->text
= NULL
;
856 wMenuDestroy(scr
->window_menu
, True
);
857 scr
->window_menu
= NULL
;