~dbarth/compiz/reworked-fix-744104

« back to all changes in this revision

Viewing changes to unity/unity_window_decorator/src/wnck.c

  • Committer: David Barth
  • Date: 2011-04-05 20:20:54 UTC
  • Revision ID: david.barth@canonical.com-20110405202054-fnh0y5t2s228mf4k
re-integrate the unity-window-decorator, for real this time

Show diffs side-by-side

added added

removed removed

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