~focus-follows-mouse/ubuntu/precise/compiz/fix-883383

« back to all changes in this revision

Viewing changes to .pc/103_git_fix_gtk_w_d.patch/gtk/window-decorator/events.c

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2011-03-22 21:45:34 UTC
  • mfrom: (0.168.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20110322214534-l6i6ds54os5uoqt1
Tags: 1:0.9.4git20110322-0ubuntu1
* New upstream bug fix snapshot:
  - Application windows can sometimes fail to display and will
    mask regions of the screen (LP: #709461)
  - Compiz switcher Alt-Tab order is not predictable - should
    maintain LIFO ordering in application switcher (LP: #175874)
  - after compiz crashed, gnome-panel isn't mapped again (LP: #711378)
  - invisible windows border problem (LP: #710271)
  - Compiz thinks you are clicking in an edge window when you
    are not (LP: #734250)
  - Add test case for invisible window regressions (LP: #736876)
  - often can't alt-click-dnd to move the focussed dialog (LP: #711911)
  - When windows open for the first time they should not hide (LP: #723878)
  - Unity Grid is broken for multi-monitor setups (LP: #709221)
  - Pixmaps trashed during animations when window is unmapped (LP: #733331)
  - Windows have blank decorations when rapidly closing and
    reopening (LP: #733328)
  - Unity is not restored on unity/compiz crash: compiz doesn't register
    properly with gnome-session (LP: #716462)
* remove the patch taken from upstream
* refresh u-w-d patch with latest upstream work
* debian/compiz-core.install:
  - image move to the final destination
* debian/patches/100_bump_core.h.patch:
  - bump for ABI breakage
* debian/compiz-decorator:
  - use gtk-window-decorator and not unity-window-decorator as it's really
    crashy for now (will probably redo an upload tomorrow with a fixed
    decorator)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright © 2006 Novell, Inc.
3
 
 *
4
 
 * This library is free software; you can redistribute it and/or
5
 
 * modify it under the terms of the GNU Lesser General Public
6
 
 * License as published by the Free Software Foundation; either
7
 
 * version 2 of the License, or (at your option) any later version.
8
 
 *
9
 
 * This library is distributed in the hope that it will be useful,
10
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 
 * Lesser General Public License for more details.
13
 
 *
14
 
 * You should have received a copy of the GNU Lesser General Public
15
 
 * License along with this library; if not, write to the
16
 
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17
 
 * Boston, MA 02111-1307, USA.
18
 
 *
19
 
 * Author: David Reveman <davidr@novell.com>
20
 
 *
21
 
 * 2D Mode: Copyright © 2010 Sam Spilsbury <smspillaz@gmail.com>
22
 
 * Frames Management: Copright © 2011 Canonical Ltd.
23
 
 *        Authored By: Sam Spilsbury <sam.spilsbury@canonical.com>
24
 
 */
25
 
 
26
 
#include "gtk-window-decorator.h" 
27
 
 
28
 
void
29
 
move_resize_window (WnckWindow *win,
30
 
                    int        direction,
31
 
                    decor_event *gtkwd_event)
32
 
{
33
 
    Display    *xdisplay;
34
 
    GdkDisplay *gdkdisplay;
35
 
    GdkScreen  *screen;
36
 
    Window     xroot;
37
 
    XEvent     ev;
38
 
 
39
 
    gdkdisplay = gdk_display_get_default ();
40
 
    xdisplay   = GDK_DISPLAY_XDISPLAY (gdkdisplay);
41
 
    screen     = gdk_display_get_default_screen (gdkdisplay);
42
 
    xroot      = RootWindowOfScreen (gdk_x11_screen_get_xscreen (screen));
43
 
 
44
 
    if (action_menu_mapped)
45
 
    {
46
 
        gtk_object_destroy (GTK_OBJECT (action_menu));
47
 
        action_menu_mapped = FALSE;
48
 
        action_menu = NULL;
49
 
        return;
50
 
    }
51
 
 
52
 
    ev.xclient.type    = ClientMessage;
53
 
    ev.xclient.display = xdisplay;
54
 
 
55
 
    ev.xclient.serial     = 0;
56
 
    ev.xclient.send_event = TRUE;
57
 
 
58
 
    ev.xclient.window       = wnck_window_get_xid (win);
59
 
    ev.xclient.message_type = wm_move_resize_atom;
60
 
    ev.xclient.format       = 32;
61
 
 
62
 
    ev.xclient.data.l[0] = gtkwd_event->x_root;
63
 
    ev.xclient.data.l[1] = gtkwd_event->y_root;
64
 
    ev.xclient.data.l[2] = direction;
65
 
    ev.xclient.data.l[3] = gtkwd_event->button;
66
 
    ev.xclient.data.l[4] = 1;
67
 
 
68
 
    XUngrabPointer (xdisplay, gtkwd_event->time);
69
 
    XUngrabKeyboard (xdisplay, gtkwd_event->time);
70
 
 
71
 
    XSendEvent (xdisplay, xroot, FALSE,
72
 
                SubstructureRedirectMask | SubstructureNotifyMask,
73
 
                &ev);
74
 
 
75
 
    XSync (xdisplay, FALSE);
76
 
}
77
 
 
78
 
void
79
 
common_button_event (WnckWindow *win,
80
 
                     decor_event *gtkwd_event,
81
 
                     decor_event_type gtkwd_type,
82
 
                     int        button,
83
 
                     int        max,
84
 
                     char       *tooltip)
85
 
{
86
 
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
87
 
    guint   state = d->button_states[button];
88
 
 
89
 
    handle_tooltip_event (win, gtkwd_event, gtkwd_type, state, tooltip);
90
 
 
91
 
    if (d->frame_window && gtkwd_type == GEnterNotify)
92
 
    {
93
 
        GdkCursor* cursor;
94
 
        cursor = gdk_cursor_new (GDK_LEFT_PTR);
95
 
        gdk_window_set_cursor (d->frame_window, cursor);
96
 
        gdk_cursor_unref (cursor);
97
 
    }
98
 
 
99
 
    switch (gtkwd_type) {
100
 
    case GButtonPress:
101
 
        if (gtkwd_event->button <= max)
102
 
            d->button_states[button] |= PRESSED_EVENT_WINDOW;
103
 
        break;
104
 
    case GButtonRelease:
105
 
        if (gtkwd_event->button <= max)
106
 
            d->button_states[button] &= ~PRESSED_EVENT_WINDOW;
107
 
        break;
108
 
    case GEnterNotify:
109
 
        d->button_states[button] |= IN_EVENT_WINDOW;
110
 
        break;
111
 
    case GLeaveNotify:
112
 
        d->button_states[button] &= ~IN_EVENT_WINDOW;
113
 
        break;
114
 
    default:
115
 
        break;
116
 
    }
117
 
 
118
 
    if (state != d->button_states[button])
119
 
        queue_decor_draw (d);
120
 
}
121
 
 
122
 
#define BUTTON_EVENT_ACTION_STATE (PRESSED_EVENT_WINDOW | IN_EVENT_WINDOW)
123
 
 
124
 
void
125
 
close_button_event (WnckWindow *win,
126
 
                    decor_event *gtkwd_event,
127
 
                    decor_event_type gtkwd_type)
128
 
{
129
 
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
130
 
    guint   state = d->button_states[BUTTON_CLOSE];
131
 
 
132
 
    common_button_event (win, gtkwd_event, gtkwd_type,
133
 
                         BUTTON_CLOSE, 1, _("Close Window"));
134
 
 
135
 
    switch (gtkwd_type) {
136
 
    case GButtonRelease:
137
 
        if (gtkwd_event->button == 1)
138
 
            if (state == BUTTON_EVENT_ACTION_STATE)
139
 
                wnck_window_close (win, gtkwd_event->time);
140
 
        break;
141
 
    default:
142
 
        break;
143
 
    }
144
 
}
145
 
 
146
 
void
147
 
max_button_event (WnckWindow *win,
148
 
                  decor_event *gtkwd_event,
149
 
                  decor_event_type gtkwd_type)
150
 
{
151
 
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
152
 
    guint   state = d->button_states[BUTTON_MAX];
153
 
 
154
 
    if (wnck_window_is_maximized (win))
155
 
        common_button_event (win, gtkwd_event, gtkwd_type, BUTTON_MAX,
156
 
                             3, _("Unmaximize Window"));
157
 
    else
158
 
        common_button_event (win, gtkwd_event, gtkwd_type, BUTTON_MAX,
159
 
                             3, _("Maximize Window"));
160
 
 
161
 
    switch (gtkwd_type) {
162
 
    case GButtonRelease:
163
 
        if (gtkwd_event->button <= 3)
164
 
        {
165
 
            if (state == BUTTON_EVENT_ACTION_STATE)
166
 
            {
167
 
                if (gtkwd_event->button == 2)
168
 
                {
169
 
                    if (wnck_window_is_maximized_vertically (win))
170
 
                        wnck_window_unmaximize_vertically (win);
171
 
                    else
172
 
                        wnck_window_maximize_vertically (win);
173
 
                }
174
 
                else if (gtkwd_event->button == 3)
175
 
                {
176
 
                    if (wnck_window_is_maximized_horizontally (win))
177
 
                        wnck_window_unmaximize_horizontally (win);
178
 
                    else
179
 
                        wnck_window_maximize_horizontally (win);
180
 
                }
181
 
                else
182
 
                {
183
 
                    if (wnck_window_is_maximized (win))
184
 
                        wnck_window_unmaximize (win);
185
 
                    else
186
 
                        wnck_window_maximize (win);
187
 
                }
188
 
            }
189
 
        }
190
 
        break;
191
 
    default:
192
 
        break;
193
 
    }
194
 
}
195
 
 
196
 
void
197
 
min_button_event (WnckWindow *win,
198
 
                  decor_event *gtkwd_event,
199
 
                  decor_event_type gtkwd_type)
200
 
{
201
 
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
202
 
    guint   state = d->button_states[BUTTON_MIN];
203
 
 
204
 
    common_button_event (win, gtkwd_event, gtkwd_type,
205
 
                         BUTTON_MIN, 1, _("Minimize Window"));
206
 
 
207
 
    switch (gtkwd_type) {
208
 
    case GButtonRelease:
209
 
        if (gtkwd_event->button == 1)
210
 
            if (state == BUTTON_EVENT_ACTION_STATE)
211
 
                wnck_window_minimize (win);
212
 
        break;
213
 
    default:
214
 
        break;
215
 
    }
216
 
}
217
 
 
218
 
void
219
 
menu_button_event (WnckWindow *win,
220
 
                   decor_event *gtkwd_event,
221
 
                   decor_event_type gtkwd_type)
222
 
{
223
 
 
224
 
    common_button_event (win, gtkwd_event, gtkwd_type,
225
 
                         BUTTON_MENU, 1, _("Window Menu"));
226
 
 
227
 
    switch (gtkwd_type) {
228
 
    case GButtonPress:
229
 
        if (gtkwd_event->button == 1)
230
 
            action_menu_map (win,
231
 
                             gtkwd_event->button,
232
 
                             gtkwd_event->time);
233
 
        break;
234
 
    default:
235
 
        break;
236
 
    }
237
 
}
238
 
 
239
 
void
240
 
shade_button_event (WnckWindow *win,
241
 
                    decor_event *gtkwd_event,
242
 
                    decor_event_type gtkwd_type)
243
 
{
244
 
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
245
 
    guint   state = d->button_states[BUTTON_SHADE];
246
 
 
247
 
    common_button_event (win, gtkwd_event, gtkwd_type,
248
 
                         BUTTON_SHADE, 1, _("Shade"));
249
 
 
250
 
    switch (gtkwd_type) {
251
 
    case GButtonRelease:
252
 
        if (gtkwd_event->button == 1)
253
 
        {
254
 
            if (state == BUTTON_EVENT_ACTION_STATE)
255
 
                wnck_window_shade (win);
256
 
        }
257
 
        break;
258
 
    default:
259
 
        break;
260
 
    }
261
 
}
262
 
 
263
 
void
264
 
above_button_event (WnckWindow *win,
265
 
                    decor_event *gtkwd_event,
266
 
                    decor_event_type gtkwd_type)
267
 
{
268
 
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
269
 
    guint   state = d->button_states[BUTTON_ABOVE];
270
 
 
271
 
    common_button_event (win, gtkwd_event, gtkwd_type,
272
 
                         BUTTON_ABOVE, 1, _("Make Above"));
273
 
 
274
 
    switch (gtkwd_type) {
275
 
    case GButtonRelease:
276
 
        if (gtkwd_event->button == 1)
277
 
            if (state == BUTTON_EVENT_ACTION_STATE)
278
 
#ifdef HAVE_LIBWNCK_2_18_1
279
 
                wnck_window_make_above (win);
280
 
#endif
281
 
        break;
282
 
    default:
283
 
        break;
284
 
    }
285
 
}
286
 
 
287
 
void
288
 
stick_button_event (WnckWindow *win,
289
 
                    decor_event *gtkwd_event,
290
 
                    decor_event_type gtkwd_type)
291
 
{
292
 
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
293
 
    guint   state = d->button_states[BUTTON_STICK];
294
 
 
295
 
    common_button_event (win, gtkwd_event, gtkwd_type,
296
 
                         BUTTON_STICK, 1, _("Stick"));
297
 
 
298
 
    switch (gtkwd_type) {
299
 
    case GButtonRelease:
300
 
        if (gtkwd_event->button == 1)
301
 
            if (state == BUTTON_EVENT_ACTION_STATE)
302
 
                wnck_window_stick (win);
303
 
        break;
304
 
    default:
305
 
        break;
306
 
    }
307
 
}
308
 
 
309
 
void
310
 
unshade_button_event (WnckWindow *win,
311
 
                      decor_event *gtkwd_event,
312
 
                      decor_event_type gtkwd_type)
313
 
{
314
 
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
315
 
    guint   state = d->button_states[BUTTON_UNSHADE];
316
 
 
317
 
    common_button_event (win, gtkwd_event, gtkwd_type,
318
 
                         BUTTON_UNSHADE, 1, _("Unshade"));
319
 
 
320
 
    switch (gtkwd_type) {
321
 
    case GButtonRelease:
322
 
        if (gtkwd_event->button == 1)
323
 
            if (state == BUTTON_EVENT_ACTION_STATE)
324
 
                wnck_window_unshade (win);
325
 
        break;
326
 
    default:
327
 
        break;
328
 
    }
329
 
}
330
 
 
331
 
void
332
 
unabove_button_event (WnckWindow *win,
333
 
                      decor_event *gtkwd_event,
334
 
                      decor_event_type gtkwd_type)
335
 
{
336
 
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
337
 
    guint   state = d->button_states[BUTTON_UNABOVE];
338
 
 
339
 
    common_button_event (win, gtkwd_event, gtkwd_type,
340
 
                         BUTTON_UNABOVE, 1, _("Unmake Above"));
341
 
 
342
 
    switch (gtkwd_type) {
343
 
    case GButtonRelease:
344
 
        if (gtkwd_event->button == 1)
345
 
            if (state == BUTTON_EVENT_ACTION_STATE)
346
 
#ifdef HAVE_LIBWNCK_2_18_1
347
 
                wnck_window_unmake_above (win);
348
 
#endif
349
 
        break;
350
 
    default:
351
 
        break;
352
 
    }
353
 
}
354
 
 
355
 
void
356
 
unstick_button_event (WnckWindow *win,
357
 
                      decor_event *gtkwd_event,
358
 
                      decor_event_type gtkwd_type)
359
 
{
360
 
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
361
 
    guint   state = d->button_states[BUTTON_UNSTICK];
362
 
 
363
 
    common_button_event (win, gtkwd_event, gtkwd_type,
364
 
                         BUTTON_UNSTICK, 1, _("Unstick"));
365
 
 
366
 
    switch (gtkwd_type) {
367
 
    case GButtonRelease:
368
 
        if (gtkwd_event->button == 1)
369
 
            if (state == BUTTON_EVENT_ACTION_STATE)
370
 
                wnck_window_unstick (win);
371
 
        break;
372
 
    default:
373
 
        break;
374
 
    }
375
 
}
376
 
 
377
 
void
378
 
handle_title_button_event (WnckWindow   *win,
379
 
                           int          action,
380
 
                           decor_event *gtkwd_event)
381
 
{
382
 
    switch (action) {
383
 
    case CLICK_ACTION_SHADE:
384
 
        if (wnck_window_is_shaded (win))
385
 
            wnck_window_unshade (win);
386
 
        else
387
 
            wnck_window_shade (win);
388
 
        break;
389
 
    case CLICK_ACTION_MAXIMIZE:
390
 
        if (wnck_window_is_maximized (win))
391
 
            wnck_window_unmaximize (win);
392
 
        else
393
 
            wnck_window_maximize (win);
394
 
        break;
395
 
    case CLICK_ACTION_MINIMIZE:
396
 
        if (!wnck_window_is_minimized (win))
397
 
            wnck_window_minimize (win);
398
 
        break;
399
 
    case CLICK_ACTION_RAISE:
400
 
        restack_window (win, Above);
401
 
        break;
402
 
    case CLICK_ACTION_LOWER:
403
 
        restack_window (win, Below);
404
 
        break;
405
 
    case CLICK_ACTION_MENU:
406
 
        action_menu_map (win, gtkwd_event->button, gtkwd_event->time);
407
 
        break;
408
 
    }
409
 
}
410
 
 
411
 
void
412
 
handle_mouse_wheel_title_event (WnckWindow   *win,
413
 
                                unsigned int button)
414
 
{
415
 
    switch (settings->wheel_action) {
416
 
    case WHEEL_ACTION_SHADE:
417
 
        if (button == 4)
418
 
        {
419
 
            if (!wnck_window_is_shaded (win))
420
 
                wnck_window_shade (win);
421
 
        }
422
 
        else if (button == 5)
423
 
        {
424
 
            if (wnck_window_is_shaded (win))
425
 
                wnck_window_unshade (win);
426
 
        }
427
 
        break;
428
 
    default:
429
 
        break;
430
 
    }
431
 
}
432
 
 
433
 
void
434
 
title_event (WnckWindow       *win,
435
 
             decor_event      *gtkwd_event,
436
 
             decor_event_type gtkwd_type)
437
 
{
438
 
    static int    last_button_num = 0;
439
 
    static Window last_button_xwindow = None;
440
 
    static Time   last_button_time = 0;
441
 
    static int    last_button_x = 0;
442
 
    static int    last_button_y = 0;
443
 
 
444
 
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
445
 
 
446
 
    if (d->frame_window && gtkwd_type == GEnterNotify)
447
 
    {
448
 
        GdkCursor* cursor = gdk_cursor_new (GDK_LEFT_PTR);
449
 
        gdk_window_set_cursor (d->frame_window, cursor);
450
 
        gdk_cursor_unref (cursor);
451
 
    }
452
 
 
453
 
    if (gtkwd_type != GButtonPress)
454
 
        return;
455
 
 
456
 
    if (gtkwd_event->button == 1)
457
 
    {
458
 
        if (gtkwd_event->button == last_button_num                      &&
459
 
            gtkwd_event->window == last_button_xwindow                  &&
460
 
            gtkwd_event->time < last_button_time + double_click_timeout &&
461
 
            dist (gtkwd_event->x, gtkwd_event->y,
462
 
                  last_button_x, last_button_y) < DOUBLE_CLICK_DISTANCE)
463
 
        {
464
 
            handle_title_button_event (win, settings->double_click_action,
465
 
                                       gtkwd_event);
466
 
 
467
 
            last_button_num     = 0;
468
 
            last_button_xwindow = None;
469
 
            last_button_time    = 0;
470
 
            last_button_x       = 0;
471
 
            last_button_y       = 0;
472
 
        }
473
 
        else
474
 
        {
475
 
            last_button_num     = gtkwd_event->button;
476
 
            last_button_xwindow = gtkwd_event->window;
477
 
            last_button_time    = gtkwd_event->time;
478
 
            last_button_x       = gtkwd_event->x;
479
 
            last_button_y       = gtkwd_event->y;
480
 
 
481
 
            restack_window (win, Above);
482
 
 
483
 
            move_resize_window (win, WM_MOVERESIZE_MOVE, gtkwd_event);
484
 
        }
485
 
    }
486
 
    else if (gtkwd_event->button == 2)
487
 
    {
488
 
        handle_title_button_event (win, settings->middle_click_action,
489
 
                                   gtkwd_event);
490
 
    }
491
 
    else if (gtkwd_event->button == 3)
492
 
    {
493
 
        handle_title_button_event (win, settings->right_click_action,
494
 
                                   gtkwd_event);
495
 
    }
496
 
    else if (gtkwd_event->button == 4 ||
497
 
             gtkwd_event->button == 5)
498
 
    {
499
 
        handle_mouse_wheel_title_event (win, gtkwd_event->button);
500
 
    }
501
 
}
502
 
 
503
 
void
504
 
frame_common_event (WnckWindow       *win,
505
 
                    int              direction,
506
 
                    decor_event      *gtkwd_event,
507
 
                    decor_event_type gtkwd_type)
508
 
{
509
 
 
510
 
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
511
 
 
512
 
    if (d->frame_window && gtkwd_type == GEnterNotify)
513
 
    {
514
 
        GdkCursor *cursor = NULL;
515
 
 
516
 
        switch (direction)
517
 
        {
518
 
            case WM_MOVERESIZE_SIZE_TOPLEFT:
519
 
                cursor = gdk_cursor_new (GDK_TOP_LEFT_CORNER);
520
 
                break;
521
 
            case WM_MOVERESIZE_SIZE_LEFT:
522
 
                cursor = gdk_cursor_new (GDK_LEFT_SIDE);
523
 
                break;
524
 
            case WM_MOVERESIZE_SIZE_BOTTOMLEFT:
525
 
                cursor = gdk_cursor_new (GDK_BOTTOM_LEFT_CORNER);
526
 
                break;
527
 
            case WM_MOVERESIZE_SIZE_BOTTOM:
528
 
                cursor = gdk_cursor_new (GDK_BOTTOM_SIDE);
529
 
                break;
530
 
            case WM_MOVERESIZE_SIZE_BOTTOMRIGHT:
531
 
                cursor = gdk_cursor_new (GDK_BOTTOM_RIGHT_CORNER);
532
 
                break;
533
 
            case WM_MOVERESIZE_SIZE_RIGHT:
534
 
                cursor = gdk_cursor_new (GDK_RIGHT_SIDE);
535
 
                break;
536
 
            case WM_MOVERESIZE_SIZE_TOPRIGHT:
537
 
                cursor = gdk_cursor_new (GDK_TOP_RIGHT_CORNER);
538
 
                break;
539
 
            case WM_MOVERESIZE_SIZE_TOP:
540
 
                cursor = gdk_cursor_new (GDK_TOP_SIDE);
541
 
                break;
542
 
            default:
543
 
                break;
544
 
        }
545
 
 
546
 
        if (cursor)
547
 
        {
548
 
            gdk_window_set_cursor (d->frame_window, cursor);
549
 
            gdk_cursor_unref (cursor);
550
 
        }
551
 
    }
552
 
 
553
 
    if (gtkwd_type != GButtonPress)
554
 
        return;
555
 
 
556
 
    switch (gtkwd_event->button) {
557
 
    case 1:
558
 
        move_resize_window (win, direction, gtkwd_event);
559
 
        restack_window (win, Above);
560
 
        break;
561
 
    case 2:
562
 
        handle_title_button_event (win, settings->middle_click_action,
563
 
                                   gtkwd_event);
564
 
        break;
565
 
    case 3:
566
 
        handle_title_button_event (win, settings->right_click_action,
567
 
                                   gtkwd_event);
568
 
        break;
569
 
    }
570
 
}
571
 
 
572
 
void
573
 
top_left_event (WnckWindow       *win,
574
 
                decor_event      *gtkwd_event,
575
 
                decor_event_type gtkwd_type)
576
 
{
577
 
    frame_common_event (win, WM_MOVERESIZE_SIZE_TOPLEFT,
578
 
                        gtkwd_event, gtkwd_type);
579
 
}
580
 
 
581
 
void
582
 
top_event (WnckWindow       *win,
583
 
           decor_event      *gtkwd_event,
584
 
           decor_event_type gtkwd_type)
585
 
{
586
 
    frame_common_event (win, WM_MOVERESIZE_SIZE_TOP,
587
 
                        gtkwd_event, gtkwd_type);
588
 
}
589
 
 
590
 
void
591
 
top_right_event (WnckWindow       *win,
592
 
                 decor_event      *gtkwd_event,
593
 
                 decor_event_type gtkwd_type)
594
 
{
595
 
    frame_common_event (win, WM_MOVERESIZE_SIZE_TOPRIGHT,
596
 
                        gtkwd_event, gtkwd_type);
597
 
}
598
 
 
599
 
void
600
 
left_event (WnckWindow       *win,
601
 
            decor_event      *gtkwd_event,
602
 
            decor_event_type gtkwd_type)
603
 
{
604
 
    frame_common_event (win, WM_MOVERESIZE_SIZE_LEFT,
605
 
                        gtkwd_event, gtkwd_type);
606
 
}
607
 
 
608
 
void
609
 
right_event (WnckWindow       *win,
610
 
             decor_event      *gtkwd_event,
611
 
             decor_event_type gtkwd_type)
612
 
{
613
 
    frame_common_event (win, WM_MOVERESIZE_SIZE_RIGHT,
614
 
                        gtkwd_event, gtkwd_type);
615
 
}
616
 
 
617
 
void
618
 
bottom_left_event (WnckWindow *win,
619
 
                   decor_event *gtkwd_event,
620
 
                   decor_event_type gtkwd_type)
621
 
{
622
 
    frame_common_event (win, WM_MOVERESIZE_SIZE_BOTTOMLEFT,
623
 
                        gtkwd_event, gtkwd_type);
624
 
}
625
 
 
626
 
void
627
 
bottom_event (WnckWindow *win,
628
 
              decor_event *gtkwd_event,
629
 
              decor_event_type gtkwd_type)
630
 
{
631
 
    frame_common_event (win, WM_MOVERESIZE_SIZE_BOTTOM,
632
 
                        gtkwd_event, gtkwd_type);
633
 
}
634
 
 
635
 
void
636
 
bottom_right_event (WnckWindow *win,
637
 
                    decor_event *gtkwd_event,
638
 
                    decor_event_type gtkwd_type)
639
 
{
640
 
    frame_common_event (win, WM_MOVERESIZE_SIZE_BOTTOMRIGHT,
641
 
                        gtkwd_event, gtkwd_type);
642
 
}
643
 
 
644
 
void
645
 
frame_window_realized (GtkWidget *widget,
646
 
                       gpointer  data)
647
 
{
648
 
    decor_t *d = (decor_t *) data;
649
 
 
650
 
    if (d)
651
 
    {
652
 
        GdkWindow *gdk_frame_window = gtk_widget_get_window (d->decor_window);
653
 
        gdk_window_reparent (gdk_frame_window, d->frame_window, 0, 0);
654
 
        gdk_window_lower (gdk_frame_window);
655
 
 
656
 
    }
657
 
}
658
 
 
659
 
event_callback
660
 
find_event_callback_for_point (decor_t *d,
661
 
                               int     x,
662
 
                               int     y,
663
 
                               Bool    *enter,
664
 
                               Bool    *leave,
665
 
                               BoxPtr  *entered_box)
666
 
{
667
 
    int    i, j;
668
 
    BoxPtr box;
669
 
 
670
 
    for (i = 0; i < BUTTON_NUM; i++)
671
 
    {
672
 
        box = &d->button_windows[i].pos;
673
 
        if (x >= box->x1 && x <= box->x2 &&
674
 
            y >= box->y1 && y <= box->y2)
675
 
        {
676
 
            if (d->last_pos_entered != box)
677
 
            {
678
 
                if (enter)
679
 
                    *enter = TRUE;
680
 
                if (leave && d->last_pos_entered)
681
 
                    *leave = TRUE;
682
 
                if (entered_box)
683
 
                    *entered_box = box;
684
 
            }
685
 
            return d->button_windows[i].callback;
686
 
        }
687
 
    }
688
 
 
689
 
    for (i = 0; i < 3; i++)
690
 
    {
691
 
        for (j = 0; j < 3; j++)
692
 
        {
693
 
            box = &d->event_windows[i][j].pos;
694
 
            if (x >= box->x1 && x <= box->x2 &&
695
 
                y >= box->y1 && y <= box->y2)
696
 
            {
697
 
                if (d->last_pos_entered != box)
698
 
                {
699
 
                    if (enter)
700
 
                        *enter = TRUE;
701
 
                    if (leave && d->last_pos_entered)
702
 
                        *leave = TRUE;
703
 
                    if (entered_box)
704
 
                        *entered_box = box;
705
 
                }
706
 
                return d->event_windows[i][j].callback;
707
 
            }
708
 
        }
709
 
    }
710
 
 
711
 
    return NULL;
712
 
}
713
 
 
714
 
event_callback
715
 
find_leave_event_callback (decor_t *d)
716
 
{
717
 
    int i, j;
718
 
 
719
 
    for (i = 0; i < BUTTON_NUM; i++)
720
 
    {
721
 
        if (d->last_pos_entered == &d->button_windows[i].pos)
722
 
            return d->button_windows[i].callback;
723
 
    }
724
 
 
725
 
    for (i = 0; i < 3; i++)
726
 
    {
727
 
        for (j = 0; j < 3; j++)
728
 
        {
729
 
            if (d->last_pos_entered == &d->event_windows[i][j].pos)
730
 
                return d->event_windows[i][j].callback;
731
 
        }
732
 
    }
733
 
 
734
 
    return NULL;
735
 
}
736
 
 
737
 
void
738
 
frame_handle_button_press (GtkWidget      *widget,
739
 
                           GdkEventButton *event,
740
 
                           gpointer       user_data)
741
 
{
742
 
    decor_t *d = (decor_t *) user_data;
743
 
 
744
 
    if (d)
745
 
    {
746
 
        /* Check to see where the event happened and fill out an appropriate
747
 
         * struct
748
 
         */
749
 
        event_callback cb;
750
 
 
751
 
        cb = find_event_callback_for_point (d, event->x, event->y,
752
 
                                            NULL, NULL, NULL);
753
 
 
754
 
        if (cb && d->decorated)
755
 
        {
756
 
            decor_event gtkwd_event;
757
 
 
758
 
            gtkwd_event.window = GDK_WINDOW_XID (d->frame_window);
759
 
            gtkwd_event.button = event->button;
760
 
            gtkwd_event.x      = event->x;
761
 
            gtkwd_event.y      = event->y;
762
 
            gtkwd_event.x_root = event->x_root;
763
 
            gtkwd_event.y_root = event->y_root;
764
 
            gtkwd_event.time   = event->time;
765
 
 
766
 
            (*cb) (d->win, &gtkwd_event, GButtonPress);
767
 
        }
768
 
    }
769
 
}
770
 
 
771
 
void
772
 
frame_handle_button_release (GtkWidget      *widget,
773
 
                             GdkEventButton *event,
774
 
                             gpointer       user_data)
775
 
{
776
 
    decor_t *d = (decor_t *) user_data;
777
 
 
778
 
    if (d)
779
 
    {
780
 
        event_callback cb;
781
 
 
782
 
        cb = find_event_callback_for_point (d, event->x, event->y,
783
 
                                            NULL, NULL, NULL);
784
 
 
785
 
        if (cb && d->decorated)
786
 
        {
787
 
            decor_event gtkwd_event;
788
 
 
789
 
            gtkwd_event.window = GDK_WINDOW_XID (d->frame_window);
790
 
            gtkwd_event.button = event->button;
791
 
            gtkwd_event.x      = event->x;
792
 
            gtkwd_event.y      = event->y;
793
 
            gtkwd_event.x_root = event->x_root;
794
 
            gtkwd_event.y_root = event->y_root;
795
 
            gtkwd_event.time   = event->time;
796
 
 
797
 
            (*cb) (d->win, &gtkwd_event, GButtonRelease);
798
 
        }
799
 
    }
800
 
}
801
 
 
802
 
void
803
 
frame_handle_motion (GtkWidget      *widget,
804
 
                     GdkEventMotion *event,
805
 
                     gpointer       user_data)
806
 
{
807
 
    decor_t *d = (decor_t *) user_data;
808
 
 
809
 
    if (d)
810
 
    {
811
 
        event_callback cb = NULL;
812
 
        Bool           send_enter = FALSE;
813
 
        Bool           send_leave = FALSE;
814
 
        BoxPtr         entered_box;
815
 
 
816
 
        cb = find_event_callback_for_point (d, event->x, event->y,
817
 
                                            &send_enter, &send_leave,
818
 
                                            &entered_box);
819
 
 
820
 
        if (cb && d->decorated)
821
 
        {
822
 
            decor_event gtkwd_event;
823
 
 
824
 
            gtkwd_event.window = GDK_WINDOW_XID (d->frame_window);
825
 
            gtkwd_event.x      = event->x;
826
 
            gtkwd_event.y      = event->y;
827
 
            gtkwd_event.x_root = event->x_root;
828
 
            gtkwd_event.y_root = event->y_root;
829
 
            gtkwd_event.time   = event->time;
830
 
 
831
 
            if (send_enter)
832
 
                (*cb) (d->win, &gtkwd_event, GEnterNotify);
833
 
 
834
 
            if (send_leave)
835
 
            {
836
 
                event_callback leave_cb;
837
 
 
838
 
                leave_cb = find_leave_event_callback (d);
839
 
 
840
 
                if (leave_cb)
841
 
                    (*leave_cb) (d->win, &gtkwd_event, GLeaveNotify);
842
 
 
843
 
            }
844
 
 
845
 
            if (send_enter)
846
 
                d->last_pos_entered = entered_box;
847
 
        }
848
 
        else if (d->last_pos_entered && d->decorated)
849
 
        {
850
 
            /* We are not in an event / button window but last_pos_entered
851
 
             * is still set, so send a GLeaveNotify to last_pos_entered
852
 
             * and set it to NULL
853
 
             */
854
 
 
855
 
            event_callback leave_cb;
856
 
 
857
 
            leave_cb = find_leave_event_callback (d);
858
 
 
859
 
            if (leave_cb)
860
 
            {
861
 
                decor_event    gtkwd_event;
862
 
 
863
 
                gtkwd_event.window = GDK_WINDOW_XID (d->frame_window);
864
 
                gtkwd_event.x      = event->x;
865
 
                gtkwd_event.y      = event->y;
866
 
                gtkwd_event.x_root = event->x_root;
867
 
                gtkwd_event.y_root = event->y_root;
868
 
                gtkwd_event.time   = event->time;
869
 
 
870
 
                (*leave_cb) (d->win, &gtkwd_event, GLeaveNotify);
871
 
            }
872
 
 
873
 
            d->last_pos_entered = NULL;
874
 
        }
875
 
    }
876
 
}
877
 
 
878
 
GdkFilterReturn
879
 
event_filter_func (GdkXEvent *gdkxevent,
880
 
                   GdkEvent  *event,
881
 
                   gpointer  data)
882
 
{
883
 
    Display    *xdisplay;
884
 
    GdkDisplay *gdkdisplay;
885
 
    XEvent     *xevent = gdkxevent;
886
 
    gulong     xid = 0;
887
 
    Window     select = 0;
888
 
 
889
 
    gdkdisplay = gdk_display_get_default ();
890
 
    xdisplay   = GDK_DISPLAY_XDISPLAY (gdkdisplay);
891
 
 
892
 
    switch (xevent->type) {
893
 
    case CreateNotify:
894
 
        {
895
 
            if (!wnck_window_get (xevent->xcreatewindow.window))
896
 
            {
897
 
                GdkWindow *toplevel = create_foreign_window (xevent->xcreatewindow.window);
898
 
 
899
 
                if (toplevel)
900
 
                {
901
 
                    gdk_window_set_events (toplevel,
902
 
                                           gdk_window_get_events (toplevel) |
903
 
                                           GDK_PROPERTY_CHANGE_MASK);
904
 
 
905
 
                    /* check if the window is a switcher and update accordingly */
906
 
 
907
 
                    if (get_window_prop (xevent->xcreatewindow.window, select_window_atom, &select))
908
 
                        update_switcher_window (xevent->xcreatewindow.window, select);
909
 
                }
910
 
            }
911
 
        }
912
 
        break;
913
 
    case ButtonPress:
914
 
    case ButtonRelease:
915
 
        xid = (gulong)
916
 
            g_hash_table_lookup (frame_table,
917
 
                                 GINT_TO_POINTER (xevent->xbutton.window));
918
 
        break;
919
 
    case EnterNotify:
920
 
    case LeaveNotify:
921
 
        xid = (gulong)
922
 
            g_hash_table_lookup (frame_table,
923
 
                                 GINT_TO_POINTER (xevent->xcrossing.window));
924
 
        break;
925
 
    case MotionNotify:
926
 
        xid = (gulong)
927
 
            g_hash_table_lookup (frame_table,
928
 
                                 GINT_TO_POINTER (xevent->xmotion.window));
929
 
        break;
930
 
    case PropertyNotify:
931
 
        if (xevent->xproperty.atom == frame_input_window_atom)
932
 
        {
933
 
            WnckWindow *win;
934
 
 
935
 
            xid = xevent->xproperty.window;
936
 
 
937
 
            win = wnck_window_get (xid);
938
 
            if (win)
939
 
            {
940
 
                Window frame;
941
 
 
942
 
                if (!get_window_prop (xid, select_window_atom, &select))
943
 
                {
944
 
                    if (get_window_prop (xid, frame_input_window_atom, &frame))
945
 
                        add_frame_window (win, frame, FALSE);
946
 
                    else
947
 
                        remove_frame_window (win);
948
 
                }
949
 
            }
950
 
        }
951
 
        if (xevent->xproperty.atom == frame_output_window_atom)
952
 
        {
953
 
            WnckWindow *win;
954
 
 
955
 
            xid = xevent->xproperty.window;
956
 
 
957
 
            win = wnck_window_get (xid);
958
 
            if (win)
959
 
            {
960
 
                Window frame;
961
 
 
962
 
                if (!get_window_prop (xid, select_window_atom, &select))
963
 
                {
964
 
                    if (get_window_prop (xid, frame_output_window_atom, &frame))
965
 
                        add_frame_window (win, frame, TRUE);
966
 
                    else
967
 
                        remove_frame_window (win);
968
 
                }
969
 
            }
970
 
        }
971
 
        else if (xevent->xproperty.atom == compiz_shadow_info_atom ||
972
 
                 xevent->xproperty.atom == compiz_shadow_color_atom)
973
 
        {
974
 
            GdkScreen  *g_screen = gdk_display_get_default_screen (gdkdisplay);
975
 
            Window     root = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (g_screen));
976
 
            WnckScreen *screen;
977
 
            
978
 
            screen = wnck_screen_get_for_root (root);
979
 
            
980
 
            if (screen)
981
 
            {
982
 
                if (shadow_property_changed (screen))
983
 
                    decorations_changed (screen);
984
 
            }
985
 
        }
986
 
        else if (xevent->xproperty.atom == mwm_hints_atom)
987
 
        {
988
 
            WnckWindow *win;
989
 
 
990
 
            xid = xevent->xproperty.window;
991
 
 
992
 
            win = wnck_window_get (xid);
993
 
            if (win)
994
 
            {
995
 
                decor_t  *d = g_object_get_data (G_OBJECT (win), "decor");
996
 
                gboolean decorated = FALSE;
997
 
 
998
 
                if (get_mwm_prop (xid) & (MWM_DECOR_ALL | MWM_DECOR_TITLE))
999
 
                    decorated = TRUE;
1000
 
 
1001
 
                if (decorated != d->decorated)
1002
 
                {
1003
 
                    d->decorated = decorated;
1004
 
                    if (decorated)
1005
 
                    {
1006
 
                        d->context = NULL;
1007
 
                        d->width = d->height = 0;
1008
 
 
1009
 
                        update_window_decoration_size (win);
1010
 
                        update_event_windows (win);
1011
 
                    }
1012
 
                    else
1013
 
                    {
1014
 
                        gdk_error_trap_push ();
1015
 
                        XDeleteProperty (xdisplay, xid, win_decor_atom);
1016
 
                        gdk_display_sync (gdk_display_get_default ());
1017
 
                        gdk_error_trap_pop ();
1018
 
                    }
1019
 
                }
1020
 
            }
1021
 
        }
1022
 
        else if (xevent->xproperty.atom == select_window_atom)
1023
 
        {
1024
 
            Window select;
1025
 
 
1026
 
            if (get_window_prop (xevent->xproperty.window, select_window_atom, &select))
1027
 
                update_switcher_window (xevent->xproperty.window, select);
1028
 
        }
1029
 
        break;
1030
 
    case DestroyNotify:
1031
 
        g_hash_table_remove (frame_table,
1032
 
                             GINT_TO_POINTER (xevent->xproperty.window));
1033
 
        break;
1034
 
    case ClientMessage:
1035
 
        if (xevent->xclient.message_type == toolkit_action_atom)
1036
 
        {
1037
 
            long action;
1038
 
 
1039
 
            action = xevent->xclient.data.l[0];
1040
 
            if (action == toolkit_action_window_menu_atom)
1041
 
            {
1042
 
                WnckWindow *win;
1043
 
 
1044
 
                win = wnck_window_get (xevent->xclient.window);
1045
 
                if (win)
1046
 
                {
1047
 
                    action_menu_map (win,
1048
 
                                     xevent->xclient.data.l[2],
1049
 
                                     xevent->xclient.data.l[1]);
1050
 
                }
1051
 
            }
1052
 
            else if (action == toolkit_action_force_quit_dialog_atom)
1053
 
            {
1054
 
                WnckWindow *win;
1055
 
 
1056
 
                win = wnck_window_get (xevent->xclient.window);
1057
 
                if (win)
1058
 
                {
1059
 
                    if (xevent->xclient.data.l[2])
1060
 
                        show_force_quit_dialog (win,
1061
 
                                                xevent->xclient.data.l[1]);
1062
 
                    else
1063
 
                        hide_force_quit_dialog (win);
1064
 
                }
1065
 
            }
1066
 
        }
1067
 
    default:
1068
 
        break;
1069
 
    }
1070
 
 
1071
 
    if (xid)
1072
 
    {
1073
 
        WnckWindow *win;
1074
 
 
1075
 
        win = wnck_window_get (xid);
1076
 
        if (win)
1077
 
        {
1078
 
            decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
1079
 
 
1080
 
            if (d->decorated)
1081
 
            {
1082
 
                gint             i, j;
1083
 
                event_callback   cb = NULL;
1084
 
                Window           w = xevent->xany.window;
1085
 
 
1086
 
                for (i = 0; i < 3; i++)
1087
 
                    for (j = 0; j < 3; j++)
1088
 
                        if (d->event_windows[i][j].window == w)
1089
 
                            cb = d->event_windows[i][j].callback;
1090
 
 
1091
 
                if (!cb)
1092
 
                {
1093
 
                    for (i = 0; i < BUTTON_NUM; i++)
1094
 
                        if (d->button_windows[i].window == w)
1095
 
                            cb = d->button_windows[i].callback;
1096
 
                }
1097
 
 
1098
 
                if (cb)
1099
 
                {
1100
 
                    decor_event      gtkwd_event;
1101
 
                    decor_event_type gtkwd_type;
1102
 
 
1103
 
                    gtkwd_event.window = w;
1104
 
 
1105
 
                    switch (xevent->type)
1106
 
                    {
1107
 
                        case ButtonPress:
1108
 
                        case ButtonRelease:
1109
 
                            if (xevent->type == ButtonPress)
1110
 
                                gtkwd_type = GButtonPress;
1111
 
                            else
1112
 
                                gtkwd_type = GButtonRelease;
1113
 
                            gtkwd_event.button = xevent->xbutton.button;
1114
 
                            gtkwd_event.x = xevent->xbutton.x;
1115
 
                            gtkwd_event.y = xevent->xbutton.y;
1116
 
                            gtkwd_event.x_root = xevent->xbutton.x_root;
1117
 
                            gtkwd_event.y_root = xevent->xbutton.y_root;
1118
 
                            gtkwd_event.time = xevent->xbutton.time;
1119
 
                            break;
1120
 
                        case EnterNotify:
1121
 
                        case LeaveNotify:
1122
 
                            if (xevent->type == EnterNotify)
1123
 
                                gtkwd_type = GEnterNotify;
1124
 
                            else
1125
 
                                gtkwd_type = GLeaveNotify;
1126
 
                            gtkwd_event.x = xevent->xcrossing.x;
1127
 
                            gtkwd_event.y = xevent->xcrossing.y;
1128
 
                            gtkwd_event.x_root = xevent->xcrossing.x_root;
1129
 
                            gtkwd_event.y_root = xevent->xcrossing.y_root;
1130
 
                            gtkwd_event.time = xevent->xcrossing.time;
1131
 
                            break;
1132
 
                        default:
1133
 
                            cb = NULL;
1134
 
                            break;
1135
 
                    }
1136
 
                    if (cb)
1137
 
                        (*cb) (win, &gtkwd_event, gtkwd_type);
1138
 
                }
1139
 
            }
1140
 
        }
1141
 
    }
1142
 
 
1143
 
    return GDK_FILTER_CONTINUE;
1144
 
}
1145
 
 
1146
 
GdkFilterReturn
1147
 
selection_event_filter_func (GdkXEvent *gdkxevent,
1148
 
                             GdkEvent  *event,
1149
 
                             gpointer  data)
1150
 
{
1151
 
    Display    *xdisplay;
1152
 
    GdkDisplay *gdkdisplay;
1153
 
    XEvent     *xevent = gdkxevent;
1154
 
    int        status;
1155
 
 
1156
 
    gdkdisplay = gdk_display_get_default ();
1157
 
    xdisplay   = GDK_DISPLAY_XDISPLAY (gdkdisplay);
1158
 
 
1159
 
    switch (xevent->type) {
1160
 
    case SelectionRequest:
1161
 
        decor_handle_selection_request (xdisplay, xevent, dm_sn_timestamp);
1162
 
        break;
1163
 
    case SelectionClear:
1164
 
        status = decor_handle_selection_clear (xdisplay, xevent, 0);
1165
 
        if (status == DECOR_SELECTION_GIVE_UP)
1166
 
            gtk_main_quit ();
1167
 
    default:
1168
 
        break;
1169
 
    }
1170
 
 
1171
 
    return GDK_FILTER_CONTINUE;
1172
 
}