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

« back to all changes in this revision

Viewing changes to .pc/087_fix_decorator_crashes.patch/gtk/window-decorator/wnck.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
 
const gchar *
29
 
get_frame_type (WnckWindowType wnck_type)
30
 
{
31
 
    switch (wnck_type)
32
 
    {
33
 
        case WNCK_WINDOW_NORMAL:
34
 
            return "normal";
35
 
        case WNCK_WINDOW_DIALOG:
36
 
            return "dialog";
37
 
        case WNCK_WINDOW_MENU:
38
 
            return "menu";
39
 
        case WNCK_WINDOW_UTILITY:
40
 
            return "utility";
41
 
        default:
42
 
            return "bare";
43
 
    }
44
 
 
45
 
    return "normal";
46
 
}
47
 
 
48
 
static void
49
 
window_name_changed (WnckWindow *win)
50
 
{
51
 
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
52
 
 
53
 
    if (d->decorated)
54
 
    {
55
 
        if (!update_window_decoration_size (win))
56
 
            queue_decor_draw (d);
57
 
    }
58
 
}
59
 
 
60
 
static void
61
 
window_geometry_changed (WnckWindow *win)
62
 
{
63
 
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
64
 
 
65
 
    if (d->decorated)
66
 
    {
67
 
        int width, height;
68
 
 
69
 
        wnck_window_get_client_window_geometry (win, NULL, NULL,
70
 
                                                &width, &height);
71
 
 
72
 
        if (width != d->client_width || height != d->client_height)
73
 
        {
74
 
            d->client_width  = width;
75
 
            d->client_height = height;
76
 
 
77
 
            update_window_decoration_size (win);
78
 
            update_event_windows (win);
79
 
        }
80
 
    }
81
 
}
82
 
 
83
 
static void
84
 
window_icon_changed (WnckWindow *win)
85
 
{
86
 
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
87
 
 
88
 
    if (d->decorated)
89
 
    {
90
 
        update_window_decoration_icon (win);
91
 
        queue_decor_draw (d);
92
 
    }
93
 
}
94
 
 
95
 
static void
96
 
window_state_changed (WnckWindow *win)
97
 
{
98
 
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
99
 
 
100
 
    if (d->decorated)
101
 
    {
102
 
        update_window_decoration_state (win);
103
 
        if (!update_window_decoration_size (win))
104
 
            queue_decor_draw (d);
105
 
 
106
 
        update_event_windows (win);
107
 
    }
108
 
}
109
 
 
110
 
static void
111
 
window_actions_changed (WnckWindow *win)
112
 
{
113
 
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
114
 
 
115
 
    if (d->decorated)
116
 
    {
117
 
        update_window_decoration_actions (win);
118
 
        if (!update_window_decoration_size (win))
119
 
            queue_decor_draw (d);
120
 
 
121
 
        update_event_windows (win);
122
 
    }
123
 
}
124
 
 
125
 
void
126
 
update_frames_border_extents (gpointer key,
127
 
                              gpointer value,
128
 
                              gpointer user_data)
129
 
{
130
 
    decor_frame_t *frame = (decor_frame_t *) value;
131
 
 
132
 
    (*theme_update_border_extents) (frame);
133
 
}
134
 
 
135
 
void
136
 
decorations_changed (WnckScreen *screen)
137
 
{
138
 
    GdkDisplay *gdkdisplay;
139
 
    GdkScreen  *gdkscreen;
140
 
    GList      *windows;
141
 
    Window     select;
142
 
 
143
 
    gdkdisplay = gdk_display_get_default ();
144
 
    gdkscreen  = gdk_display_get_default_screen (gdkdisplay);
145
 
 
146
 
    gwd_frames_foreach (set_frames_scales, (gpointer) settings->font);
147
 
 
148
 
    update_titlebar_font ();
149
 
    gwd_process_frames (update_frames_border_extents,
150
 
                        window_type_frames,
151
 
                        WINDOW_TYPE_FRAMES_NUM,
152
 
                        NULL);
153
 
    update_shadow ();
154
 
 
155
 
    update_default_decorations (gdkscreen);
156
 
 
157
 
    if (minimal)
158
 
        return;
159
 
 
160
 
    /* Update all normal windows */
161
 
 
162
 
    windows = wnck_screen_get_windows (screen);
163
 
    while (windows != NULL)
164
 
    {
165
 
        decor_t *d = g_object_get_data (G_OBJECT (windows->data), "decor");
166
 
 
167
 
        if (d->decorated)
168
 
        {
169
 
 
170
 
#ifdef USE_METACITY
171
 
            if (d->draw == draw_window_decoration ||
172
 
                d->draw == meta_draw_window_decoration)
173
 
                d->draw = theme_draw_window_decoration;
174
 
#endif
175
 
 
176
 
        }
177
 
 
178
 
        update_window_decoration (WNCK_WINDOW (windows->data));
179
 
        windows = windows->next;
180
 
    }
181
 
 
182
 
    /* Update switcher window */
183
 
 
184
 
    if (switcher_window &&
185
 
        get_window_prop (switcher_window->prop_xid,
186
 
                         select_window_atom, &select))
187
 
    {
188
 
        decor_t *d = switcher_window;
189
 
        /* force size update */
190
 
        d->context = NULL;
191
 
        d->width = d->height = 0;
192
 
 
193
 
        update_switcher_window (d->prop_xid, select);
194
 
    }
195
 
}
196
 
 
197
 
void
198
 
restack_window (WnckWindow *win,
199
 
                int        stack_mode)
200
 
{
201
 
    Display    *xdisplay;
202
 
    GdkDisplay *gdkdisplay;
203
 
    GdkScreen  *screen;
204
 
    Window     xroot;
205
 
    XEvent     ev;
206
 
 
207
 
    gdkdisplay = gdk_display_get_default ();
208
 
    xdisplay   = GDK_DISPLAY_XDISPLAY (gdkdisplay);
209
 
    screen     = gdk_display_get_default_screen (gdkdisplay);
210
 
    xroot      = RootWindowOfScreen (gdk_x11_screen_get_xscreen (screen));
211
 
 
212
 
    if (action_menu_mapped)
213
 
    {
214
 
        gtk_object_destroy (GTK_OBJECT (action_menu));
215
 
        action_menu_mapped = FALSE;
216
 
        action_menu = NULL;
217
 
        return;
218
 
    }
219
 
 
220
 
    ev.xclient.type    = ClientMessage;
221
 
    ev.xclient.display = xdisplay;
222
 
 
223
 
    ev.xclient.serial     = 0;
224
 
    ev.xclient.send_event = TRUE;
225
 
 
226
 
    ev.xclient.window       = wnck_window_get_xid (win);
227
 
    ev.xclient.message_type = restack_window_atom;
228
 
    ev.xclient.format       = 32;
229
 
 
230
 
    ev.xclient.data.l[0] = 2;
231
 
    ev.xclient.data.l[1] = None;
232
 
    ev.xclient.data.l[2] = stack_mode;
233
 
    ev.xclient.data.l[3] = 0;
234
 
    ev.xclient.data.l[4] = 0;
235
 
 
236
 
    XSendEvent (xdisplay, xroot, FALSE,
237
 
                SubstructureRedirectMask | SubstructureNotifyMask,
238
 
                &ev);
239
 
 
240
 
    XSync (xdisplay, FALSE);
241
 
}
242
 
 
243
 
 
244
 
void
245
 
add_frame_window (WnckWindow *win,
246
 
                  Window     frame,
247
 
                  Bool       mode)
248
 
{
249
 
    Display              *xdisplay;
250
 
    XSetWindowAttributes attr;
251
 
    gulong               xid = wnck_window_get_xid (win);
252
 
    decor_t              *d = g_object_get_data (G_OBJECT (win), "decor");
253
 
    gint                 i, j;
254
 
 
255
 
    xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
256
 
 
257
 
    /* If we have already done this, there is no need to do it again, except
258
 
     * if the property changed.
259
 
     *
260
 
     * The reason this check is here is because sometimes the PropertyNotify X
261
 
     * event can come a bit after the property on the window is actually set
262
 
     * which might result in this function being called twice - once by
263
 
     * wnck through window_opened and once through our X event handler
264
 
     * event_filter_func
265
 
     */
266
 
 
267
 
    if (d->created && mode && d->frame_window)
268
 
        return;
269
 
 
270
 
    d->active = wnck_window_is_active (win);
271
 
    d->win = win;
272
 
    d->frame = gwd_get_decor_frame (get_frame_type (wnck_window_get_window_type (win)));
273
 
    d->last_pos_entered = NULL;
274
 
 
275
 
    attr.event_mask = ButtonPressMask | EnterWindowMask |
276
 
                      LeaveWindowMask | ExposureMask;
277
 
    attr.override_redirect = TRUE;
278
 
 
279
 
    gdk_error_trap_push ();
280
 
 
281
 
    if (mode)
282
 
    {
283
 
        GdkColormap *colormap;
284
 
 
285
 
        d->frame_window = create_gdk_window (frame);
286
 
        d->decor_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
287
 
 
288
 
        colormap = get_colormap_for_drawable (GDK_DRAWABLE (d->frame_window));
289
 
 
290
 
        d->decor_image = gtk_image_new ();
291
 
 
292
 
        gtk_widget_set_colormap (d->decor_window, colormap);
293
 
        gtk_widget_set_colormap (d->decor_image, colormap);
294
 
 
295
 
        d->decor_event_box = gtk_event_box_new ();
296
 
        gtk_event_box_set_visible_window (GTK_EVENT_BOX (d->decor_event_box),
297
 
                                          FALSE);
298
 
        gtk_widget_set_events (d->decor_event_box, GDK_BUTTON_PRESS_MASK |
299
 
                                                   GDK_BUTTON_RELEASE_MASK |
300
 
                                                   GDK_POINTER_MOTION_MASK);
301
 
 
302
 
        g_signal_connect (G_OBJECT (d->decor_event_box), "button-press-event",
303
 
                          G_CALLBACK (frame_handle_button_press),
304
 
                          (gpointer) (d));
305
 
 
306
 
        g_signal_connect (G_OBJECT (d->decor_event_box), "button-release-event",
307
 
                          G_CALLBACK (frame_handle_button_release),
308
 
                          (gpointer) (d));
309
 
 
310
 
        g_signal_connect (G_OBJECT (d->decor_event_box), "motion-notify-event",
311
 
                          G_CALLBACK (frame_handle_motion),
312
 
                          (gpointer) (d));
313
 
 
314
 
        gtk_container_add (GTK_CONTAINER (d->decor_event_box), d->decor_image);
315
 
        gtk_event_box_set_above_child (GTK_EVENT_BOX (d->decor_event_box), TRUE);
316
 
        gtk_widget_show_all (d->decor_event_box);
317
 
        gtk_window_set_decorated (GTK_WINDOW (d->decor_window), FALSE);
318
 
        gtk_window_set_default_size (GTK_WINDOW (d->decor_window), 1000, 1000);
319
 
        gtk_container_add (GTK_CONTAINER (d->decor_window), d->decor_event_box);
320
 
 
321
 
        /* Assumed realization happens here */
322
 
 
323
 
        g_signal_connect (G_OBJECT (d->decor_window), "realize",
324
 
                          G_CALLBACK (frame_window_realized), (gpointer) d);
325
 
 
326
 
        gtk_widget_show_all (d->decor_window);
327
 
        gtk_widget_show (d->decor_window);
328
 
 
329
 
        g_object_set_data (G_OBJECT (d->frame_window),
330
 
                           "client_wnck_window", win);
331
 
    }
332
 
    else
333
 
    {
334
 
        d->frame_window = NULL;
335
 
 
336
 
        for (i = 0; i < 3; i++)
337
 
        {
338
 
            for (j = 0; j < 3; j++)
339
 
            {
340
 
                d->event_windows[i][j].window =
341
 
                XCreateWindow (xdisplay,
342
 
                               frame,
343
 
                               0, 0, 1, 1, 0,
344
 
                               CopyFromParent, CopyFromParent, CopyFromParent,
345
 
                               CWOverrideRedirect | CWEventMask, &attr);
346
 
 
347
 
                if (cursor[i][j].cursor)
348
 
                    XDefineCursor (xdisplay, d->event_windows[i][j].window,
349
 
                    cursor[i][j].cursor);
350
 
            }
351
 
        }
352
 
 
353
 
        attr.event_mask |= ButtonReleaseMask;
354
 
 
355
 
        for (i = 0; i < BUTTON_NUM; i++)
356
 
        {
357
 
            d->button_windows[i].window =
358
 
            XCreateWindow (xdisplay,
359
 
                           frame,
360
 
                           0, 0, 1, 1, 0,
361
 
                           CopyFromParent, CopyFromParent, CopyFromParent,
362
 
                           CWOverrideRedirect | CWEventMask, &attr);
363
 
 
364
 
            d->button_states[i] = 0;
365
 
        }
366
 
    }
367
 
 
368
 
    gdk_display_sync (gdk_display_get_default ());
369
 
    if (!gdk_error_trap_pop ())
370
 
    {
371
 
        if (get_mwm_prop (xid) & (MWM_DECOR_ALL | MWM_DECOR_TITLE))
372
 
            d->decorated = TRUE;
373
 
 
374
 
        for (i = 0; i < 3; i++)
375
 
            for (j = 0; j < 3; j++)
376
 
            {
377
 
                Window win = d->event_windows[i][j].window;
378
 
                g_hash_table_insert (frame_table,
379
 
                                     GINT_TO_POINTER (win),
380
 
                                     GINT_TO_POINTER (xid));
381
 
            }
382
 
 
383
 
        for (i = 0; i < BUTTON_NUM; i++)
384
 
            g_hash_table_insert (frame_table,
385
 
                                 GINT_TO_POINTER (d->button_windows[i].window),
386
 
                                 GINT_TO_POINTER (xid));
387
 
 
388
 
        if (d->frame_window)
389
 
        {
390
 
            g_hash_table_insert (frame_table,
391
 
                                 GINT_TO_POINTER (frame),
392
 
                                 GINT_TO_POINTER (xid));
393
 
        }
394
 
        update_window_decoration_state (win);
395
 
        update_window_decoration_actions (win);
396
 
        update_window_decoration_icon (win);
397
 
        update_window_decoration_size (win);
398
 
 
399
 
        update_event_windows (win);
400
 
    }
401
 
    else
402
 
    {
403
 
        for (i = 0; i < 3; i++)
404
 
            for (j = 0; j < 3; j++)
405
 
                d->event_windows[i][j].window = None;
406
 
    }
407
 
 
408
 
    d->created = TRUE;
409
 
}
410
 
 
411
 
void
412
 
remove_frame_window (WnckWindow *win)
413
 
{
414
 
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
415
 
    Display *xdisplay;
416
 
 
417
 
    xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
418
 
 
419
 
    if (d->pixmap)
420
 
    {
421
 
        g_object_unref (G_OBJECT (d->pixmap));
422
 
        d->pixmap = NULL;
423
 
    }
424
 
 
425
 
    if (d->buffer_pixmap)
426
 
    {
427
 
        g_object_unref (G_OBJECT (d->buffer_pixmap));
428
 
        d->buffer_pixmap = NULL;
429
 
    }
430
 
 
431
 
    if (d->cr)
432
 
    {
433
 
        cairo_destroy (d->cr);
434
 
        d->cr = NULL;
435
 
    }
436
 
 
437
 
    if (d->picture && !d->frame_window)
438
 
    {
439
 
        XRenderFreePicture (xdisplay, d->picture);
440
 
        d->picture = 0;
441
 
    }
442
 
 
443
 
    if (d->name)
444
 
    {
445
 
        g_free (d->name);
446
 
        d->name = NULL;
447
 
    }
448
 
 
449
 
    if (d->layout)
450
 
    {
451
 
        g_object_unref (G_OBJECT (d->layout));
452
 
        d->layout = NULL;
453
 
    }
454
 
 
455
 
    if (d->icon)
456
 
    {
457
 
        cairo_pattern_destroy (d->icon);
458
 
        d->icon = NULL;
459
 
    }
460
 
 
461
 
    if (d->icon_pixmap)
462
 
    {
463
 
        g_object_unref (G_OBJECT (d->icon_pixmap));
464
 
        d->icon_pixmap = NULL;
465
 
    }
466
 
 
467
 
    if (d->icon_pixbuf)
468
 
    {
469
 
        g_object_unref (G_OBJECT (d->icon_pixbuf));
470
 
        d->icon_pixbuf = NULL;
471
 
    }
472
 
 
473
 
    if (d->force_quit_dialog)
474
 
    {
475
 
        GtkWidget *dialog = d->force_quit_dialog;
476
 
 
477
 
        d->force_quit_dialog = NULL;
478
 
        gtk_widget_destroy (dialog);
479
 
    }
480
 
 
481
 
    if (d->frame_window)
482
 
    {
483
 
        gdk_window_destroy (d->frame_window);
484
 
        d->frame_window = NULL;
485
 
    }
486
 
 
487
 
    if (d->decor_image)
488
 
    {
489
 
        g_object_unref (d->decor_image);
490
 
        d->decor_image = NULL;
491
 
    }
492
 
 
493
 
    if (d->decor_event_box)
494
 
    {
495
 
        g_object_unref (d->decor_event_box);
496
 
        d->decor_event_box = NULL;
497
 
    }
498
 
 
499
 
    if (d->decor_window)
500
 
    {
501
 
        g_object_unref (d->decor_window);
502
 
        d->decor_window = NULL;
503
 
    }
504
 
 
505
 
    if (d->frame)
506
 
    {
507
 
        gwd_decor_frame_unref (d->frame);
508
 
        d->frame = NULL;
509
 
    }
510
 
 
511
 
    gdk_error_trap_push ();
512
 
    XDeleteProperty (xdisplay, wnck_window_get_xid (win), win_decor_atom);
513
 
    gdk_display_sync (gdk_display_get_default ());
514
 
    gdk_error_trap_pop ();
515
 
 
516
 
    d->width  = 0;
517
 
    d->height = 0;
518
 
 
519
 
    d->decorated = FALSE;
520
 
 
521
 
    d->state   = 0;
522
 
    d->actions = 0;
523
 
 
524
 
    d->context = NULL;
525
 
    d->shadow  = NULL;
526
 
 
527
 
    draw_list = g_slist_remove (draw_list, d);
528
 
}
529
 
 
530
 
void
531
 
connect_window (WnckWindow *win)
532
 
{
533
 
    g_signal_connect_object (win, "name_changed",
534
 
                             G_CALLBACK (window_name_changed),
535
 
                             0, 0);
536
 
    g_signal_connect_object (win, "geometry_changed",
537
 
                             G_CALLBACK (window_geometry_changed),
538
 
                             0, 0);
539
 
    g_signal_connect_object (win, "icon_changed",
540
 
                             G_CALLBACK (window_icon_changed),
541
 
                             0, 0);
542
 
    g_signal_connect_object (win, "state_changed",
543
 
                             G_CALLBACK (window_state_changed),
544
 
                             0, 0);
545
 
    g_signal_connect_object (win, "actions_changed",
546
 
                             G_CALLBACK (window_actions_changed),
547
 
                             0, 0);
548
 
}
549
 
 
550
 
static void
551
 
active_window_changed (WnckScreen *screen)
552
 
{
553
 
    WnckWindow *win;
554
 
    decor_t    *d;
555
 
 
556
 
    win = wnck_screen_get_previously_active_window (screen);
557
 
    if (win)
558
 
    {
559
 
        d = g_object_get_data (G_OBJECT (win), "decor");
560
 
        if (d && d->pixmap)
561
 
        {
562
 
            d->active = wnck_window_is_active (win);
563
 
            queue_decor_draw (d);
564
 
        }
565
 
    }
566
 
 
567
 
    win = wnck_screen_get_active_window (screen);
568
 
    if (win)
569
 
    {
570
 
        d = g_object_get_data (G_OBJECT (win), "decor");
571
 
        if (d && d->pixmap)
572
 
        {
573
 
            d->active = wnck_window_is_active (win);
574
 
            queue_decor_draw (d);
575
 
        }
576
 
    }
577
 
}
578
 
 
579
 
void
580
 
window_opened (WnckScreen *screen,
581
 
               WnckWindow *win)
582
 
{
583
 
    decor_t      *d;
584
 
    Window       window;
585
 
    gulong       xid;
586
 
    unsigned int i, j;
587
 
 
588
 
    static event_callback callback[3][3] = {
589
 
        { top_left_event,    top_event,    top_right_event    },
590
 
        { left_event,        title_event,  right_event        },
591
 
        { bottom_left_event, bottom_event, bottom_right_event }
592
 
    };
593
 
    static event_callback button_callback[BUTTON_NUM] = {
594
 
        close_button_event,
595
 
        max_button_event,
596
 
        min_button_event,
597
 
        menu_button_event,
598
 
        shade_button_event,
599
 
        above_button_event,
600
 
        stick_button_event,
601
 
        unshade_button_event,
602
 
        unabove_button_event,
603
 
        unstick_button_event
604
 
    };
605
 
 
606
 
    d = calloc (1, sizeof (decor_t));
607
 
    if (!d)
608
 
        return;
609
 
 
610
 
    for (i = 0; i < 3; i++)
611
 
        for (j = 0; j < 3; j++)
612
 
            d->event_windows[i][j].callback = callback[i][j];
613
 
 
614
 
    for (i = 0; i < BUTTON_NUM; i++)
615
 
        d->button_windows[i].callback = button_callback[i];
616
 
 
617
 
    wnck_window_get_client_window_geometry (win, NULL, NULL,
618
 
                                            &d->client_width,
619
 
                                            &d->client_height);
620
 
 
621
 
    d->draw = theme_draw_window_decoration;
622
 
 
623
 
    d->created = FALSE;
624
 
    d->pixmap = NULL;
625
 
    d->cr = NULL;
626
 
    d->buffer_pixmap = NULL;
627
 
    d->picture = None;
628
 
 
629
 
    connect_window (win);
630
 
 
631
 
    g_object_set_data (G_OBJECT (win), "decor", d);
632
 
 
633
 
    xid = wnck_window_get_xid (win);
634
 
 
635
 
    if (get_window_prop (xid, frame_input_window_atom, &window))
636
 
    {
637
 
        add_frame_window (win, window, FALSE);
638
 
    }
639
 
    else if (get_window_prop (xid, frame_output_window_atom, &window))
640
 
    {
641
 
        add_frame_window (win, window, TRUE);
642
 
    }
643
 
}
644
 
 
645
 
void
646
 
window_closed (WnckScreen *screen,
647
 
               WnckWindow *win)
648
 
{
649
 
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
650
 
 
651
 
    if (d)
652
 
    {
653
 
        remove_frame_window (win);
654
 
        g_object_set_data (G_OBJECT (win), "decor", NULL);
655
 
        g_free (d);
656
 
    }
657
 
}
658
 
 
659
 
void
660
 
connect_screen (WnckScreen *screen)
661
 
{
662
 
    GList *windows;
663
 
 
664
 
    g_signal_connect_object (G_OBJECT (screen), "active_window_changed",
665
 
                             G_CALLBACK (active_window_changed),
666
 
                             0, 0);
667
 
    g_signal_connect_object (G_OBJECT (screen), "window_opened",
668
 
                             G_CALLBACK (window_opened),
669
 
                             0, 0);
670
 
    g_signal_connect_object (G_OBJECT (screen), "window_closed",
671
 
                             G_CALLBACK (window_closed),
672
 
                             0, 0);
673
 
 
674
 
    windows = wnck_screen_get_windows (screen);
675
 
    while (windows != NULL)
676
 
    {
677
 
        window_opened (screen, windows->data);
678
 
        windows = windows->next;
679
 
    }
680
 
}