~profzoom/ubuntu/quantal/wmaker/bug-1079925

« back to all changes in this revision

Viewing changes to src/switchmenu.c

  • Committer: Bazaar Package Importer
  • Author(s): Marcelo E. Magallon
  • Date: 2004-11-10 14:05:30 UTC
  • Revision ID: james.westby@ubuntu.com-20041110140530-qpd66b5lm38x7apk
Tags: upstream-0.91.0
ImportĀ upstreamĀ versionĀ 0.91.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Window Maker window manager
 
3
 *
 
4
 *  Copyright (c) 1997      Shige Abe
 
5
 *  Copyright (c) 1997-2003 Alfredo K. Kojima
 
6
 *
 
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.
 
11
 *
 
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.
 
16
 *
 
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,
 
20
 *  USA.
 
21
 */
 
22
 
 
23
 
 
24
#include "wconfig.h"
 
25
 
 
26
#ifndef LITE
 
27
 
 
28
#include <stdio.h>
 
29
#include <stdlib.h>
 
30
#include <string.h>
 
31
 
 
32
#include <X11/Xlib.h>
 
33
#include <X11/Xutil.h>
 
34
 
 
35
#include "WindowMaker.h"
 
36
#include "window.h"
 
37
#include "actions.h"
 
38
#include "client.h"
 
39
#include "funcs.h"
 
40
#include "stacking.h"
 
41
#include "workspace.h"
 
42
#include "framewin.h"
 
43
 
 
44
/********* Global Variables *******/
 
45
extern WPreferences wPreferences;
 
46
extern Time LastTimestamp;
 
47
 
 
48
 
 
49
static int initialized = 0;
 
50
 
 
51
 
 
52
static void observer(void *self, WMNotification *notif);
 
53
static void wsobserver(void *self, WMNotification *notif);
 
54
 
 
55
 
 
56
/*
 
57
 * FocusWindow
 
58
 *
 
59
 *  - Needs to check if already in the right workspace before
 
60
 *    calling wChangeWorkspace?
 
61
 *
 
62
 *  Order:
 
63
 *    Switch to correct workspace
 
64
 *    Unshade if shaded
 
65
 *    If iconified then deiconify else focus/raise.
 
66
 */
 
67
static void
 
68
focusWindow(WMenu *menu, WMenuEntry *entry)
 
69
{
 
70
    WWindow *wwin;
 
71
    WScreen *scr;
 
72
    int x, y, move=0;
 
73
 
 
74
    wwin = (WWindow*)entry->clientdata;
 
75
    scr = wwin->screen_ptr;
 
76
 
 
77
    wMakeWindowVisible(wwin);
 
78
 
 
79
    x = wwin->frame_x;
 
80
    y = wwin->frame_y;
 
81
 
 
82
    /* bring window back to visible area */
 
83
    move = wScreenBringInside(scr, &x, &y, wwin->frame->core->width,
 
84
                              wwin->frame->core->height);
 
85
 
 
86
    if (move) {
 
87
        wWindowConfigure(wwin, x, y, wwin->client.width, wwin->client.height);
 
88
    }
 
89
}
 
90
 
 
91
 
 
92
void
 
93
InitializeSwitchMenu()
 
94
{
 
95
    if (!initialized) {
 
96
        initialized = 1;
 
97
 
 
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);
 
105
 
 
106
        WMAddNotificationObserver(wsobserver, NULL, WMNWorkspaceChanged, NULL);
 
107
        WMAddNotificationObserver(wsobserver, NULL, WMNWorkspaceNameChanged, NULL);
 
108
    }
 
109
}
 
110
 
 
111
 
 
112
/*
 
113
 *
 
114
 * Open switch menu
 
115
 *
 
116
 */
 
117
void
 
118
OpenSwitchMenu(WScreen *scr, int x, int y, int keyboard)
 
119
{
 
120
    WMenu *switchmenu = scr->switch_menu;
 
121
    WWindow *wwin;
 
122
 
 
123
    if (switchmenu) {
 
124
        if (switchmenu->flags.mapped) {
 
125
            if (!switchmenu->flags.buttoned) {
 
126
                wMenuUnmap(switchmenu);
 
127
            } else {
 
128
                wRaiseFrame(switchmenu->frame->core);
 
129
 
 
130
                if (keyboard)
 
131
                    wMenuMapAt(switchmenu, 0, 0, True);
 
132
                else
 
133
                    wMenuMapCopyAt(switchmenu,
 
134
                                   x-switchmenu->frame->core->width/2, y);
 
135
            }
 
136
        } else {
 
137
            if (keyboard && x==scr->scr_width/2 && y==scr->scr_height/2) {
 
138
                y = y - switchmenu->frame->core->height/2;
 
139
            }
 
140
            wMenuMapAt(switchmenu, x-switchmenu->frame->core->width/2, y,
 
141
                       keyboard);
 
142
        }
 
143
        return;
 
144
    }
 
145
    switchmenu = wMenuCreate(scr,_("Windows"),True);
 
146
    scr->switch_menu = switchmenu;
 
147
 
 
148
 
 
149
    wwin = scr->focused_window;
 
150
    while (wwin) {
 
151
        UpdateSwitchMenu(scr, wwin, ACTION_ADD);
 
152
 
 
153
        wwin = wwin->prev;
 
154
    }
 
155
 
 
156
    if (switchmenu) {
 
157
        int newx, newy;
 
158
 
 
159
        if (!switchmenu->flags.realized)
 
160
            wMenuRealize(switchmenu);
 
161
 
 
162
        if (keyboard && x==0 && y==0) {
 
163
            newx = newy = 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;
 
167
        } else {
 
168
            newx = x - switchmenu->frame->core->width/2;
 
169
            newy = y;
 
170
        }
 
171
        wMenuMapAt(switchmenu, newx, newy, keyboard);
 
172
    }
 
173
}
 
174
 
 
175
 
 
176
static int
 
177
menuIndexForWindow(WMenu *menu, WWindow *wwin, int old_pos)
 
178
{
 
179
    int idx;
 
180
 
 
181
    if (menu->entry_no <= old_pos)
 
182
        return -1;
 
183
 
 
184
#define WS(i)  ((WWindow*)menu->entries[i]->clientdata)->frame->workspace
 
185
    if (old_pos >= 0) {
 
186
        if (WS(old_pos) >= wwin->frame->workspace
 
187
            && (old_pos == 0 || WS(old_pos-1) <= wwin->frame->workspace)) {
 
188
            return old_pos;
 
189
        }
 
190
    }
 
191
#undef WS
 
192
 
 
193
    for (idx = 0; idx < menu->entry_no; idx++) {
 
194
        WWindow *tw = (WWindow*)menu->entries[idx]->clientdata;
 
195
 
 
196
        if (!IS_OMNIPRESENT(tw)
 
197
            && tw->frame->workspace > wwin->frame->workspace) {
 
198
            break;
 
199
        }
 
200
    }
 
201
 
 
202
    return idx;
 
203
}
 
204
 
 
205
 
 
206
/*
 
207
 * Update switch menu
 
208
 */
 
209
void
 
210
UpdateSwitchMenu(WScreen *scr, WWindow *wwin, int action)
 
211
{
 
212
    WMenu *switchmenu = scr->switch_menu;
 
213
    WMenuEntry *entry;
 
214
    char title[MAX_MENU_TEXT_LENGTH+6];
 
215
    int len = sizeof(title);
 
216
    int i;
 
217
    int checkVisibility = 0;
 
218
 
 
219
    if (!wwin->screen_ptr->switch_menu)
 
220
        return;
 
221
    /*
 
222
     *  This menu is updated under the following conditions:
 
223
     *
 
224
     *    1.  When a window is created.
 
225
     *    2.  When a window is destroyed.
 
226
     *
 
227
     *    3.  When a window changes it's title.
 
228
     *    4.  When a window changes its workspace.
 
229
     */
 
230
    if (action == ACTION_ADD) {
 
231
        char *t;
 
232
        int idx;
 
233
 
 
234
        if (wwin->flags.internal_window || WFLAGP(wwin, skip_window_list))
 
235
            return;
 
236
 
 
237
        if (wwin->frame->title)
 
238
            snprintf(title, len, "%s", wwin->frame->title);
 
239
        else
 
240
            snprintf(title, len, "%s", DEF_WINDOW_TITLE);
 
241
        t = ShrinkString(scr->menu_entry_font, title, MAX_WINDOWLIST_WIDTH);
 
242
 
 
243
        if (IS_OMNIPRESENT(wwin))
 
244
            idx = -1;
 
245
        else {
 
246
            idx = menuIndexForWindow(switchmenu, wwin, -1);
 
247
        }
 
248
 
 
249
        entry = wMenuInsertCallback(switchmenu, idx, t, focusWindow, wwin);
 
250
        wfree(t);
 
251
 
 
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, "[*]");
 
256
        else
 
257
            snprintf(entry->rtext, MAX_WORKSPACENAME_WIDTH, "[%s]",
 
258
                     scr->workspaces[wwin->frame->workspace]->name);
 
259
 
 
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;
 
272
        }
 
273
 
 
274
        wMenuRealize(switchmenu);
 
275
        checkVisibility = 1;
 
276
    } else {
 
277
        char *t;
 
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) {
 
282
                switch (action) {
 
283
                case ACTION_REMOVE:
 
284
                    wMenuRemoveItem(switchmenu, i);
 
285
                    wMenuRealize(switchmenu);
 
286
                    checkVisibility = 1;
 
287
                    break;
 
288
 
 
289
                case ACTION_CHANGE:
 
290
                    if (entry->text)
 
291
                        wfree(entry->text);
 
292
 
 
293
                    if (wwin->frame->title)
 
294
                        snprintf(title, MAX_MENU_TEXT_LENGTH, "%s",
 
295
                                 wwin->frame->title);
 
296
                    else
 
297
                        snprintf(title, MAX_MENU_TEXT_LENGTH, "%s",
 
298
                                 DEF_WINDOW_TITLE);
 
299
 
 
300
                    t = ShrinkString(scr->menu_entry_font, title, MAX_WINDOWLIST_WIDTH);
 
301
                    entry->text = t;
 
302
 
 
303
                    wMenuRealize(switchmenu);
 
304
                    checkVisibility = 1;
 
305
                    break;
 
306
 
 
307
                case ACTION_CHANGE_WORKSPACE:
 
308
                    if (entry->rtext) {
 
309
                        int idx = -1;
 
310
                        char *t, *rt;
 
311
                        int it, ion;
 
312
 
 
313
                        if (IS_OMNIPRESENT(wwin)) {
 
314
                            snprintf(entry->rtext, MAX_WORKSPACENAME_WIDTH,
 
315
                                     "[*]");
 
316
                        } else {
 
317
                            snprintf(entry->rtext, MAX_WORKSPACENAME_WIDTH,
 
318
                                     "[%s]", scr->workspaces[wwin->frame->workspace]->name);
 
319
                        }
 
320
 
 
321
                        rt = entry->rtext;
 
322
                        entry->rtext = NULL;
 
323
                        t = entry->text;
 
324
                        entry->text = NULL;
 
325
 
 
326
                        it = entry->flags.indicator_type;
 
327
                        ion = entry->flags.indicator_on;
 
328
 
 
329
                        if (!IS_OMNIPRESENT(wwin) && idx < 0) {
 
330
                            idx = menuIndexForWindow(switchmenu, wwin, i);
 
331
                        }
 
332
 
 
333
                        wMenuRemoveItem(switchmenu, i);
 
334
 
 
335
                        entry = wMenuInsertCallback(switchmenu, idx, t,
 
336
                                                    focusWindow, wwin);
 
337
                        wfree(t);
 
338
                        entry->rtext = rt;
 
339
                        entry->flags.indicator = 1;
 
340
                        entry->flags.indicator_type = it;
 
341
                        entry->flags.indicator_on = ion;
 
342
                    }
 
343
                    wMenuRealize(switchmenu);
 
344
                    checkVisibility = 1;
 
345
                    break;
 
346
 
 
347
 
 
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;
 
358
                    } else {
 
359
                        entry->flags.indicator_on = wwin->flags.focused;
 
360
                        entry->flags.indicator_type = MI_DIAMOND;
 
361
                    }
 
362
                    break;
 
363
                }
 
364
                break;
 
365
            }
 
366
        }
 
367
    }
 
368
    if (checkVisibility) {
 
369
        int tmp;
 
370
 
 
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);
 
376
        }
 
377
    }
 
378
    wMenuPaint(switchmenu);
 
379
}
 
380
 
 
381
 
 
382
 
 
383
void
 
384
UpdateSwitchMenuWorkspace(WScreen *scr, int workspace)
 
385
{
 
386
    WMenu *menu = scr->switch_menu;
 
387
    int i;
 
388
    WWindow *wwin;
 
389
 
 
390
    if (!menu)
 
391
        return;
 
392
 
 
393
    for (i=0; i<menu->entry_no; i++) {
 
394
        wwin = (WWindow*)menu->entries[i]->clientdata;
 
395
 
 
396
        if (wwin->frame->workspace==workspace
 
397
            && !IS_OMNIPRESENT(wwin)) {
 
398
            if (IS_OMNIPRESENT(wwin))
 
399
                snprintf(menu->entries[i]->rtext, MAX_WORKSPACENAME_WIDTH,"[*]");
 
400
            else
 
401
                snprintf(menu->entries[i]->rtext, MAX_WORKSPACENAME_WIDTH,"[%s]",
 
402
                         scr->workspaces[wwin->frame->workspace]->name);
 
403
            menu->flags.realized = 0;
 
404
        }
 
405
    }
 
406
    if (!menu->flags.realized)
 
407
        wMenuRealize(menu);
 
408
}
 
409
 
 
410
 
 
411
static void
 
412
observer(void *self, WMNotification *notif)
 
413
{
 
414
    WWindow *wwin = (WWindow*)WMGetNotificationObject(notif);
 
415
    const char *name = WMGetNotificationName(notif);
 
416
    void *data = WMGetNotificationClientData(notif);
 
417
 
 
418
    if (!wwin)
 
419
        return;
 
420
 
 
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);
 
434
        } else {
 
435
            UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_STATE);
 
436
        }
 
437
    }
 
438
}
 
439
 
 
440
 
 
441
static void
 
442
wsobserver(void *self, WMNotification *notif)
 
443
{
 
444
    WScreen *scr = (WScreen*)WMGetNotificationObject(notif);
 
445
    const char *name = WMGetNotificationName(notif);
 
446
    void *data = WMGetNotificationClientData(notif);
 
447
 
 
448
    if (strcmp(name, WMNWorkspaceNameChanged) == 0) {
 
449
        UpdateSwitchMenuWorkspace(scr, (int)data);
 
450
    } else if (strcmp(name, WMNWorkspaceChanged) == 0) {
 
451
 
 
452
    }
 
453
}
 
454
 
 
455
 
 
456
#endif /* !LITE */
 
457