~dbarth/compiz/reworked-fix-744104

« back to all changes in this revision

Viewing changes to unity/unity_window_decorator/src/decorator.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 const PangoFontDescription *
 
4
get_titlebar_font (void)
 
5
{
 
6
    if (use_system_font)
 
7
    {
 
8
        return NULL;
 
9
    }
 
10
    else
 
11
        return titlebar_font;
 
12
}
 
13
 
 
14
void
 
15
update_titlebar_font (void)
 
16
{
 
17
    const PangoFontDescription *font_desc;
 
18
    PangoFontMetrics           *metrics;
 
19
    PangoLanguage              *lang;
 
20
 
 
21
    font_desc = get_titlebar_font ();
 
22
    if (!font_desc)
 
23
    {
 
24
        GtkStyle *default_style;
 
25
 
 
26
        default_style = gtk_widget_get_default_style ();
 
27
        font_desc = default_style->font_desc;
 
28
    }
 
29
 
 
30
    pango_context_set_font_description (pango_context, font_desc);
 
31
 
 
32
    lang    = pango_context_get_language (pango_context);
 
33
    metrics = pango_context_get_metrics (pango_context, font_desc, lang);
 
34
 
 
35
    text_height = PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
 
36
                                pango_font_metrics_get_descent (metrics));
 
37
 
 
38
    pango_font_metrics_unref (metrics);
 
39
}
 
40
 
 
41
void
 
42
update_event_windows (WnckWindow *win)
 
43
{
 
44
    Display *xdisplay;
 
45
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
 
46
    gint    x0, y0, width, height, x, y, w, h;
 
47
    gint    i, j, k, l;
 
48
    gint    actions = d->actions;
 
49
 
 
50
    xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 
51
 
 
52
    wnck_window_get_client_window_geometry (win, &x0, &y0, &width, &height);
 
53
 
 
54
    if (d->state & WNCK_WINDOW_STATE_SHADED)
 
55
    {
 
56
        height = 0;
 
57
        k = l = 1;
 
58
    }
 
59
    else
 
60
    {
 
61
        k = 0;
 
62
        l = 2;
 
63
    }
 
64
 
 
65
    gdk_error_trap_push ();
 
66
 
 
67
    for (i = 0; i < 3; i++)
 
68
    {
 
69
        static guint event_window_actions[3][3] = {
 
70
            {
 
71
                WNCK_WINDOW_ACTION_RESIZE,
 
72
                WNCK_WINDOW_ACTION_RESIZE,
 
73
                WNCK_WINDOW_ACTION_RESIZE
 
74
            }, {
 
75
                WNCK_WINDOW_ACTION_RESIZE,
 
76
                WNCK_WINDOW_ACTION_MOVE,
 
77
                WNCK_WINDOW_ACTION_RESIZE
 
78
            }, {
 
79
                WNCK_WINDOW_ACTION_RESIZE,
 
80
                WNCK_WINDOW_ACTION_RESIZE,
 
81
                WNCK_WINDOW_ACTION_RESIZE
 
82
            }
 
83
        };
 
84
 
 
85
        for (j = 0; j < 3; j++)
 
86
        {
 
87
            w = 0;
 
88
            h = 0;
 
89
 
 
90
            if (actions & event_window_actions[i][j] && i >= k && i <= l)
 
91
                (*theme_get_event_window_position) (d, i, j, width, height,
 
92
                                                    &x, &y, &w, &h);
 
93
 
 
94
            if (d->frame_window)
 
95
            {
 
96
                BoxPtr box = &d->event_windows[i][j].pos;
 
97
                box->x1  = x;
 
98
                box->x2 = x + w;
 
99
                box->y1 = y;
 
100
                box->y2 = y + h;
 
101
            }
 
102
            else if (!d->frame_window && w != 0 && h != 0)
 
103
            {
 
104
                XMapWindow (xdisplay, d->event_windows[i][j].window);
 
105
                XMoveResizeWindow (xdisplay, d->event_windows[i][j].window,
 
106
                                   x, y, w, h);
 
107
            }
 
108
            else if (!d->frame_window)
 
109
            {
 
110
                XUnmapWindow (xdisplay, d->event_windows[i][j].window);
 
111
            }
 
112
        }
 
113
    }
 
114
 
 
115
    /* no button event windows if width is less than minimum width */
 
116
    if (width < ICON_SPACE + d->button_width)
 
117
        actions = 0;
 
118
 
 
119
    for (i = 0; i < BUTTON_NUM; i++)
 
120
    {
 
121
        static guint button_actions[BUTTON_NUM] = {
 
122
            WNCK_WINDOW_ACTION_CLOSE,
 
123
            WNCK_WINDOW_ACTION_MAXIMIZE,
 
124
            WNCK_WINDOW_ACTION_MINIMIZE,
 
125
            0,
 
126
            WNCK_WINDOW_ACTION_SHADE,
 
127
 
 
128
#ifdef HAVE_LIBWNCK_2_18_1
 
129
            WNCK_WINDOW_ACTION_ABOVE,
 
130
            WNCK_WINDOW_ACTION_STICK,
 
131
            WNCK_WINDOW_ACTION_UNSHADE,
 
132
            WNCK_WINDOW_ACTION_ABOVE,
 
133
            WNCK_WINDOW_ACTION_UNSTICK
 
134
#else
 
135
            0,
 
136
            0,
 
137
            0,
 
138
            0,
 
139
            0
 
140
#endif
 
141
 
 
142
        };
 
143
 
 
144
        if (d->frame_window &&
 
145
            button_actions[i] && !(actions & button_actions[i]))
 
146
        {
 
147
            memset (&d->button_windows[i].pos, 0, sizeof (Box));
 
148
        }
 
149
        else if (!d->frame_window &&
 
150
                 button_actions[i] && !(actions & button_actions[i]))
 
151
        {
 
152
            XUnmapWindow (xdisplay, d->button_windows[i].window);
 
153
            continue;
 
154
        }
 
155
 
 
156
        if (d->frame_window &&
 
157
            (*theme_get_button_position) (d, i, width, height, &x, &y, &w, &h))
 
158
        {
 
159
            BoxPtr box = &d->button_windows[i].pos;
 
160
            box->x1 = x;
 
161
            box->y1 = y;
 
162
            box->x2 = x + w;
 
163
            box->y2 = y + h;
 
164
        }
 
165
        else if (!d->frame_window &&
 
166
                 (*theme_get_button_position) (d, i, width, height,
 
167
                                               &x, &y, &w, &h))
 
168
        {
 
169
            Window win = d->button_windows[i].window;
 
170
            XMapWindow (xdisplay, win);
 
171
            XMoveResizeWindow (xdisplay, win, x, y, w, h);
 
172
        }
 
173
        else if (!d->frame_window)
 
174
        {
 
175
            XUnmapWindow (xdisplay, d->button_windows[i].window);
 
176
        }
 
177
    }
 
178
 
 
179
    gdk_display_sync (gdk_display_get_default ());
 
180
    gdk_error_trap_pop ();
 
181
}
 
182
 
 
183
#ifdef HAVE_WNCK_WINDOW_HAS_NAME
 
184
static const char *
 
185
wnck_window_get_real_name (WnckWindow *win)
 
186
{
 
187
    return wnck_window_has_name (win) ? wnck_window_get_name (win) : NULL;
 
188
}
 
189
#define wnck_window_get_name wnck_window_get_real_name
 
190
#endif
 
191
 
 
192
gint
 
193
max_window_name_width (WnckWindow *win)
 
194
{
 
195
    decor_t     *d = g_object_get_data (G_OBJECT (win), "decor");
 
196
    const gchar *name;
 
197
    gint        w;
 
198
 
 
199
    if (!d->layout)
 
200
    {
 
201
        d->layout = pango_layout_new (pango_context);
 
202
        if (!d->layout)
 
203
            return 0;
 
204
 
 
205
        pango_layout_set_wrap (d->layout, PANGO_WRAP_CHAR);
 
206
    }
 
207
 
 
208
    name = wnck_window_get_name (win);
 
209
    if (!name)
 
210
        return 0;
 
211
 
 
212
    pango_layout_set_auto_dir (d->layout, FALSE);
 
213
    pango_layout_set_width (d->layout, -1);
 
214
    pango_layout_set_text (d->layout, name, strlen (name));
 
215
    pango_layout_get_pixel_size (d->layout, &w, NULL);
 
216
 
 
217
    if (d->name)
 
218
        pango_layout_set_text (d->layout, d->name, strlen (d->name));
 
219
 
 
220
    return w + 6;
 
221
}
 
222
 
 
223
void
 
224
update_window_decoration_name (WnckWindow *win)
 
225
{
 
226
    decor_t         *d = g_object_get_data (G_OBJECT (win), "decor");
 
227
    const gchar     *name;
 
228
    glong           name_length;
 
229
    PangoLayoutLine *line;
 
230
 
 
231
    if (d->name)
 
232
    {
 
233
        g_free (d->name);
 
234
        d->name = NULL;
 
235
    }
 
236
 
 
237
    name = wnck_window_get_name (win);
 
238
    if (name && (name_length = strlen (name)))
 
239
    {
 
240
        gint w;
 
241
 
 
242
        if (theme_draw_window_decoration != draw_window_decoration)
 
243
        {
 
244
            w = SHRT_MAX;
 
245
        }
 
246
        else
 
247
        {
 
248
            gint width;
 
249
 
 
250
            wnck_window_get_client_window_geometry (win, NULL, NULL,
 
251
                                                    &width, NULL);
 
252
 
 
253
            w = width - ICON_SPACE - 2 - d->button_width;
 
254
            if (w < 1)
 
255
                w = 1;
 
256
        }
 
257
 
 
258
        pango_layout_set_auto_dir (d->layout, FALSE);
 
259
        pango_layout_set_width (d->layout, w * PANGO_SCALE);
 
260
        pango_layout_set_text (d->layout, name, name_length);
 
261
 
 
262
        line = pango_layout_get_line (d->layout, 0);
 
263
 
 
264
        name_length = line->length;
 
265
        if (pango_layout_get_line_count (d->layout) > 1)
 
266
        {
 
267
            if (name_length < 4)
 
268
            {
 
269
                pango_layout_set_text (d->layout, NULL, 0);
 
270
                return;
 
271
            }
 
272
 
 
273
            d->name = g_strndup (name, name_length);
 
274
            strcpy (d->name + name_length - 3, "...");
 
275
        }
 
276
        else
 
277
            d->name = g_strndup (name, name_length);
 
278
 
 
279
        pango_layout_set_text (d->layout, d->name, name_length);
 
280
    }
 
281
}
 
282
 
 
283
void
 
284
update_window_decoration_icon (WnckWindow *win)
 
285
{
 
286
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
 
287
 
 
288
    if (d->icon)
 
289
    {
 
290
        cairo_pattern_destroy (d->icon);
 
291
        d->icon = NULL;
 
292
    }
 
293
 
 
294
    if (d->icon_pixmap)
 
295
    {
 
296
        g_object_unref (G_OBJECT (d->icon_pixmap));
 
297
        d->icon_pixmap = NULL;
 
298
    }
 
299
 
 
300
    if (d->icon_pixbuf)
 
301
        g_object_unref (G_OBJECT (d->icon_pixbuf));
 
302
 
 
303
    d->icon_pixbuf = wnck_window_get_mini_icon (win);
 
304
    if (d->icon_pixbuf)
 
305
    {
 
306
        cairo_t *cr;
 
307
 
 
308
        g_object_ref (G_OBJECT (d->icon_pixbuf));
 
309
 
 
310
        if (d->frame_window)
 
311
            d->icon_pixmap = pixmap_new_from_pixbuf (d->icon_pixbuf,
 
312
                                                     24);
 
313
        else
 
314
            d->icon_pixmap = pixmap_new_from_pixbuf (d->icon_pixbuf,
 
315
                                                     32);
 
316
        cr = gdk_cairo_create (GDK_DRAWABLE (d->icon_pixmap));
 
317
        d->icon = cairo_pattern_create_for_surface (cairo_get_target (cr));
 
318
        cairo_destroy (cr);
 
319
    }
 
320
}
 
321
 
 
322
gboolean
 
323
update_window_decoration_size (WnckWindow *win)
 
324
{
 
325
    decor_t           *d = g_object_get_data (G_OBJECT (win), "decor");
 
326
    GdkPixmap         *pixmap, *buffer_pixmap = NULL;
 
327
    Picture           picture;
 
328
    gint              width, height;
 
329
    gint              x, y, w, h, name_width;
 
330
    Display           *xdisplay;
 
331
    XRenderPictFormat *format;
 
332
    int               depth;
 
333
 
 
334
    if (!d)
 
335
        return FALSE;
 
336
 
 
337
    xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 
338
 
 
339
    wnck_window_get_client_window_geometry (win, &x, &y, &w, &h);
 
340
 
 
341
    name_width = max_window_name_width (win);
 
342
 
 
343
    if (!(*theme_calc_decoration_size) (d, w, h, name_width, &width, &height))
 
344
    {
 
345
        update_window_decoration_name (win);
 
346
        return FALSE;
 
347
    }
 
348
 
 
349
    gdk_error_trap_push ();
 
350
 
 
351
    if (d->frame_window)
 
352
        depth = gdk_drawable_get_depth (GDK_DRAWABLE (d->frame_window));
 
353
    else
 
354
        depth = 32;
 
355
 
 
356
    pixmap = create_pixmap (width, height, depth);
 
357
 
 
358
    gdk_flush ();
 
359
 
 
360
    if (!pixmap || gdk_error_trap_pop ())
 
361
    {
 
362
        memset (pixmap, 0, sizeof (pixmap));
 
363
        return FALSE;
 
364
    }
 
365
 
 
366
    gdk_error_trap_push ();
 
367
 
 
368
    buffer_pixmap = create_pixmap (width, height, depth);
 
369
 
 
370
    gdk_flush ();
 
371
 
 
372
    if (!buffer_pixmap || gdk_error_trap_pop ())
 
373
    {
 
374
        memset (buffer_pixmap, 0, sizeof (buffer_pixmap));
 
375
        g_object_unref (G_OBJECT (pixmap));
 
376
        return FALSE;
 
377
    }
 
378
 
 
379
    format = get_format_for_drawable (d, GDK_DRAWABLE (buffer_pixmap));
 
380
    picture = XRenderCreatePicture (xdisplay, GDK_PIXMAP_XID (buffer_pixmap),
 
381
                                    format, 0, NULL);
 
382
 
 
383
    if (d->pixmap)
 
384
        g_object_unref (G_OBJECT (d->pixmap));
 
385
 
 
386
    if (d->buffer_pixmap)
 
387
        g_object_unref (G_OBJECT (d->buffer_pixmap));
 
388
 
 
389
    if (d->picture)
 
390
        XRenderFreePicture (xdisplay, d->picture);
 
391
 
 
392
    if (d->cr)
 
393
        cairo_destroy (d->cr);
 
394
 
 
395
    d->pixmap        = pixmap;
 
396
    d->buffer_pixmap = buffer_pixmap;
 
397
    d->cr            = gdk_cairo_create (pixmap);
 
398
 
 
399
    d->picture = picture;
 
400
 
 
401
    d->width  = width;
 
402
    d->height = height;
 
403
 
 
404
    d->prop_xid = wnck_window_get_xid (win);
 
405
 
 
406
    update_window_decoration_name (win);
 
407
 
 
408
    queue_decor_draw (d);
 
409
 
 
410
    return TRUE;
 
411
}
 
412
 
 
413
void
 
414
draw_border_shape (Display         *xdisplay,
 
415
                   Pixmap          pixmap,
 
416
                   Picture         picture,
 
417
                   int             width,
 
418
                   int             height,
 
419
                   decor_context_t *c,
 
420
                   void            *closure)
 
421
{
 
422
    static XRenderColor white = { 0xffff, 0xffff, 0xffff, 0xffff };
 
423
    GdkColormap         *colormap;
 
424
    decor_t             d;
 
425
    double              save_decoration_alpha;
 
426
 
 
427
    memset (&d, 0, sizeof (d));
 
428
 
 
429
    d.pixmap  = gdk_pixmap_foreign_new_for_display (gdk_display_get_default (),
 
430
                                                    pixmap);
 
431
    d.width   = width;
 
432
    d.height  = height;
 
433
    d.active  = TRUE;
 
434
    d.draw    = theme_draw_window_decoration;
 
435
    d.picture = picture;
 
436
    d.context = c;
 
437
 
 
438
    /* we use closure argument if maximized */
 
439
    if (closure)
 
440
        d.state |=
 
441
            WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY |
 
442
            WNCK_WINDOW_STATE_MAXIMIZED_VERTICALLY;
 
443
 
 
444
    decor_get_default_layout (c, 1, 1, &d.border_layout);
 
445
 
 
446
    colormap = get_colormap_for_drawable (GDK_DRAWABLE (d.pixmap));
 
447
    gdk_drawable_set_colormap (d.pixmap, colormap);
 
448
 
 
449
    /* create shadow from opaque decoration */
 
450
    save_decoration_alpha = decoration_alpha;
 
451
    decoration_alpha = 1.0;
 
452
 
 
453
    (*d.draw) (&d);
 
454
 
 
455
    decoration_alpha = save_decoration_alpha;
 
456
 
 
457
    XRenderFillRectangle (xdisplay, PictOpSrc, picture, &white,
 
458
                          c->left_space,
 
459
                          c->top_space,
 
460
                          width - c->left_space - c->right_space,
 
461
                          height - c->top_space - c->bottom_space);
 
462
 
 
463
    g_object_unref (G_OBJECT (d.pixmap));
 
464
}
 
465
 
 
466
int
 
467
update_shadow (void)
 
468
{
 
469
    decor_shadow_options_t opt_active_shadow;
 
470
    decor_shadow_options_t opt_inactive_shadow;
 
471
    decor_shadow_options_t opt_no_shadow;
 
472
    Display                *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 
473
    GdkDisplay             *display = gdk_display_get_default ();
 
474
    GdkScreen              *screen = gdk_display_get_default_screen (display);
 
475
 
 
476
    opt_active_shadow.shadow_radius  = shadow_radius;
 
477
    opt_active_shadow.shadow_opacity = shadow_opacity;
 
478
 
 
479
    memcpy (opt_active_shadow.shadow_color, shadow_color, sizeof (shadow_color));
 
480
 
 
481
    opt_active_shadow.shadow_offset_x = shadow_offset_x;
 
482
    opt_active_shadow.shadow_offset_y = shadow_offset_y;
 
483
 
 
484
    opt_inactive_shadow.shadow_radius  = shadow_radius;
 
485
    opt_inactive_shadow.shadow_opacity = shadow_opacity;
 
486
 
 
487
    memcpy (opt_inactive_shadow.shadow_color, shadow_color, sizeof (shadow_color));
 
488
 
 
489
    opt_inactive_shadow.shadow_offset_x = shadow_offset_x;
 
490
    opt_inactive_shadow.shadow_offset_y = shadow_offset_y;
 
491
 
 
492
    opt_no_shadow.shadow_radius  = 0;
 
493
    opt_no_shadow.shadow_opacity = 0;
 
494
 
 
495
    opt_no_shadow.shadow_offset_x = 0;
 
496
    opt_no_shadow.shadow_offset_y = 0;
 
497
 
 
498
    if (no_border_shadow)
 
499
    {
 
500
        decor_shadow_destroy (xdisplay, no_border_shadow);
 
501
        no_border_shadow = NULL;
 
502
    }
 
503
 
 
504
    no_border_shadow = decor_shadow_create (xdisplay,
 
505
                                            gdk_x11_screen_get_xscreen (screen),
 
506
                                            1, 1,
 
507
                                            0,
 
508
                                            0,
 
509
                                            0,
 
510
                                            0,
 
511
                                            0, 0, 0, 0,
 
512
                                            &opt_inactive_shadow,
 
513
                                            &shadow_context,
 
514
                                            decor_draw_simple,
 
515
                                            0);
 
516
 
 
517
    if (border_active_shadow)
 
518
    {
 
519
        decor_shadow_destroy (xdisplay, border_active_shadow);
 
520
        border_active_shadow = NULL;
 
521
    }
 
522
 
 
523
    border_active_shadow = (*theme_update_shadow) (SHADOW_TYPE_ACTIVE_NORMAL);
 
524
 
 
525
    if (!border_active_shadow)
 
526
        border_active_shadow = cairo_update_shadow (SHADOW_TYPE_ACTIVE_NORMAL);
 
527
 
 
528
    if (border_inactive_shadow)
 
529
    {
 
530
        decor_shadow_destroy (xdisplay, border_inactive_shadow);
 
531
        border_inactive_shadow = NULL;
 
532
    }
 
533
 
 
534
    border_inactive_shadow = (*theme_update_shadow) (SHADOW_TYPE_INACTIVE_NORMAL);
 
535
 
 
536
    if (!border_inactive_shadow)
 
537
        border_inactive_shadow = cairo_update_shadow (SHADOW_TYPE_INACTIVE_NORMAL);
 
538
 
 
539
    if (border_no_shadow)
 
540
    {
 
541
        decor_shadow_destroy (xdisplay, border_no_shadow);
 
542
        border_no_shadow = NULL;
 
543
    }
 
544
 
 
545
    border_no_shadow = decor_shadow_create (xdisplay,
 
546
                                         gdk_x11_screen_get_xscreen (screen),
 
547
                                         1, 1,
 
548
                                         _win_extents.left,
 
549
                                         _win_extents.right,
 
550
                                         _win_extents.top + titlebar_height,
 
551
                                         _win_extents.bottom,
 
552
                                         _win_extents.left -
 
553
                                         TRANSLUCENT_CORNER_SIZE,
 
554
                                         _win_extents.right -
 
555
                                         TRANSLUCENT_CORNER_SIZE,
 
556
                                         _win_extents.top + titlebar_height -
 
557
                                         TRANSLUCENT_CORNER_SIZE,
 
558
                                         _win_extents.bottom -
 
559
                                         TRANSLUCENT_CORNER_SIZE,
 
560
                                         &opt_no_shadow,
 
561
                                         &window_context_no_shadow,
 
562
                                         draw_border_shape,
 
563
                                         0);
 
564
 
 
565
    decor_context_t *context = &window_context_no_shadow;
 
566
 
 
567
 
 
568
    if (max_border_active_shadow)
 
569
    {
 
570
        decor_shadow_destroy (xdisplay, max_border_active_shadow);
 
571
        max_border_active_shadow = NULL;
 
572
    }
 
573
 
 
574
    max_border_active_shadow = (*theme_update_shadow) (SHADOW_TYPE_ACTIVE_MAX);
 
575
 
 
576
    if (!max_border_active_shadow)
 
577
        max_border_active_shadow = cairo_update_shadow (SHADOW_TYPE_ACTIVE_MAX);
 
578
 
 
579
    if (max_border_inactive_shadow)
 
580
    {
 
581
        decor_shadow_destroy (xdisplay, max_border_inactive_shadow);
 
582
        max_border_inactive_shadow = NULL;
 
583
    }
 
584
 
 
585
    max_border_inactive_shadow = (*theme_update_shadow) (SHADOW_TYPE_INACTIVE_MAX);
 
586
 
 
587
    if (!max_border_inactive_shadow)
 
588
        max_border_inactive_shadow = cairo_update_shadow (SHADOW_TYPE_INACTIVE_MAX);
 
589
 
 
590
    if (max_border_no_shadow)
 
591
    {
 
592
        decor_shadow_destroy (xdisplay, max_border_active_shadow);
 
593
        max_border_active_shadow = NULL;
 
594
    }
 
595
 
 
596
    max_border_no_shadow =
 
597
        decor_shadow_create (xdisplay,
 
598
                             gdk_x11_screen_get_xscreen (screen),
 
599
                             1, 1,
 
600
                             _max_win_extents.left,
 
601
                             _max_win_extents.right,
 
602
                             _max_win_extents.top + max_titlebar_height,
 
603
                             _max_win_extents.bottom,
 
604
                             _max_win_extents.left - TRANSLUCENT_CORNER_SIZE,
 
605
                             _max_win_extents.right - TRANSLUCENT_CORNER_SIZE,
 
606
                             _max_win_extents.top + max_titlebar_height -
 
607
                             TRANSLUCENT_CORNER_SIZE,
 
608
                             _max_win_extents.bottom - TRANSLUCENT_CORNER_SIZE,
 
609
                             &opt_no_shadow,
 
610
                             &max_window_context_no_shadow,
 
611
                             draw_border_shape,
 
612
                             (void *) 1);
 
613
 
 
614
    if (switcher_shadow)
 
615
    {
 
616
        decor_shadow_destroy (xdisplay, switcher_shadow);
 
617
        switcher_shadow = NULL;
 
618
    }
 
619
 
 
620
    switcher_shadow = decor_shadow_create (xdisplay,
 
621
                                           gdk_x11_screen_get_xscreen (screen),
 
622
                                           1, 1,
 
623
                                           _switcher_extents.left,
 
624
                                           _switcher_extents.right,
 
625
                                           _switcher_extents.top,
 
626
                                           _switcher_extents.bottom,
 
627
                                           _switcher_extents.left -
 
628
                                           TRANSLUCENT_CORNER_SIZE,
 
629
                                           _switcher_extents.right -
 
630
                                           TRANSLUCENT_CORNER_SIZE,
 
631
                                           _switcher_extents.top -
 
632
                                           TRANSLUCENT_CORNER_SIZE,
 
633
                                           _switcher_extents.bottom -
 
634
                                           TRANSLUCENT_CORNER_SIZE,
 
635
                                           &opt_inactive_shadow,
 
636
                                           &switcher_context,
 
637
                                           decor_draw_simple,
 
638
                                           0);
 
639
 
 
640
    return 1;
 
641
}
 
642
 
 
643
void
 
644
update_window_decoration (WnckWindow *win)
 
645
{
 
646
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
 
647
 
 
648
    if (d->decorated)
 
649
    {
 
650
        /* force size update */
 
651
        d->context = NULL;
 
652
        d->width = d->height = 0;
 
653
 
 
654
        update_window_decoration_size (win);
 
655
        update_event_windows (win);
 
656
    }
 
657
}
 
658
 
 
659
void
 
660
update_window_decoration_state (WnckWindow *win)
 
661
{
 
662
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
 
663
 
 
664
    d->state = wnck_window_get_state (win);
 
665
}
 
666
 
 
667
void
 
668
update_window_decoration_actions (WnckWindow *win)
 
669
{
 
670
    decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
 
671
 
 
672
    d->actions = wnck_window_get_actions (win);
 
673
}
 
674
 
 
675
static gboolean
 
676
draw_decor_list (void *data)
 
677
{
 
678
    GSList  *list;
 
679
    decor_t *d;
 
680
 
 
681
    draw_idle_id = 0;
 
682
 
 
683
    for (list = draw_list; list; list = list->next)
 
684
    {
 
685
        d = (decor_t *) list->data;
 
686
        (*d->draw) (d);
 
687
    }
 
688
 
 
689
    g_slist_free (draw_list);
 
690
    draw_list = NULL;
 
691
 
 
692
    return FALSE;
 
693
}
 
694
 
 
695
void
 
696
queue_decor_draw (decor_t *d)
 
697
{
 
698
    if (g_slist_find (draw_list, d))
 
699
        return;
 
700
 
 
701
    draw_list = g_slist_append (draw_list, d);
 
702
 
 
703
    if (!draw_idle_id)
 
704
        draw_idle_id = g_idle_add (draw_decor_list, NULL);
 
705
}
 
706
 
 
707
void
 
708
update_default_decorations (GdkScreen *screen)
 
709
{
 
710
    long            data[256];
 
711
    Window          xroot;
 
712
    GdkDisplay      *gdkdisplay = gdk_display_get_default ();
 
713
    Display         *xdisplay = gdk_x11_display_get_xdisplay (gdkdisplay);
 
714
    Atom            bareAtom, normalAtom, activeAtom;
 
715
    decor_t         d;
 
716
    gint            nQuad;
 
717
    decor_quad_t    quads[N_QUADS_MAX];
 
718
    decor_extents_t extents = _win_extents;
 
719
 
 
720
    xroot = RootWindowOfScreen (gdk_x11_screen_get_xscreen (screen));
 
721
 
 
722
    bareAtom   = XInternAtom (xdisplay, DECOR_BARE_ATOM_NAME, FALSE);
 
723
    normalAtom = XInternAtom (xdisplay, DECOR_NORMAL_ATOM_NAME, FALSE);
 
724
    activeAtom = XInternAtom (xdisplay, DECOR_ACTIVE_ATOM_NAME, FALSE);
 
725
 
 
726
    if (no_border_shadow)
 
727
    {
 
728
        decor_layout_t layout;
 
729
 
 
730
        decor_get_default_layout (&shadow_context, 1, 1, &layout);
 
731
 
 
732
        nQuad = decor_set_lSrStSbS_window_quads (quads, &shadow_context,
 
733
                                                 &layout);
 
734
 
 
735
        decor_quads_to_property (data, no_border_shadow->pixmap,
 
736
                                 &_shadow_extents, &_shadow_extents,
 
737
                                 &_shadow_extents, &_shadow_extents,
 
738
                                 0, 0, quads, nQuad);
 
739
 
 
740
        XChangeProperty (xdisplay, xroot,
 
741
                         bareAtom,
 
742
                         XA_INTEGER,
 
743
                         32, PropModeReplace, (guchar *) data,
 
744
                         BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
 
745
 
 
746
        if (minimal)
 
747
        {
 
748
            XChangeProperty (xdisplay, xroot,
 
749
                             normalAtom,
 
750
                             XA_INTEGER,
 
751
                             32, PropModeReplace, (guchar *) data,
 
752
                             BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
 
753
            XChangeProperty (xdisplay, xroot,
 
754
                             activeAtom,
 
755
                             XA_INTEGER,
 
756
                             32, PropModeReplace, (guchar *) data,
 
757
                             BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
 
758
        }
 
759
    }
 
760
    else
 
761
    {
 
762
        XDeleteProperty (xdisplay, xroot, bareAtom);
 
763
 
 
764
        if (minimal)
 
765
        {
 
766
            XDeleteProperty (xdisplay, xroot, normalAtom);
 
767
            XDeleteProperty (xdisplay, xroot, activeAtom);
 
768
        }
 
769
    }
 
770
 
 
771
    if (minimal)
 
772
        return;
 
773
 
 
774
    memset (&d, 0, sizeof (d));
 
775
 
 
776
    if (d.active)
 
777
    {
 
778
        d.context = &window_active_context;
 
779
        d.shadow  = border_active_shadow;
 
780
    }
 
781
    else
 
782
    {
 
783
        d.context = &window_inactive_context;
 
784
        d.shadow  = border_inactive_shadow;
 
785
    }
 
786
 
 
787
    d.layout  = pango_layout_new (pango_context);
 
788
 
 
789
    decor_get_default_layout (d.context, 1, 1, &d.border_layout);
 
790
 
 
791
    d.width  = d.border_layout.width;
 
792
    d.height = d.border_layout.height;
 
793
 
 
794
    extents.top += titlebar_height;
 
795
 
 
796
    d.draw = theme_draw_window_decoration;
 
797
 
 
798
    if (decor_normal_pixmap)
 
799
        g_object_unref (G_OBJECT (decor_normal_pixmap));
 
800
 
 
801
    nQuad = decor_set_lSrStSbS_window_quads (quads, d.context,
 
802
                                             &d.border_layout);
 
803
 
 
804
    decor_normal_pixmap = create_pixmap (d.width, d.height, 32);
 
805
 
 
806
    if (decor_normal_pixmap)
 
807
    {
 
808
        d.pixmap  = decor_normal_pixmap;
 
809
        d.active  = FALSE;
 
810
        d.picture = XRenderCreatePicture (xdisplay,
 
811
                                          GDK_PIXMAP_XID (d.pixmap),
 
812
                                          xformat_rgba, 0, NULL);
 
813
 
 
814
        (*d.draw) (&d);
 
815
 
 
816
        XRenderFreePicture (xdisplay, d.picture);
 
817
 
 
818
        fprintf (stderr, "extents are %i %i %i %i %i\n", extents.left, extents.right, extents.top, extents.bottom);
 
819
 
 
820
        decor_quads_to_property (data, GDK_PIXMAP_XID (d.pixmap),
 
821
                                 &extents, &extents, &extents, &extents, 0, 0, quads, nQuad);
 
822
 
 
823
        XChangeProperty (xdisplay, xroot,
 
824
                         normalAtom,
 
825
                         XA_INTEGER,
 
826
                         32, PropModeReplace, (guchar *) data,
 
827
                         BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
 
828
    }
 
829
 
 
830
    if (decor_active_pixmap)
 
831
        g_object_unref (G_OBJECT (decor_active_pixmap));
 
832
 
 
833
    decor_active_pixmap = create_pixmap (d.width, d.height, 32);
 
834
 
 
835
    if (decor_active_pixmap)
 
836
    {
 
837
        d.pixmap  = decor_active_pixmap;
 
838
        d.active  = TRUE;
 
839
        d.picture = XRenderCreatePicture (xdisplay,
 
840
                                          GDK_PIXMAP_XID (d.pixmap),
 
841
                                          xformat_rgba, 0, NULL);
 
842
 
 
843
        (*d.draw) (&d);
 
844
 
 
845
        XRenderFreePicture (xdisplay, d.picture);
 
846
 
 
847
        decor_quads_to_property (data, GDK_PIXMAP_XID (d.pixmap),
 
848
                                 &extents, &extents, &extents, &extents, 0, 0, quads, nQuad);
 
849
 
 
850
        XChangeProperty (xdisplay, xroot,
 
851
                         activeAtom,
 
852
                         XA_INTEGER,
 
853
                         32, PropModeReplace, (guchar *) data,
 
854
                         BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
 
855
    }
 
856
 
 
857
    if (d.layout)
 
858
        g_object_unref (G_OBJECT (d.layout));
 
859
}
 
860
 
 
861
void
 
862
copy_to_front_buffer (decor_t *d)
 
863
{
 
864
    if (!d->buffer_pixmap)
 
865
        return;
 
866
 
 
867
    cairo_set_operator (d->cr, CAIRO_OPERATOR_SOURCE);
 
868
    gdk_cairo_set_source_pixmap (d->cr, d->buffer_pixmap, 0, 0);
 
869
    cairo_paint (d->cr);
 
870
}