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"
78 unsigned int shortcut_idx
;
80 } menu_maximize_entries
[] = {
81 { N_("Maximize vertically"), WKBD_VMAXIMIZE
, MAX_VERTICAL
},
82 { N_("Maximize horizontally"), WKBD_HMAXIMIZE
, MAX_HORIZONTAL
},
83 { N_("Maximize left half"), WKBD_LHMAXIMIZE
, MAX_VERTICAL
| MAX_LEFTHALF
},
84 { N_("Maximize right half"), WKBD_RHMAXIMIZE
, MAX_VERTICAL
| MAX_RIGHTHALF
},
85 { N_("Maximize top half"), WKBD_THMAXIMIZE
, MAX_HORIZONTAL
| MAX_TOPHALF
},
86 { N_("Maximize bottom half"), WKBD_BHMAXIMIZE
, MAX_HORIZONTAL
| MAX_BOTTOMHALF
},
87 { N_("Maximize left top corner"), WKBD_LTCMAXIMIZE
, MAX_LEFTHALF
| MAX_TOPHALF
},
88 { N_("Maximize right top corner"), WKBD_RTCMAXIMIZE
, MAX_RIGHTHALF
| MAX_TOPHALF
},
89 { N_("Maximize left bottom corner"), WKBD_LBCMAXIMIZE
, MAX_LEFTHALF
| MAX_BOTTOMHALF
},
90 { N_("Maximize right bottom corner"), WKBD_RBCMAXIMIZE
, MAX_RIGHTHALF
| MAX_BOTTOMHALF
},
91 { N_("Maximus: tiled maximization"), WKBD_MAXIMUS
, MAX_MAXIMUS
}
94 static void updateOptionsMenu(WMenu
* menu
, WWindow
* wwin
);
96 static void execWindowOptionCommand(WMenu
* menu
, WMenuEntry
* entry
)
98 WWindow
*wwin
= (WWindow
*) entry
->clientdata
;
100 /* Parameter not used, but tell the compiler that it is ok */
103 switch (entry
->order
) {
105 if (wwin
->frame
->core
->stacking
->window_level
!= WMFloatingLevel
)
106 ChangeStackingLevel(wwin
->frame
->core
, WMFloatingLevel
);
108 ChangeStackingLevel(wwin
->frame
->core
, WMNormalLevel
);
111 case WO_KEEP_AT_BOTTOM
:
112 if (wwin
->frame
->core
->stacking
->window_level
!= WMSunkenLevel
)
113 ChangeStackingLevel(wwin
->frame
->core
, WMSunkenLevel
);
115 ChangeStackingLevel(wwin
->frame
->core
, WMNormalLevel
);
119 wWindowSetOmnipresent(wwin
, !wwin
->flags
.omnipresent
);
124 static void execMaximizeCommand(WMenu
* menu
, WMenuEntry
* entry
)
126 WWindow
*wwin
= (WWindow
*) entry
->clientdata
;
128 /* Parameter not used, but tell the compiler that it is ok */
131 handleMaximize(wwin
, menu_maximize_entries
[entry
->order
].maxim_direction
);
134 static void updateUnmaximizeShortcut(WMenuEntry
* entry
, int flags
)
138 switch (flags
& (MAX_HORIZONTAL
| MAX_VERTICAL
| MAX_LEFTHALF
| MAX_RIGHTHALF
| MAX_TOPHALF
| MAX_BOTTOMHALF
| MAX_MAXIMUS
)) {
140 key
= WKBD_HMAXIMIZE
;
144 key
= WKBD_VMAXIMIZE
;
147 case MAX_LEFTHALF
| MAX_VERTICAL
:
148 key
= WKBD_LHMAXIMIZE
;
151 case MAX_RIGHTHALF
| MAX_VERTICAL
:
152 key
= WKBD_RHMAXIMIZE
;
155 case MAX_TOPHALF
| MAX_HORIZONTAL
:
156 key
= WKBD_THMAXIMIZE
;
159 case MAX_BOTTOMHALF
| MAX_HORIZONTAL
:
160 key
= WKBD_BHMAXIMIZE
;
163 case MAX_LEFTHALF
| MAX_TOPHALF
:
164 key
= WKBD_LTCMAXIMIZE
;
167 case MAX_RIGHTHALF
| MAX_TOPHALF
:
168 key
= WKBD_RTCMAXIMIZE
;
171 case MAX_LEFTHALF
| MAX_BOTTOMHALF
:
172 key
= WKBD_LBCMAXIMIZE
;
175 case MAX_RIGHTHALF
| MAX_BOTTOMHALF
:
176 key
= WKBD_RBCMAXIMIZE
;
188 entry
->rtext
= GetShortcutKey(wKeyBindings
[key
]);
191 static void execMenuCommand(WMenu
* menu
, WMenuEntry
* entry
)
193 WWindow
*wwin
= (WWindow
*) entry
->clientdata
;
196 CloseWindowMenu(menu
->frame
->screen_ptr
);
198 switch (entry
->order
) {
200 /* send delete message */
201 wClientSendProtocol(wwin
, w_global
.atom
.wm
.delete_window
,
202 w_global
.timestamp
.last_event
);
207 if (wPreferences
.dont_confirm_kill
208 || wMessageDialog(menu
->frame
->screen_ptr
, _("Kill Application"),
210 ("This will kill the application.\nAny unsaved changes will be lost.\nPlease confirm."),
211 _("Yes"), _("No"), NULL
) == WAPRDefault
) {
212 if (!wwin
->flags
.destroyed
)
219 if (wwin
->flags
.miniaturized
) {
220 wDeiconifyWindow(wwin
);
222 if (wwin
->protocols
.MINIATURIZE_WINDOW
) {
223 wClientSendProtocol(wwin
, w_global
.atom
.gnustep
.wm_miniaturize_window
,
224 w_global
.timestamp
.last_event
);
226 wIconifyWindow(wwin
);
232 if (wwin
->flags
.maximized
)
233 wUnmaximizeWindow(wwin
);
235 wMaximizeWindow(wwin
, MAX_VERTICAL
| MAX_HORIZONTAL
);
239 if (wwin
->flags
.shaded
)
240 wUnshadeWindow(wwin
);
246 if (!wwin
->flags
.miniaturized
)
247 wSelectWindow(wwin
, !wwin
->flags
.selected
);
249 wIconSelect(wwin
->icon
);
253 wKeyboardMoveResizeWindow(wwin
);
257 wShowInspectorForWindow(wwin
);
261 (void) RelaunchWindow(wwin
);
265 wapp
= wApplicationOf(wwin
->main_window
);
266 wHideApplication(wapp
);
271 static void switchWSCommand(WMenu
* menu
, WMenuEntry
* entry
)
273 WWindow
*wwin
= (WWindow
*) entry
->clientdata
;
275 /* Parameter not used, but tell the compiler that it is ok */
278 wSelectWindow(wwin
, False
);
279 wWindowChangeWorkspace(wwin
, entry
->order
);
282 static void makeShortcutCommand(WMenu
* menu
, WMenuEntry
* entry
)
284 WWindow
*wwin
= (WWindow
*) entry
->clientdata
;
285 WScreen
*scr
= wwin
->screen_ptr
;
286 int index
= entry
->order
- WO_ENTRIES
;
288 /* Parameter not used, but tell the compiler that it is ok */
291 if (scr
->shortcutWindows
[index
]) {
292 WMFreeArray(scr
->shortcutWindows
[index
]);
293 scr
->shortcutWindows
[index
] = NULL
;
296 if (wwin
->flags
.selected
&& scr
->selected_windows
) {
297 scr
->shortcutWindows
[index
] = WMDuplicateArray(scr
->selected_windows
);
298 /*WMRemoveFromArray(scr->shortcutWindows[index], wwin);
299 WMInsertInArray(scr->shortcutWindows[index], 0, wwin); */
301 scr
->shortcutWindows
[index
] = WMCreateArray(4);
302 WMAddToArray(scr
->shortcutWindows
[index
], wwin
);
305 wSelectWindow(wwin
, !wwin
->flags
.selected
);
308 wSelectWindow(wwin
, !wwin
->flags
.selected
);
312 static void updateWorkspaceMenu(WMenu
* menu
)
314 WScreen
*scr
= menu
->frame
->screen_ptr
;
315 char title
[MAX_WORKSPACENAME_WIDTH
+ 1];
319 for (i
= 0; i
< scr
->workspace_count
; i
++) {
320 if (i
< menu
->entry_no
) {
322 entry
= menu
->entries
[i
];
323 if (strcmp(entry
->text
, scr
->workspaces
[i
]->name
) != 0) {
325 strncpy(title
, scr
->workspaces
[i
]->name
, MAX_WORKSPACENAME_WIDTH
);
326 title
[MAX_WORKSPACENAME_WIDTH
] = 0;
327 menu
->entries
[i
]->text
= wstrdup(title
);
328 menu
->entries
[i
]->rtext
= GetShortcutKey(wKeyBindings
[WKBD_MOVE_WORKSPACE1
+ i
]);
329 menu
->flags
.realized
= 0;
332 strncpy(title
, scr
->workspaces
[i
]->name
, MAX_WORKSPACENAME_WIDTH
);
333 title
[MAX_WORKSPACENAME_WIDTH
] = 0;
335 entry
= wMenuAddCallback(menu
, title
, switchWSCommand
, NULL
);
336 entry
->rtext
= GetShortcutKey(wKeyBindings
[WKBD_MOVE_WORKSPACE1
+ i
]);
338 menu
->flags
.realized
= 0;
341 /* workspace shortcut labels */
342 if (i
/ 10 == scr
->current_workspace
/ 10)
343 entry
->rtext
= GetShortcutKey(wKeyBindings
[WKBD_MOVE_WORKSPACE1
+ (i
% 10)]);
348 if (!menu
->flags
.realized
)
352 static void updateMakeShortcutMenu(WMenu
* menu
, WWindow
* wwin
)
354 WMenu
*smenu
= menu
->cascades
[menu
->entries
[MC_OPTIONS
]->cascade
];
363 buflen
= strlen(_("Set Shortcut")) + 16;
364 buffer
= wmalloc(buflen
);
366 for (i
= WO_ENTRIES
; i
< smenu
->entry_no
; i
++) {
367 int shortcutNo
= i
- WO_ENTRIES
;
368 WMenuEntry
*entry
= smenu
->entries
[i
];
369 WMArray
*shortSelWindows
= wwin
->screen_ptr
->shortcutWindows
[shortcutNo
];
371 snprintf(buffer
, buflen
, "%s %i", _("Set Shortcut"), shortcutNo
+ 1);
373 if (!shortSelWindows
) {
374 entry
->flags
.indicator_on
= 0;
376 entry
->flags
.indicator_on
= 1;
377 if (WMCountInArray(shortSelWindows
, wwin
))
378 entry
->flags
.indicator_type
= MI_DIAMOND
;
380 entry
->flags
.indicator_type
= MI_CHECK
;
383 if (strcmp(buffer
, entry
->text
) != 0) {
385 entry
->text
= wstrdup(buffer
);
386 smenu
->flags
.realized
= 0;
389 kcode
= wKeyBindings
[WKBD_WINDOW1
+ shortcutNo
].keycode
;
394 tmp
= GetShortcutKey(wKeyBindings
[WKBD_WINDOW1
+ shortcutNo
]);
396 if (entry
->rtext
!= NULL
) {
397 /* There was a shortcut, but there is no more */
400 smenu
->flags
.realized
= 0;
402 } else if (entry
->rtext
== NULL
) {
403 /* There was no shortcut, but there is one now */
405 smenu
->flags
.realized
= 0;
406 } else if (strcmp(tmp
, entry
->rtext
) != 0) {
407 /* There was a shortcut, but it has changed */
410 smenu
->flags
.realized
= 0;
412 /* There was a shortcut but it did not change */
415 wMenuSetEnabled(smenu
, i
, True
);
417 wMenuSetEnabled(smenu
, i
, False
);
421 smenu
->flags
.realized
= 0;
424 entry
->clientdata
= wwin
;
427 if (!smenu
->flags
.realized
)
431 static void updateOptionsMenu(WMenu
* menu
, WWindow
* wwin
)
433 WMenu
*smenu
= menu
->cascades
[menu
->entries
[MC_OPTIONS
]->cascade
];
435 /* keep on top check */
436 smenu
->entries
[WO_KEEP_ON_TOP
]->clientdata
= wwin
;
437 smenu
->entries
[WO_KEEP_ON_TOP
]->flags
.indicator_on
=
438 (wwin
->frame
->core
->stacking
->window_level
== WMFloatingLevel
) ? 1 : 0;
439 wMenuSetEnabled(smenu
, WO_KEEP_ON_TOP
, !wwin
->flags
.miniaturized
);
441 /* keep at bottom check */
442 smenu
->entries
[WO_KEEP_AT_BOTTOM
]->clientdata
= wwin
;
443 smenu
->entries
[WO_KEEP_AT_BOTTOM
]->flags
.indicator_on
=
444 (wwin
->frame
->core
->stacking
->window_level
== WMSunkenLevel
) ? 1 : 0;
445 wMenuSetEnabled(smenu
, WO_KEEP_AT_BOTTOM
, !wwin
->flags
.miniaturized
);
447 /* omnipresent check */
448 smenu
->entries
[WO_OMNIPRESENT
]->clientdata
= wwin
;
449 smenu
->entries
[WO_OMNIPRESENT
]->flags
.indicator_on
= IS_OMNIPRESENT(wwin
);
451 smenu
->flags
.realized
= 0;
455 static void updateMaximizeMenu(WMenu
* menu
, WWindow
* wwin
)
457 WMenu
*smenu
= menu
->cascades
[menu
->entries
[MC_OTHERMAX
]->cascade
];
460 for (i
= 0; i
< smenu
->entry_no
; i
++) {
461 smenu
->entries
[i
]->clientdata
= wwin
;
462 smenu
->entries
[i
]->rtext
= GetShortcutKey(wKeyBindings
[menu_maximize_entries
[i
].shortcut_idx
]);
465 smenu
->flags
.realized
= 0;
469 static WMenu
*makeWorkspaceMenu(WScreen
* scr
)
473 menu
= wMenuCreate(scr
, NULL
, False
);
475 wwarning(_("could not create submenu for window menu"));
479 updateWorkspaceMenu(menu
);
484 static WMenu
*makeMakeShortcutMenu(WMenu
* menu
)
488 for (i
= 0; i
< MAX_WINDOW_SHORTCUTS
; i
++) {
490 entry
= wMenuAddCallback(menu
, "", makeShortcutCommand
, NULL
);
492 entry
->flags
.indicator
= 1;
498 static WMenu
*makeOptionsMenu(WScreen
* scr
)
503 menu
= wMenuCreate(scr
, NULL
, False
);
505 wwarning(_("could not create submenu for window menu"));
509 entry
= wMenuAddCallback(menu
, _("Keep on top"), execWindowOptionCommand
, NULL
);
510 entry
->flags
.indicator
= 1;
511 entry
->flags
.indicator_type
= MI_CHECK
;
513 entry
= wMenuAddCallback(menu
, _("Keep at bottom"), execWindowOptionCommand
, NULL
);
514 entry
->flags
.indicator
= 1;
515 entry
->flags
.indicator_type
= MI_CHECK
;
517 entry
= wMenuAddCallback(menu
, _("Omnipresent"), execWindowOptionCommand
, NULL
);
518 entry
->flags
.indicator
= 1;
519 entry
->flags
.indicator_type
= MI_CHECK
;
524 static WMenu
*makeMaximizeMenu(WScreen
* scr
)
529 menu
= wMenuCreate(scr
, NULL
, False
);
531 wwarning(_("could not create submenu for window menu"));
535 for (i
= 0; i
< wlengthof(menu_maximize_entries
); i
++)
536 wMenuAddCallback(menu
, _(menu_maximize_entries
[i
].label
), execMaximizeCommand
, NULL
);
541 static WMenu
*createWindowMenu(WScreen
* scr
)
546 menu
= wMenuCreate(scr
, NULL
, False
);
548 * Warning: If you make some change that affects the order of the
549 * entries, you must update the command enum in the top of
552 entry
= wMenuAddCallback(menu
, _("Maximize"), execMenuCommand
, NULL
);
554 entry
= wMenuAddCallback(menu
, _("Other maximization"), NULL
, NULL
);
555 wMenuEntrySetCascade(menu
, entry
, makeMaximizeMenu(scr
));
557 entry
= wMenuAddCallback(menu
, _("Miniaturize"), execMenuCommand
, NULL
);
559 entry
= wMenuAddCallback(menu
, _("Shade"), execMenuCommand
, NULL
);
561 entry
= wMenuAddCallback(menu
, _("Hide"), execMenuCommand
, NULL
);
563 entry
= wMenuAddCallback(menu
, _("Resize/Move"), execMenuCommand
, NULL
);
565 entry
= wMenuAddCallback(menu
, _("Select"), execMenuCommand
, NULL
);
567 entry
= wMenuAddCallback(menu
, _("Move To"), NULL
, NULL
);
568 scr
->workspace_submenu
= makeWorkspaceMenu(scr
);
569 if (scr
->workspace_submenu
)
570 wMenuEntrySetCascade(menu
, entry
, scr
->workspace_submenu
);
572 entry
= wMenuAddCallback(menu
, _("Attributes..."), execMenuCommand
, NULL
);
574 entry
= wMenuAddCallback(menu
, _("Options"), NULL
, NULL
);
575 wMenuEntrySetCascade(menu
, entry
, makeMakeShortcutMenu(makeOptionsMenu(scr
)));
578 entry = wMenuAddCallback(menu, _("Select Shortcut"), NULL, NULL);
579 wMenuEntrySetCascade(menu, entry, makeMakeShortcutMenu(scr));
582 entry
= wMenuAddCallback(menu
, _("Launch"), execMenuCommand
, NULL
);
584 entry
= wMenuAddCallback(menu
, _("Close"), execMenuCommand
, NULL
);
586 entry
= wMenuAddCallback(menu
, _("Kill"), execMenuCommand
, NULL
);
591 void CloseWindowMenu(WScreen
* scr
)
593 if (scr
->window_menu
) {
594 if (scr
->window_menu
->flags
.mapped
)
595 wMenuUnmap(scr
->window_menu
);
597 if (scr
->window_menu
->entries
[0]->clientdata
) {
598 WWindow
*wwin
= (WWindow
*) scr
->window_menu
->entries
[0]->clientdata
;
600 wwin
->flags
.menu_open_for_me
= 0;
602 scr
->window_menu
->entries
[0]->clientdata
= NULL
;
606 static void updateMenuForWindow(WMenu
* menu
, WWindow
* wwin
)
608 WApplication
*wapp
= wApplicationOf(wwin
->main_window
);
609 WScreen
*scr
= wwin
->screen_ptr
;
612 updateOptionsMenu(menu
, wwin
);
613 updateMaximizeMenu(menu
, wwin
);
615 updateMakeShortcutMenu(menu
, wwin
);
617 wMenuSetEnabled(menu
, MC_HIDE
, wapp
!= NULL
&& !WFLAGP(wapp
->main_window_desc
, no_appicon
));
619 wMenuSetEnabled(menu
, MC_CLOSE
, (wwin
->protocols
.DELETE_WINDOW
&& !WFLAGP(wwin
, no_closable
)));
621 if (wwin
->flags
.miniaturized
) {
622 static char *text
= NULL
;
624 text
= _("Deminiaturize");
626 menu
->entries
[MC_MINIATURIZE
]->text
= text
;
628 static char *text
= NULL
;
630 text
= _("Miniaturize");
632 menu
->entries
[MC_MINIATURIZE
]->text
= text
;
635 wMenuSetEnabled(menu
, MC_MINIATURIZE
, !WFLAGP(wwin
, no_miniaturizable
));
637 if (wwin
->flags
.maximized
) {
638 static char *text
= NULL
;
640 text
= _("Unmaximize");
642 menu
->entries
[MC_MAXIMIZE
]->text
= text
;
643 updateUnmaximizeShortcut(menu
->entries
[MC_MAXIMIZE
], wwin
->flags
.maximized
);
645 static char *text
= NULL
;
647 text
= _("Maximize");
649 menu
->entries
[MC_MAXIMIZE
]->text
= text
;
650 menu
->entries
[MC_MAXIMIZE
]->rtext
= GetShortcutKey(wKeyBindings
[WKBD_MAXIMIZE
]);
652 wMenuSetEnabled(menu
, MC_MAXIMIZE
, IS_RESIZABLE(wwin
));
654 wMenuSetEnabled(menu
, MC_MOVERESIZE
, IS_RESIZABLE(wwin
)
655 && !wwin
->flags
.miniaturized
);
657 if (wwin
->flags
.shaded
) {
658 static char *text
= NULL
;
662 menu
->entries
[MC_SHADE
]->text
= text
;
664 static char *text
= NULL
;
668 menu
->entries
[MC_SHADE
]->text
= text
;
671 wMenuSetEnabled(menu
, MC_SHADE
, !WFLAGP(wwin
, no_shadeable
)
672 && !wwin
->flags
.miniaturized
);
674 if (wwin
->flags
.selected
) {
675 static char *text
= NULL
;
677 text
= _("Deselect");
679 menu
->entries
[MC_SELECT
]->text
= text
;
681 static char *text
= NULL
;
685 menu
->entries
[MC_SELECT
]->text
= text
;
688 wMenuSetEnabled(menu
, MC_DUMMY_MOVETO
, !IS_OMNIPRESENT(wwin
));
690 if (!wwin
->flags
.inspector_open
) {
691 wMenuSetEnabled(menu
, MC_PROPERTIES
, True
);
693 wMenuSetEnabled(menu
, MC_PROPERTIES
, False
);
696 /* Update shortcut labels except for (Un)Maximize which is
697 * handled separately.
699 menu
->entries
[MC_MINIATURIZE
]->rtext
= GetShortcutKey(wKeyBindings
[WKBD_MINIATURIZE
]);
700 menu
->entries
[MC_SHADE
]->rtext
= GetShortcutKey(wKeyBindings
[WKBD_SHADE
]);
701 menu
->entries
[MC_HIDE
]->rtext
= GetShortcutKey(wKeyBindings
[WKBD_HIDE
]);
702 menu
->entries
[MC_MOVERESIZE
]->rtext
= GetShortcutKey(wKeyBindings
[WKBD_MOVERESIZE
]);
703 menu
->entries
[MC_SELECT
]->rtext
= GetShortcutKey(wKeyBindings
[WKBD_SELECT
]);
704 menu
->entries
[MC_RELAUNCH
]->rtext
= GetShortcutKey(wKeyBindings
[WKBD_RELAUNCH
]);
705 menu
->entries
[MC_CLOSE
]->rtext
= GetShortcutKey(wKeyBindings
[WKBD_CLOSE
]);
707 /* set the client data of the entries to the window */
708 for (i
= 0; i
< menu
->entry_no
; i
++) {
709 menu
->entries
[i
]->clientdata
= wwin
;
712 for (i
= 0; i
< scr
->workspace_submenu
->entry_no
; i
++) {
713 scr
->workspace_submenu
->entries
[i
]->clientdata
= wwin
;
714 if (i
== scr
->current_workspace
)
715 wMenuSetEnabled(scr
->workspace_submenu
, i
, False
);
717 wMenuSetEnabled(scr
->workspace_submenu
, i
, True
);
720 menu
->flags
.realized
= 0;
724 static WMenu
*open_window_menu_core(WWindow
*wwin
)
726 WScreen
*scr
= wwin
->screen_ptr
;
729 wwin
->flags
.menu_open_for_me
= 1;
731 if (!scr
->window_menu
) {
732 scr
->window_menu
= createWindowMenu(scr
);
734 /* hack to save some memory allocation/deallocation */
735 wfree(scr
->window_menu
->entries
[MC_MINIATURIZE
]->text
);
736 wfree(scr
->window_menu
->entries
[MC_MAXIMIZE
]->text
);
737 wfree(scr
->window_menu
->entries
[MC_SHADE
]->text
);
738 wfree(scr
->window_menu
->entries
[MC_SELECT
]->text
);
740 updateWorkspaceMenu(scr
->workspace_submenu
);
743 menu
= scr
->window_menu
;
744 if (menu
->flags
.mapped
) {
746 if (menu
->entries
[0]->clientdata
== wwin
)
750 updateMenuForWindow(menu
, wwin
);
755 static void prepare_menu_position(WMenu
*menu
, int *x
, int *y
)
759 rect
= wGetRectForHead(menu
->frame
->screen_ptr
,
760 wGetHeadForPointerLocation(menu
->frame
->screen_ptr
));
761 if (*x
< rect
.pos
.x
- menu
->frame
->core
->width
/ 2)
762 *x
= rect
.pos
.x
- menu
->frame
->core
->width
/ 2;
767 void OpenWindowMenu(WWindow
*wwin
, int x
, int y
, int keyboard
)
771 menu
= open_window_menu_core(wwin
);
775 /* Specific menu position */
776 x
-= menu
->frame
->core
->width
/ 2;
777 if (x
+ menu
->frame
->core
->width
> wwin
->frame_x
+ wwin
->frame
->core
->width
)
778 x
= wwin
->frame_x
+ wwin
->frame
->core
->width
- menu
->frame
->core
->width
;
779 if (x
< wwin
->frame_x
)
782 /* Common menu position */
783 prepare_menu_position(menu
, &x
, &y
);
785 if (!wwin
->flags
.internal_window
)
786 wMenuMapAt(menu
, x
, y
, keyboard
);
789 void OpenWindowMenu2(WWindow
*wwin
, int x
, int y
, int keyboard
)
793 WScreen
*scr
= wwin
->screen_ptr
;
795 menu
= open_window_menu_core(wwin
);
799 /* Specific menu position */
800 for (i
= 0; i
< scr
->workspace_submenu
->entry_no
; i
++) {
801 scr
->workspace_submenu
->entries
[i
]->clientdata
= wwin
;
802 wMenuSetEnabled(scr
->workspace_submenu
, i
, True
);
805 x
-= menu
->frame
->core
->width
/ 2;
807 /* Common menu position */
808 prepare_menu_position(menu
, &x
, &y
);
810 if (!wwin
->flags
.internal_window
)
811 wMenuMapAt(menu
, x
, y
, keyboard
);
814 void OpenMiniwindowMenu(WWindow
* wwin
, int x
, int y
)
818 menu
= open_window_menu_core(wwin
);
822 x
-= menu
->frame
->core
->width
/ 2;
824 wMenuMapAt(menu
, x
, y
, False
);
827 void DestroyWindowMenu(WScreen
*scr
)
829 if (scr
->window_menu
) {
830 scr
->window_menu
->entries
[MC_MINIATURIZE
]->text
= NULL
;
831 scr
->window_menu
->entries
[MC_MAXIMIZE
]->text
= NULL
;
832 scr
->window_menu
->entries
[MC_SHADE
]->text
= NULL
;
833 scr
->window_menu
->entries
[MC_SELECT
]->text
= NULL
;
834 wMenuDestroy(scr
->window_menu
, True
);
835 scr
->window_menu
= NULL
;