2
* Window Maker window manager
4
* Copyright (c) 1997 Shige Abe
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
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
33
#include <X11/Xutil.h>
35
#include "WindowMaker.h"
41
#include "workspace.h"
44
/********* Global Variables *******/
45
extern WPreferences wPreferences;
46
extern Time LastTimestamp;
49
static int initialized = 0;
52
static void observer(void *self, WMNotification *notif);
53
static void wsobserver(void *self, WMNotification *notif);
59
* - Needs to check if already in the right workspace before
60
* calling wChangeWorkspace?
63
* Switch to correct workspace
65
* If iconified then deiconify else focus/raise.
68
focusWindow(WMenu *menu, WMenuEntry *entry)
74
wwin = (WWindow*)entry->clientdata;
75
scr = wwin->screen_ptr;
77
wMakeWindowVisible(wwin);
82
/* bring window back to visible area */
83
move = wScreenBringInside(scr, &x, &y, wwin->frame->core->width,
84
wwin->frame->core->height);
87
wWindowConfigure(wwin, x, y, wwin->client.width, wwin->client.height);
93
InitializeSwitchMenu()
98
WMAddNotificationObserver(observer, NULL, WMNManaged, NULL);
99
WMAddNotificationObserver(observer, NULL, WMNUnmanaged, NULL);
100
WMAddNotificationObserver(observer, NULL, WMNChangedWorkspace, NULL);
101
WMAddNotificationObserver(observer, NULL, WMNChangedState, NULL);
102
WMAddNotificationObserver(observer, NULL, WMNChangedFocus, NULL);
103
WMAddNotificationObserver(observer, NULL, WMNChangedStacking, NULL);
104
WMAddNotificationObserver(observer, NULL, WMNChangedName, NULL);
106
WMAddNotificationObserver(wsobserver, NULL, WMNWorkspaceChanged, NULL);
107
WMAddNotificationObserver(wsobserver, NULL, WMNWorkspaceNameChanged, NULL);
118
OpenSwitchMenu(WScreen *scr, int x, int y, int keyboard)
120
WMenu *switchmenu = scr->switch_menu;
124
if (switchmenu->flags.mapped) {
125
if (!switchmenu->flags.buttoned) {
126
wMenuUnmap(switchmenu);
128
wRaiseFrame(switchmenu->frame->core);
131
wMenuMapAt(switchmenu, 0, 0, True);
133
wMenuMapCopyAt(switchmenu,
134
x-switchmenu->frame->core->width/2, y);
137
if (keyboard && x==scr->scr_width/2 && y==scr->scr_height/2) {
138
y = y - switchmenu->frame->core->height/2;
140
wMenuMapAt(switchmenu, x-switchmenu->frame->core->width/2, y,
145
switchmenu = wMenuCreate(scr,_("Windows"),True);
146
scr->switch_menu = switchmenu;
149
wwin = scr->focused_window;
151
UpdateSwitchMenu(scr, wwin, ACTION_ADD);
159
if (!switchmenu->flags.realized)
160
wMenuRealize(switchmenu);
162
if (keyboard && x==0 && y==0) {
164
} else if (keyboard && x==scr->scr_width/2 && y==scr->scr_height/2) {
165
newx = x - switchmenu->frame->core->width/2;
166
newy = y - switchmenu->frame->core->height/2;
168
newx = x - switchmenu->frame->core->width/2;
171
wMenuMapAt(switchmenu, newx, newy, keyboard);
177
menuIndexForWindow(WMenu *menu, WWindow *wwin, int old_pos)
181
if (menu->entry_no <= old_pos)
184
#define WS(i) ((WWindow*)menu->entries[i]->clientdata)->frame->workspace
186
if (WS(old_pos) >= wwin->frame->workspace
187
&& (old_pos == 0 || WS(old_pos-1) <= wwin->frame->workspace)) {
193
for (idx = 0; idx < menu->entry_no; idx++) {
194
WWindow *tw = (WWindow*)menu->entries[idx]->clientdata;
196
if (!IS_OMNIPRESENT(tw)
197
&& tw->frame->workspace > wwin->frame->workspace) {
210
UpdateSwitchMenu(WScreen *scr, WWindow *wwin, int action)
212
WMenu *switchmenu = scr->switch_menu;
214
char title[MAX_MENU_TEXT_LENGTH+6];
215
int len = sizeof(title);
217
int checkVisibility = 0;
219
if (!wwin->screen_ptr->switch_menu)
222
* This menu is updated under the following conditions:
224
* 1. When a window is created.
225
* 2. When a window is destroyed.
227
* 3. When a window changes it's title.
228
* 4. When a window changes its workspace.
230
if (action == ACTION_ADD) {
234
if (wwin->flags.internal_window || WFLAGP(wwin, skip_window_list))
237
if (wwin->frame->title)
238
snprintf(title, len, "%s", wwin->frame->title);
240
snprintf(title, len, "%s", DEF_WINDOW_TITLE);
241
t = ShrinkString(scr->menu_entry_font, title, MAX_WINDOWLIST_WIDTH);
243
if (IS_OMNIPRESENT(wwin))
246
idx = menuIndexForWindow(switchmenu, wwin, -1);
249
entry = wMenuInsertCallback(switchmenu, idx, t, focusWindow, wwin);
252
entry->flags.indicator = 1;
253
entry->rtext = wmalloc(MAX_WORKSPACENAME_WIDTH+8);
254
if (IS_OMNIPRESENT(wwin))
255
snprintf(entry->rtext, MAX_WORKSPACENAME_WIDTH, "[*]");
257
snprintf(entry->rtext, MAX_WORKSPACENAME_WIDTH, "[%s]",
258
scr->workspaces[wwin->frame->workspace]->name);
260
if (wwin->flags.hidden) {
261
entry->flags.indicator_type = MI_HIDDEN;
262
entry->flags.indicator_on = 1;
263
} else if (wwin->flags.miniaturized) {
264
entry->flags.indicator_type = MI_MINIWINDOW;
265
entry->flags.indicator_on = 1;
266
} else if (wwin->flags.focused) {
267
entry->flags.indicator_type = MI_DIAMOND;
268
entry->flags.indicator_on = 1;
269
} else if (wwin->flags.shaded) {
270
entry->flags.indicator_type = MI_SHADED;
271
entry->flags.indicator_on = 1;
274
wMenuRealize(switchmenu);
278
for (i=0; i<switchmenu->entry_no; i++) {
279
entry = switchmenu->entries[i];
280
/* this is the entry that was changed */
281
if (entry->clientdata == wwin) {
284
wMenuRemoveItem(switchmenu, i);
285
wMenuRealize(switchmenu);
293
if (wwin->frame->title)
294
snprintf(title, MAX_MENU_TEXT_LENGTH, "%s",
297
snprintf(title, MAX_MENU_TEXT_LENGTH, "%s",
300
t = ShrinkString(scr->menu_entry_font, title, MAX_WINDOWLIST_WIDTH);
303
wMenuRealize(switchmenu);
307
case ACTION_CHANGE_WORKSPACE:
313
if (IS_OMNIPRESENT(wwin)) {
314
snprintf(entry->rtext, MAX_WORKSPACENAME_WIDTH,
317
snprintf(entry->rtext, MAX_WORKSPACENAME_WIDTH,
318
"[%s]", scr->workspaces[wwin->frame->workspace]->name);
326
it = entry->flags.indicator_type;
327
ion = entry->flags.indicator_on;
329
if (!IS_OMNIPRESENT(wwin) && idx < 0) {
330
idx = menuIndexForWindow(switchmenu, wwin, i);
333
wMenuRemoveItem(switchmenu, i);
335
entry = wMenuInsertCallback(switchmenu, idx, t,
339
entry->flags.indicator = 1;
340
entry->flags.indicator_type = it;
341
entry->flags.indicator_on = ion;
343
wMenuRealize(switchmenu);
348
case ACTION_CHANGE_STATE:
349
if (wwin->flags.hidden) {
350
entry->flags.indicator_type = MI_HIDDEN;
351
entry->flags.indicator_on = 1;
352
} else if (wwin->flags.miniaturized) {
353
entry->flags.indicator_type = MI_MINIWINDOW;
354
entry->flags.indicator_on = 1;
355
} else if (wwin->flags.shaded && !wwin->flags.focused) {
356
entry->flags.indicator_type = MI_SHADED;
357
entry->flags.indicator_on = 1;
359
entry->flags.indicator_on = wwin->flags.focused;
360
entry->flags.indicator_type = MI_DIAMOND;
368
if (checkVisibility) {
371
tmp = switchmenu->frame->top_width + 5;
372
/* if menu got unreachable, bring it to a visible place */
373
if (switchmenu->frame_x < tmp - (int)switchmenu->frame->core->width) {
374
wMenuMove(switchmenu, tmp - (int)switchmenu->frame->core->width,
375
switchmenu->frame_y, False);
378
wMenuPaint(switchmenu);
384
UpdateSwitchMenuWorkspace(WScreen *scr, int workspace)
386
WMenu *menu = scr->switch_menu;
393
for (i=0; i<menu->entry_no; i++) {
394
wwin = (WWindow*)menu->entries[i]->clientdata;
396
if (wwin->frame->workspace==workspace
397
&& !IS_OMNIPRESENT(wwin)) {
398
if (IS_OMNIPRESENT(wwin))
399
snprintf(menu->entries[i]->rtext, MAX_WORKSPACENAME_WIDTH,"[*]");
401
snprintf(menu->entries[i]->rtext, MAX_WORKSPACENAME_WIDTH,"[%s]",
402
scr->workspaces[wwin->frame->workspace]->name);
403
menu->flags.realized = 0;
406
if (!menu->flags.realized)
412
observer(void *self, WMNotification *notif)
414
WWindow *wwin = (WWindow*)WMGetNotificationObject(notif);
415
const char *name = WMGetNotificationName(notif);
416
void *data = WMGetNotificationClientData(notif);
421
if (strcmp(name, WMNManaged) == 0)
422
UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_ADD);
423
else if (strcmp(name, WMNUnmanaged) == 0)
424
UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_REMOVE);
425
else if (strcmp(name, WMNChangedWorkspace) == 0)
426
UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_WORKSPACE);
427
else if (strcmp(name, WMNChangedFocus) == 0)
428
UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_STATE);
429
else if (strcmp(name, WMNChangedName) == 0)
430
UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE);
431
else if (strcmp(name, WMNChangedState) == 0) {
432
if (strcmp((char*)data, "omnipresent") == 0) {
433
UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_WORKSPACE);
435
UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_STATE);
442
wsobserver(void *self, WMNotification *notif)
444
WScreen *scr = (WScreen*)WMGetNotificationObject(notif);
445
const char *name = WMGetNotificationName(notif);
446
void *data = WMGetNotificationClientData(notif);
448
if (strcmp(name, WMNWorkspaceNameChanged) == 0) {
449
UpdateSwitchMenuWorkspace(scr, (int)data);
450
} else if (strcmp(name, WMNWorkspaceChanged) == 0) {