~dbarth/compiz/reworked-fix-744104

« back to all changes in this revision

Viewing changes to unity/unity_window_decorator/src/cairo.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
void
 
4
rounded_rectangle (cairo_t *cr,
 
5
                   double  x,
 
6
                   double  y,
 
7
                   double  w,
 
8
                   double  h,
 
9
                   double  radius,
 
10
                   int     corner)
 
11
{
 
12
    if (corner & CORNER_TOPLEFT)
 
13
        cairo_move_to (cr, x + radius, y);
 
14
    else
 
15
        cairo_move_to (cr, x, y);
 
16
 
 
17
    if (corner & CORNER_TOPRIGHT)
 
18
        cairo_arc (cr, x + w - radius, y + radius, radius,
 
19
                   M_PI * 1.5, M_PI * 2.0);
 
20
    else
 
21
        cairo_line_to (cr, x + w, y);
 
22
 
 
23
    if (corner & CORNER_BOTTOMRIGHT)
 
24
        cairo_arc (cr, x + w - radius, y + h - radius, radius,
 
25
                   0.0, M_PI * 0.5);
 
26
    else
 
27
        cairo_line_to (cr, x + w, y + h);
 
28
 
 
29
    if (corner & CORNER_BOTTOMLEFT)
 
30
        cairo_arc (cr, x + radius, y + h - radius, radius,
 
31
                   M_PI * 0.5, M_PI);
 
32
    else
 
33
        cairo_line_to (cr, x, y + h);
 
34
 
 
35
    if (corner & CORNER_TOPLEFT)
 
36
        cairo_arc (cr, x + radius, y + radius, radius, M_PI, M_PI * 1.5);
 
37
    else
 
38
        cairo_line_to (cr, x, y);
 
39
}
 
40
 
 
41
void
 
42
fill_rounded_rectangle (cairo_t       *cr,
 
43
                        double        x,
 
44
                        double        y,
 
45
                        double        w,
 
46
                        double        h,
 
47
                        double        radius,
 
48
                        int           corner,
 
49
                        decor_color_t *c0,
 
50
                        double        alpha0,
 
51
                        decor_color_t *c1,
 
52
                        double        alpha1,
 
53
                        int           gravity)
 
54
{
 
55
    cairo_pattern_t *pattern;
 
56
 
 
57
    rounded_rectangle (cr, x, y, w, h, radius, corner);
 
58
 
 
59
    if (gravity & SHADE_RIGHT)
 
60
    {
 
61
        x = x + w;
 
62
        w = -w;
 
63
    }
 
64
    else if (!(gravity & SHADE_LEFT))
 
65
    {
 
66
        x = w = 0;
 
67
    }
 
68
 
 
69
    if (gravity & SHADE_BOTTOM)
 
70
    {
 
71
        y = y + h;
 
72
        h = -h;
 
73
    }
 
74
    else if (!(gravity & SHADE_TOP))
 
75
    {
 
76
        y = h = 0;
 
77
    }
 
78
 
 
79
    if (w && h)
 
80
    {
 
81
        cairo_matrix_t matrix;
 
82
 
 
83
        pattern = cairo_pattern_create_radial (0.0, 0.0, 0.0, 0.0, 0.0, w);
 
84
 
 
85
        cairo_matrix_init_scale (&matrix, 1.0, w / h);
 
86
        cairo_matrix_translate (&matrix, -(x + w), -(y + h));
 
87
 
 
88
        cairo_pattern_set_matrix (pattern, &matrix);
 
89
    }
 
90
    else
 
91
    {
 
92
        pattern = cairo_pattern_create_linear (x + w, y + h, x, y);
 
93
    }
 
94
 
 
95
    cairo_pattern_add_color_stop_rgba (pattern, 0.0, c0->r, c0->g, c0->b,
 
96
                                       alpha0);
 
97
 
 
98
    cairo_pattern_add_color_stop_rgba (pattern, 1.0, c1->r, c1->g, c1->b,
 
99
                                       alpha1);
 
100
 
 
101
    cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
 
102
 
 
103
    cairo_set_source (cr, pattern);
 
104
    cairo_fill (cr);
 
105
    cairo_pattern_destroy (pattern);
 
106
}
 
107
 
 
108
void
 
109
draw_shadow_background (decor_t         *d,
 
110
                        cairo_t         *cr,
 
111
                        decor_shadow_t  *s,
 
112
                        decor_context_t *c)
 
113
{
 
114
    Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 
115
 
 
116
    if (!s || !s->picture ||!d->picture)
 
117
    {
 
118
        cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
 
119
        cairo_paint (cr);
 
120
    }
 
121
    else
 
122
    {
 
123
        decor_fill_picture_extents_with_shadow (xdisplay,
 
124
                                                s, c,
 
125
                                                d->picture,
 
126
                                                &d->border_layout);
 
127
    }
 
128
}
 
129
 
 
130
static void
 
131
draw_close_button (decor_t *d,
 
132
                   cairo_t *cr,
 
133
                   double  s)
 
134
{
 
135
    cairo_rel_move_to (cr, 0.0, s);
 
136
 
 
137
    cairo_rel_line_to (cr, s, -s);
 
138
    cairo_rel_line_to (cr, s, s);
 
139
    cairo_rel_line_to (cr, s, -s);
 
140
    cairo_rel_line_to (cr, s, s);
 
141
 
 
142
    cairo_rel_line_to (cr, -s, s);
 
143
    cairo_rel_line_to (cr, s, s);
 
144
    cairo_rel_line_to (cr, -s, s);
 
145
    cairo_rel_line_to (cr, -s, -s);
 
146
 
 
147
    cairo_rel_line_to (cr, -s, s);
 
148
    cairo_rel_line_to (cr, -s, -s);
 
149
    cairo_rel_line_to (cr, s, -s);
 
150
 
 
151
    cairo_close_path (cr);
 
152
}
 
153
 
 
154
static void
 
155
draw_max_button (decor_t *d,
 
156
                 cairo_t *cr,
 
157
                 double  s)
 
158
{
 
159
    cairo_rel_line_to (cr, 12.0, 0.0);
 
160
    cairo_rel_line_to (cr, 0.0, 12.0);
 
161
    cairo_rel_line_to (cr, -12.0, 0.0);
 
162
 
 
163
    cairo_close_path (cr);
 
164
 
 
165
    cairo_rel_move_to (cr, 2.0, s);
 
166
 
 
167
    cairo_rel_line_to (cr, 12.0 - 4.0, 0.0);
 
168
    cairo_rel_line_to (cr, 0.0, 12.0 - s - 2.0);
 
169
    cairo_rel_line_to (cr, -(12.0 - 4.0), 0.0);
 
170
 
 
171
    cairo_close_path (cr);
 
172
}
 
173
 
 
174
static void
 
175
draw_unmax_button (decor_t *d,
 
176
                   cairo_t *cr,
 
177
                   double  s)
 
178
{
 
179
    cairo_rel_move_to (cr, 1.0, 1.0);
 
180
 
 
181
    cairo_rel_line_to (cr, 10.0, 0.0);
 
182
    cairo_rel_line_to (cr, 0.0, 10.0);
 
183
    cairo_rel_line_to (cr, -10.0, 0.0);
 
184
 
 
185
    cairo_close_path (cr);
 
186
 
 
187
    cairo_rel_move_to (cr, 2.0, s);
 
188
 
 
189
    cairo_rel_line_to (cr, 10.0 - 4.0, 0.0);
 
190
    cairo_rel_line_to (cr, 0.0, 10.0 - s - 2.0);
 
191
    cairo_rel_line_to (cr, -(10.0 - 4.0), 0.0);
 
192
 
 
193
    cairo_close_path (cr);
 
194
}
 
195
 
 
196
static void
 
197
draw_min_button (decor_t *d,
 
198
                 cairo_t *cr,
 
199
                 double  s)
 
200
{
 
201
    cairo_rel_move_to (cr, 0.0, 8.0);
 
202
 
 
203
    cairo_rel_line_to (cr, 12.0, 0.0);
 
204
    cairo_rel_line_to (cr, 0.0, s);
 
205
    cairo_rel_line_to (cr, -12.0, 0.0);
 
206
 
 
207
    cairo_close_path (cr);
 
208
}
 
209
 
 
210
typedef void (*draw_proc) (cairo_t *cr);
 
211
 
 
212
static void
 
213
button_state_offsets (gdouble x,
 
214
                      gdouble y,
 
215
                      guint   state,
 
216
                      gdouble *return_x,
 
217
                      gdouble *return_y)
 
218
{
 
219
    static double off[] = { 0.0, 0.0, 0.0, 0.5 };
 
220
 
 
221
    *return_x  = x + off[state];
 
222
    *return_y  = y + off[state];
 
223
}
 
224
 
 
225
static void
 
226
button_state_paint (cairo_t       *cr,
 
227
                    GtkStyle      *style,
 
228
                    decor_color_t *color,
 
229
                    guint         state)
 
230
{
 
231
 
 
232
#define IN_STATE (PRESSED_EVENT_WINDOW | IN_EVENT_WINDOW)
 
233
 
 
234
    if ((state & IN_STATE) == IN_STATE)
 
235
    {
 
236
        if (state & IN_EVENT_WINDOW)
 
237
            cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
 
238
        else
 
239
            cairo_set_source_rgba (cr, color->r, color->g, color->b, 0.95);
 
240
 
 
241
        cairo_fill_preserve (cr);
 
242
 
 
243
        gdk_cairo_set_source_color_alpha (cr,
 
244
                                          &style->fg[GTK_STATE_NORMAL],
 
245
                                          STROKE_ALPHA);
 
246
 
 
247
        cairo_set_line_width (cr, 1.0);
 
248
        cairo_stroke (cr);
 
249
        cairo_set_line_width (cr, 2.0);
 
250
    }
 
251
    else
 
252
    {
 
253
        gdk_cairo_set_source_color_alpha (cr,
 
254
                                          &style->fg[GTK_STATE_NORMAL],
 
255
                                          STROKE_ALPHA);
 
256
        cairo_stroke_preserve (cr);
 
257
 
 
258
        if (state & IN_EVENT_WINDOW)
 
259
            cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
 
260
        else
 
261
            cairo_set_source_rgba (cr, color->r, color->g, color->b, 0.95);
 
262
 
 
263
        cairo_fill (cr);
 
264
    }
 
265
}
 
266
 
 
267
void
 
268
draw_window_decoration (decor_t *d)
 
269
{
 
270
    cairo_t       *cr;
 
271
    GtkStyle      *style;
 
272
    GdkDrawable   *drawable;
 
273
    decor_color_t color;
 
274
    double        alpha;
 
275
    double        x1, y1, x2, y2, x, y, h;
 
276
    int           corners = SHADE_LEFT | SHADE_RIGHT | SHADE_TOP | SHADE_BOTTOM;
 
277
    int           top;
 
278
    int           button_x;
 
279
 
 
280
    if (!d->pixmap)
 
281
        return;
 
282
 
 
283
    style = gtk_widget_get_style (style_window_rgba);
 
284
 
 
285
    if (d->state & (WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY |
 
286
                    WNCK_WINDOW_STATE_MAXIMIZED_VERTICALLY))
 
287
        corners = 0;
 
288
 
 
289
    color.r = style->bg[GTK_STATE_NORMAL].red   / 65535.0;
 
290
    color.g = style->bg[GTK_STATE_NORMAL].green / 65535.0;
 
291
    color.b = style->bg[GTK_STATE_NORMAL].blue  / 65535.0;
 
292
 
 
293
    if (d->frame_window)
 
294
    {
 
295
        GdkColormap *cmap;
 
296
 
 
297
        cmap = get_colormap_for_drawable (GDK_DRAWABLE (d->pixmap));
 
298
        gdk_drawable_set_colormap (GDK_DRAWABLE (d->pixmap), cmap);
 
299
        gdk_drawable_set_colormap (GDK_DRAWABLE (d->buffer_pixmap), cmap);
 
300
        drawable = GDK_DRAWABLE (d->buffer_pixmap);
 
301
    }
 
302
    else if (d->buffer_pixmap)
 
303
        drawable = GDK_DRAWABLE (d->buffer_pixmap);
 
304
    else
 
305
        drawable = GDK_DRAWABLE (d->pixmap);
 
306
 
 
307
    cr = gdk_cairo_create (GDK_DRAWABLE (drawable));
 
308
    if (!cr)
 
309
        return;
 
310
 
 
311
    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
 
312
 
 
313
    top = _win_extents.top + titlebar_height;
 
314
 
 
315
    x1 = d->context->left_space - _win_extents.left;
 
316
    y1 = d->context->top_space - _win_extents.top - titlebar_height;
 
317
    x2 = d->width - d->context->right_space + _win_extents.right;
 
318
    y2 = d->height - d->context->bottom_space + _win_extents.bottom;
 
319
 
 
320
    h = d->height - d->context->top_space - d->context->bottom_space;
 
321
 
 
322
    cairo_set_line_width (cr, 1.0);
 
323
 
 
324
    if (!d->frame_window)
 
325
        draw_shadow_background (d, cr, d->shadow, d->context);
 
326
 
 
327
    if (d->active)
 
328
    {
 
329
        decor_color_t *title_color = _title_color;
 
330
 
 
331
        alpha = decoration_alpha + 0.3;
 
332
 
 
333
        fill_rounded_rectangle (cr,
 
334
                                x1 + 0.5,
 
335
                                y1 + 0.5,
 
336
                                _win_extents.left - 0.5,
 
337
                                top - 0.5,
 
338
                                5.0, CORNER_TOPLEFT & corners,
 
339
                                &title_color[0], 1.0, &title_color[1], alpha,
 
340
                                SHADE_TOP | SHADE_LEFT);
 
341
 
 
342
        fill_rounded_rectangle (cr,
 
343
                                x1 + _win_extents.left,
 
344
                                y1 + 0.5,
 
345
                                x2 - x1 - _win_extents.left -
 
346
                                _win_extents.right,
 
347
                                top - 0.5,
 
348
                                5.0, 0,
 
349
                                &title_color[0], 1.0, &title_color[1], alpha,
 
350
                                SHADE_TOP);
 
351
 
 
352
        fill_rounded_rectangle (cr,
 
353
                                x2 - _win_extents.right,
 
354
                                y1 + 0.5,
 
355
                                _win_extents.right - 0.5,
 
356
                                top - 0.5,
 
357
                                5.0, CORNER_TOPRIGHT & corners,
 
358
                                &title_color[0], 1.0, &title_color[1], alpha,
 
359
                                SHADE_TOP | SHADE_RIGHT);
 
360
    }
 
361
    else
 
362
    {
 
363
        alpha = decoration_alpha;
 
364
 
 
365
        fill_rounded_rectangle (cr,
 
366
                                x1 + 0.5,
 
367
                                y1 + 0.5,
 
368
                                _win_extents.left - 0.5,
 
369
                                top - 0.5,
 
370
                                5.0, CORNER_TOPLEFT & corners,
 
371
                                &color, 1.0, &color, alpha,
 
372
                                SHADE_TOP | SHADE_LEFT);
 
373
 
 
374
        fill_rounded_rectangle (cr,
 
375
                                x1 + _win_extents.left,
 
376
                                y1 + 0.5,
 
377
                                x2 - x1 - _win_extents.left -
 
378
                                _win_extents.right,
 
379
                                top - 0.5,
 
380
                                5.0, 0,
 
381
                                &color, 1.0, &color, alpha,
 
382
                                SHADE_TOP);
 
383
 
 
384
        fill_rounded_rectangle (cr,
 
385
                                x2 - _win_extents.right,
 
386
                                y1 + 0.5,
 
387
                                _win_extents.right - 0.5,
 
388
                                top - 0.5,
 
389
                                5.0, CORNER_TOPRIGHT & corners,
 
390
                                &color, 1.0, &color, alpha,
 
391
                                SHADE_TOP | SHADE_RIGHT);
 
392
    }
 
393
 
 
394
    fill_rounded_rectangle (cr,
 
395
                            x1 + 0.5,
 
396
                            y1 + top,
 
397
                            _win_extents.left - 0.5,
 
398
                            h,
 
399
                            5.0, 0,
 
400
                            &color, 1.0, &color, alpha,
 
401
                            SHADE_LEFT);
 
402
 
 
403
    fill_rounded_rectangle (cr,
 
404
                            x2 - _win_extents.right,
 
405
                            y1 + top,
 
406
                            _win_extents.right - 0.5,
 
407
                            h,
 
408
                            5.0, 0,
 
409
                            &color, 1.0, &color, alpha,
 
410
                            SHADE_RIGHT);
 
411
 
 
412
 
 
413
    fill_rounded_rectangle (cr,
 
414
                            x1 + 0.5,
 
415
                            y2 - _win_extents.bottom,
 
416
                            _win_extents.left - 0.5,
 
417
                            _win_extents.bottom - 0.5,
 
418
                            5.0, CORNER_BOTTOMLEFT & corners,
 
419
                            &color, 1.0, &color, alpha,
 
420
                            SHADE_BOTTOM | SHADE_LEFT);
 
421
 
 
422
    fill_rounded_rectangle (cr,
 
423
                            x1 + _win_extents.left,
 
424
                            y2 - _win_extents.bottom,
 
425
                            x2 - x1 - _win_extents.left -
 
426
                            _win_extents.right,
 
427
                            _win_extents.bottom - 0.5,
 
428
                            5.0, 0,
 
429
                            &color, 1.0, &color, alpha,
 
430
                            SHADE_BOTTOM);
 
431
 
 
432
    fill_rounded_rectangle (cr,
 
433
                            x2 - _win_extents.right,
 
434
                            y2 - _win_extents.bottom,
 
435
                            _win_extents.right - 0.5,
 
436
                            _win_extents.bottom - 0.5,
 
437
                            5.0, CORNER_BOTTOMRIGHT & corners,
 
438
                            &color, 1.0, &color, alpha,
 
439
                            SHADE_BOTTOM | SHADE_RIGHT);
 
440
 
 
441
    cairo_rectangle (cr,
 
442
                     d->context->left_space,
 
443
                     d->context->top_space,
 
444
                     d->width - d->context->left_space -
 
445
                     d->context->right_space,
 
446
                     h);
 
447
    gdk_cairo_set_source_color (cr, &style->bg[GTK_STATE_NORMAL]);
 
448
    cairo_fill (cr);
 
449
 
 
450
    cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
 
451
 
 
452
    if (d->active)
 
453
    {
 
454
        gdk_cairo_set_source_color_alpha (cr,
 
455
                                          &style->fg[GTK_STATE_NORMAL],
 
456
                                          0.7);
 
457
 
 
458
        cairo_move_to (cr, x1 + 0.5, y1 + top - 0.5);
 
459
        cairo_rel_line_to (cr, x2 - x1 - 1.0, 0.0);
 
460
 
 
461
        cairo_stroke (cr);
 
462
    }
 
463
 
 
464
    rounded_rectangle (cr,
 
465
                       x1 + 0.5, y1 + 0.5,
 
466
                       x2 - x1 - 1.0, y2 - y1 - 1.0,
 
467
                       5.0,
 
468
                       (CORNER_TOPLEFT | CORNER_TOPRIGHT | CORNER_BOTTOMLEFT |
 
469
                        CORNER_BOTTOMRIGHT) & corners);
 
470
 
 
471
    cairo_clip (cr);
 
472
 
 
473
    cairo_translate (cr, 1.0, 1.0);
 
474
 
 
475
    rounded_rectangle (cr,
 
476
                       x1 + 0.5, y1 + 0.5,
 
477
                       x2 - x1 - 1.0, y2 - y1 - 1.0,
 
478
                       5.0,
 
479
                       (CORNER_TOPLEFT | CORNER_TOPRIGHT | CORNER_BOTTOMLEFT |
 
480
                        CORNER_BOTTOMRIGHT) & corners);
 
481
 
 
482
    cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.4);
 
483
 
 
484
    cairo_stroke (cr);
 
485
 
 
486
    cairo_translate (cr, -2.0, -2.0);
 
487
 
 
488
    rounded_rectangle (cr,
 
489
                       x1 + 0.5, y1 + 0.5,
 
490
                       x2 - x1 - 1.0, y2 - y1 - 1.0,
 
491
                       5.0,
 
492
                       (CORNER_TOPLEFT | CORNER_TOPRIGHT | CORNER_BOTTOMLEFT |
 
493
                        CORNER_BOTTOMRIGHT) & corners);
 
494
 
 
495
    cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.1);
 
496
 
 
497
    cairo_stroke (cr);
 
498
 
 
499
    cairo_translate (cr, 1.0, 1.0);
 
500
 
 
501
    cairo_reset_clip (cr);
 
502
 
 
503
    rounded_rectangle (cr,
 
504
                       x1 + 0.5, y1 + 0.5,
 
505
                       x2 - x1 - 1.0, y2 - y1 - 1.0,
 
506
                       5.0,
 
507
                       (CORNER_TOPLEFT | CORNER_TOPRIGHT | CORNER_BOTTOMLEFT |
 
508
                        CORNER_BOTTOMRIGHT) & corners);
 
509
 
 
510
    gdk_cairo_set_source_color_alpha (cr,
 
511
                                      &style->fg[GTK_STATE_NORMAL],
 
512
                                      alpha);
 
513
 
 
514
    cairo_stroke (cr);
 
515
 
 
516
    cairo_set_line_width (cr, 2.0);
 
517
 
 
518
    button_x = d->width - d->context->right_space - 13;
 
519
 
 
520
    if (d->actions & WNCK_WINDOW_ACTION_CLOSE)
 
521
    {
 
522
        button_state_offsets (button_x,
 
523
                              y1 - 3.0 + titlebar_height / 2,
 
524
                              d->button_states[BUTTON_CLOSE], &x, &y);
 
525
 
 
526
        button_x -= 17;
 
527
 
 
528
        if (d->active)
 
529
        {
 
530
            cairo_move_to (cr, x, y);
 
531
            draw_close_button (d, cr, 3.0);
 
532
            button_state_paint (cr, style, &color,
 
533
                                d->button_states[BUTTON_CLOSE]);
 
534
        }
 
535
        else
 
536
        {
 
537
            gdk_cairo_set_source_color_alpha (cr,
 
538
                                              &style->fg[GTK_STATE_NORMAL],
 
539
                                              alpha * 0.75);
 
540
 
 
541
            cairo_move_to (cr, x, y);
 
542
            draw_close_button (d, cr, 3.0);
 
543
            cairo_fill (cr);
 
544
        }
 
545
    }
 
546
 
 
547
    if (d->actions & WNCK_WINDOW_ACTION_MAXIMIZE)
 
548
    {
 
549
        button_state_offsets (button_x,
 
550
                              y1 - 3.0 + titlebar_height / 2,
 
551
                              d->button_states[BUTTON_MAX], &x, &y);
 
552
 
 
553
        button_x -= 17;
 
554
 
 
555
        cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
 
556
 
 
557
        if (d->active)
 
558
        {
 
559
            gdk_cairo_set_source_color_alpha (cr,
 
560
                                              &style->fg[GTK_STATE_NORMAL],
 
561
                                              STROKE_ALPHA);
 
562
 
 
563
            cairo_move_to (cr, x, y);
 
564
 
 
565
            if (d->state & (WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY |
 
566
                            WNCK_WINDOW_STATE_MAXIMIZED_VERTICALLY))
 
567
                draw_unmax_button (d, cr, 4.0);
 
568
            else
 
569
                draw_max_button (d, cr, 4.0);
 
570
 
 
571
            button_state_paint (cr, style, &color,
 
572
                                d->button_states[BUTTON_MAX]);
 
573
        }
 
574
        else
 
575
        {
 
576
            gdk_cairo_set_source_color_alpha (cr,
 
577
                                              &style->fg[GTK_STATE_NORMAL],
 
578
                                              alpha * 0.75);
 
579
 
 
580
            cairo_move_to (cr, x, y);
 
581
 
 
582
            if (d->state & (WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY |
 
583
                            WNCK_WINDOW_STATE_MAXIMIZED_VERTICALLY))
 
584
                draw_unmax_button (d, cr, 4.0);
 
585
            else
 
586
                draw_max_button (d, cr, 4.0);
 
587
 
 
588
            cairo_fill (cr);
 
589
        }
 
590
    }
 
591
 
 
592
    if (d->actions & WNCK_WINDOW_ACTION_MINIMIZE)
 
593
    {
 
594
        button_state_offsets (button_x,
 
595
                              y1 - 3.0 + titlebar_height / 2,
 
596
                              d->button_states[BUTTON_MIN], &x, &y);
 
597
 
 
598
        button_x -= 17;
 
599
 
 
600
        if (d->active)
 
601
        {
 
602
            gdk_cairo_set_source_color_alpha (cr,
 
603
                                              &style->fg[GTK_STATE_NORMAL],
 
604
                                              STROKE_ALPHA);
 
605
 
 
606
 
 
607
            cairo_move_to (cr, x, y);
 
608
            draw_min_button (d, cr, 4.0);
 
609
            button_state_paint (cr, style, &color,
 
610
                                d->button_states[BUTTON_MIN]);
 
611
        }
 
612
        else
 
613
        {
 
614
            gdk_cairo_set_source_color_alpha (cr,
 
615
                                              &style->fg[GTK_STATE_NORMAL],
 
616
                                              alpha * 0.75);
 
617
 
 
618
            cairo_move_to (cr, x, y);
 
619
            draw_min_button (d, cr, 4.0);
 
620
            cairo_fill (cr);
 
621
        }
 
622
    }
 
623
 
 
624
    if (d->layout)
 
625
    {
 
626
        if (d->active)
 
627
        {
 
628
            cairo_move_to (cr,
 
629
                           d->context->left_space + 21.0,
 
630
                           y1 + 2.0 + (titlebar_height - text_height) / 2.0);
 
631
 
 
632
            gdk_cairo_set_source_color_alpha (cr,
 
633
                                              &style->fg[GTK_STATE_NORMAL],
 
634
                                              STROKE_ALPHA);
 
635
 
 
636
            pango_cairo_layout_path (cr, d->layout);
 
637
            cairo_stroke (cr);
 
638
 
 
639
            cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
 
640
        }
 
641
        else
 
642
        {
 
643
            gdk_cairo_set_source_color_alpha (cr,
 
644
                                              &style->fg[GTK_STATE_NORMAL],
 
645
                                              alpha);
 
646
        }
 
647
 
 
648
        cairo_move_to (cr,
 
649
                       d->context->left_space + 21.0,
 
650
                       y1 + 2.0 + (titlebar_height - text_height) / 2.0);
 
651
 
 
652
        pango_cairo_show_layout (cr, d->layout);
 
653
    }
 
654
 
 
655
    if (d->icon)
 
656
    {
 
657
        cairo_translate (cr, d->context->left_space + 1,
 
658
                         y1 - 5.0 + titlebar_height / 2);
 
659
        cairo_set_source (cr, d->icon);
 
660
        cairo_rectangle (cr, 0.0, 0.0, 16.0, 16.0);
 
661
        cairo_clip (cr);
 
662
 
 
663
        if (d->active)
 
664
            cairo_paint (cr);
 
665
        else
 
666
            cairo_paint_with_alpha (cr, alpha);
 
667
    }
 
668
 
 
669
    cairo_destroy (cr);
 
670
 
 
671
    copy_to_front_buffer (d);
 
672
 
 
673
    if (d->frame_window)
 
674
    {
 
675
        GdkWindow *gdk_frame_window = gtk_widget_get_window (d->decor_window);
 
676
 
 
677
        gtk_image_set_from_pixmap (GTK_IMAGE (d->decor_image), d->pixmap, NULL);
 
678
        gtk_window_resize (GTK_WINDOW (d->decor_window), d->width, d->height);
 
679
        gdk_window_move (gdk_frame_window, 0, 0);
 
680
        gdk_window_lower (gdk_frame_window);
 
681
    }
 
682
 
 
683
    if (d->prop_xid)
 
684
    {
 
685
        decor_update_window_property (d);
 
686
        d->prop_xid = 0;
 
687
    }
 
688
}
 
689
 
 
690
static void
 
691
calc_button_size (decor_t *d)
 
692
{
 
693
    gint button_width;
 
694
 
 
695
    button_width = 0;
 
696
 
 
697
    if (d->actions & WNCK_WINDOW_ACTION_CLOSE)
 
698
        button_width += 17;
 
699
 
 
700
    if (d->actions & (WNCK_WINDOW_ACTION_MAXIMIZE_HORIZONTALLY   |
 
701
                      WNCK_WINDOW_ACTION_MAXIMIZE_VERTICALLY     |
 
702
                      WNCK_WINDOW_ACTION_UNMAXIMIZE_HORIZONTALLY |
 
703
                      WNCK_WINDOW_ACTION_UNMAXIMIZE_VERTICALLY))
 
704
        button_width += 17;
 
705
 
 
706
    if (d->actions & (WNCK_WINDOW_ACTION_MINIMIZE |
 
707
                      WNCK_WINDOW_ACTION_MINIMIZE))
 
708
        button_width += 17;
 
709
 
 
710
    if (button_width)
 
711
        button_width++;
 
712
 
 
713
    d->button_width = button_width;
 
714
}
 
715
 
 
716
gboolean
 
717
calc_decoration_size (decor_t *d,
 
718
                      gint    w,
 
719
                      gint    h,
 
720
                      gint    name_width,
 
721
                      gint    *width,
 
722
                      gint    *height)
 
723
{
 
724
    decor_layout_t layout;
 
725
    int            top_width;
 
726
 
 
727
    /* To avoid wasting texture memory, we only calculate the minimal
 
728
     * required decoration size then clip and stretch the texture where
 
729
     * appropriate
 
730
     */
 
731
 
 
732
    if (!d->frame_window)
 
733
    {
 
734
        calc_button_size (d);
 
735
 
 
736
        if (w < ICON_SPACE + d->button_width)
 
737
            return FALSE;
 
738
 
 
739
        top_width = name_width + d->button_width + ICON_SPACE;
 
740
        if (w < top_width)
 
741
            top_width = MAX (ICON_SPACE + d->button_width, w);
 
742
 
 
743
        if (d->active)
 
744
            decor_get_default_layout (&window_active_context, top_width, 1, &layout);
 
745
        else
 
746
            decor_get_default_layout (&window_inactive_context, top_width, 1, &layout);
 
747
 
 
748
        if (!d->context || memcmp (&layout, &d->border_layout, sizeof (layout)))
 
749
        {
 
750
            *width  = layout.width;
 
751
            *height = layout.height;
 
752
 
 
753
            d->border_layout = layout;
 
754
            if (d->active)
 
755
            {
 
756
                d->context       = &window_active_context;
 
757
                d->shadow        = border_active_shadow;
 
758
            }
 
759
            else
 
760
            {
 
761
                d->context       = &window_inactive_context;
 
762
                d->shadow        = border_inactive_shadow;
 
763
            }
 
764
 
 
765
            return TRUE;
 
766
        }
 
767
    }
 
768
    else
 
769
    {
 
770
        calc_button_size (d);
 
771
 
 
772
        /* _default_win_extents + top height */
 
773
 
 
774
        top_width = name_width + d->button_width + ICON_SPACE;
 
775
        if (w < top_width)
 
776
            top_width = MAX (ICON_SPACE + d->button_width, w);
 
777
 
 
778
        decor_get_default_layout (&window_context_no_shadow,
 
779
                                  d->client_width, d->client_height, &layout);
 
780
 
 
781
        *width = layout.width;
 
782
        *height = layout.height;
 
783
 
 
784
        d->border_layout = layout;
 
785
        d->context = &window_context_no_shadow;
 
786
        d->shadow = border_no_shadow;
 
787
 
 
788
        return TRUE;
 
789
    }
 
790
 
 
791
    return FALSE;
 
792
}
 
793
 
 
794
gboolean
 
795
get_button_position (decor_t *d,
 
796
                     gint    i,
 
797
                     gint    width,
 
798
                     gint    height,
 
799
                     gint    *x,
 
800
                     gint    *y,
 
801
                     gint    *w,
 
802
                     gint    *h)
 
803
{
 
804
    if (i > BUTTON_MENU)
 
805
        return FALSE;
 
806
 
 
807
    if (d->frame_window)
 
808
    {
 
809
        *x = bpos[i].x + bpos[i].xw * width + _win_extents.left + 4;
 
810
        *y = bpos[i].y + bpos[i].yh * height + bpos[i].yth *
 
811
            (titlebar_height - 17) + _win_extents.top + 2;
 
812
    }
 
813
    else
 
814
    {
 
815
        *x = bpos[i].x + bpos[i].xw * width;
 
816
        *y = bpos[i].y + bpos[i].yh * height + bpos[i].yth *
 
817
            (titlebar_height - 17);
 
818
    }
 
819
 
 
820
    *w = bpos[i].w + bpos[i].ww * width;
 
821
    *h = bpos[i].h + bpos[i].hh * height + bpos[i].hth +
 
822
        (titlebar_height - 17);
 
823
 
 
824
    /* hack to position multiple buttons on the right */
 
825
    if (i != BUTTON_MENU)
 
826
        *x -= 10 + 16 * i;
 
827
 
 
828
    return TRUE;
 
829
}
 
830
 
 
831
void
 
832
get_event_window_position (decor_t *d,
 
833
                           gint    i,
 
834
                           gint    j,
 
835
                           gint    width,
 
836
                           gint    height,
 
837
                           gint    *x,
 
838
                           gint    *y,
 
839
                           gint    *w,
 
840
                           gint    *h)
 
841
{
 
842
    if (d->frame_window)
 
843
    {
 
844
        *x = pos[i][j].x + pos[i][j].xw * width + _win_extents.left;
 
845
        *y = pos[i][j].y + _win_extents.top +
 
846
             pos[i][j].yh * height + pos[i][j].yth * (titlebar_height - 17);
 
847
 
 
848
        if (i == 0 && (j == 0 || j == 2))
 
849
            *y -= titlebar_height;
 
850
    }
 
851
    else
 
852
    {
 
853
        *x = pos[i][j].x + pos[i][j].xw * width;
 
854
        *y = pos[i][j].y +
 
855
             pos[i][j].yh * height + pos[i][j].yth * (titlebar_height - 17);
 
856
    }
 
857
 
 
858
    if ((d->state & WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY) &&
 
859
        (j == 0 || j == 2))
 
860
    {
 
861
        *w = 0;
 
862
    }
 
863
    else
 
864
    {
 
865
        *w = pos[i][j].w + pos[i][j].ww * width;
 
866
    }
 
867
 
 
868
    if ((d->state & WNCK_WINDOW_STATE_MAXIMIZED_VERTICALLY) &&
 
869
        (i == 0 || i == 2))
 
870
    {
 
871
        *h = 0;
 
872
    }
 
873
    else
 
874
    {
 
875
        *h = pos[i][j].h +
 
876
             pos[i][j].hh * height + pos[i][j].hth * (titlebar_height - 17);
 
877
    }
 
878
}
 
879
 
 
880
void
 
881
update_border_extents (gint text_height)
 
882
{
 
883
    _win_extents = _default_win_extents;
 
884
    _max_win_extents = _default_win_extents;
 
885
    max_titlebar_height = titlebar_height =
 
886
        (text_height < 17) ? 17 : text_height;
 
887
}
 
888
 
 
889
decor_shadow_t *
 
890
cairo_update_shadow (gint shadow_type)
 
891
{
 
892
    decor_shadow_options_t opt_active_shadow;
 
893
    decor_shadow_options_t opt_inactive_shadow;
 
894
    Display                *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 
895
    GdkDisplay             *display = gdk_display_get_default ();
 
896
    GdkScreen              *screen = gdk_display_get_default_screen (display);
 
897
 
 
898
    opt_active_shadow.shadow_radius  = shadow_radius;
 
899
    opt_active_shadow.shadow_opacity = shadow_opacity;
 
900
 
 
901
    memcpy (opt_active_shadow.shadow_color, shadow_color, sizeof (shadow_color));
 
902
 
 
903
    opt_active_shadow.shadow_offset_x = shadow_offset_x;
 
904
    opt_active_shadow.shadow_offset_y = shadow_offset_y;
 
905
 
 
906
    opt_inactive_shadow.shadow_radius  = shadow_radius;
 
907
    opt_inactive_shadow.shadow_opacity = shadow_opacity;
 
908
 
 
909
    opt_inactive_shadow.shadow_offset_x = shadow_offset_x;
 
910
    opt_inactive_shadow.shadow_offset_y = shadow_offset_y;
 
911
 
 
912
    memcpy (opt_inactive_shadow.shadow_color, shadow_color, sizeof (shadow_color));
 
913
 
 
914
    switch (shadow_type)
 
915
    {
 
916
        case SHADOW_TYPE_ACTIVE_NORMAL:
 
917
            return decor_shadow_create (xdisplay,
 
918
                                        gdk_x11_screen_get_xscreen (screen),
 
919
                                        1, 1,
 
920
                                        _win_extents.left,
 
921
                                        _win_extents.right,
 
922
                                        _win_extents.top + titlebar_height,
 
923
                                        _win_extents.bottom,
 
924
                                        _win_extents.left -
 
925
                                        TRANSLUCENT_CORNER_SIZE,
 
926
                                        _win_extents.right -
 
927
                                        TRANSLUCENT_CORNER_SIZE,
 
928
                                        _win_extents.top + titlebar_height -
 
929
                                        TRANSLUCENT_CORNER_SIZE,
 
930
                                        _win_extents.bottom -
 
931
                                        TRANSLUCENT_CORNER_SIZE,
 
932
                                        &opt_active_shadow,
 
933
                                        &window_active_context,
 
934
                                        draw_border_shape,
 
935
                                        0);
 
936
            break;
 
937
        case SHADOW_TYPE_INACTIVE_NORMAL:
 
938
            return decor_shadow_create (xdisplay,
 
939
                                        gdk_x11_screen_get_xscreen (screen),
 
940
                                        1, 1,
 
941
                                        _win_extents.left,
 
942
                                        _win_extents.right,
 
943
                                        _win_extents.top + titlebar_height,
 
944
                                        _win_extents.bottom,
 
945
                                        _win_extents.left -
 
946
                                        TRANSLUCENT_CORNER_SIZE,
 
947
                                        _win_extents.right -
 
948
                                        TRANSLUCENT_CORNER_SIZE,
 
949
                                        _win_extents.top + titlebar_height -
 
950
                                        TRANSLUCENT_CORNER_SIZE,
 
951
                                        _win_extents.bottom -
 
952
                                        TRANSLUCENT_CORNER_SIZE,
 
953
                                        &opt_inactive_shadow,
 
954
                                        &window_inactive_context,
 
955
                                        draw_border_shape,
 
956
                                        0);
 
957
        case SHADOW_TYPE_ACTIVE_MAX:
 
958
            return decor_shadow_create (xdisplay,
 
959
                                        gdk_x11_screen_get_xscreen (screen),
 
960
                                        1, 1,
 
961
                                        _max_win_extents.left,
 
962
                                        _max_win_extents.right,
 
963
                                        _max_win_extents.top + max_titlebar_height,
 
964
                                        _max_win_extents.bottom,
 
965
                                        _max_win_extents.left - TRANSLUCENT_CORNER_SIZE,
 
966
                                        _max_win_extents.right - TRANSLUCENT_CORNER_SIZE,
 
967
                                        _max_win_extents.top + max_titlebar_height -
 
968
                                        TRANSLUCENT_CORNER_SIZE,
 
969
                                        _max_win_extents.bottom - TRANSLUCENT_CORNER_SIZE,
 
970
                                        &opt_active_shadow,
 
971
                                        &max_window_active_context,
 
972
                                        draw_border_shape,
 
973
                                        (void *) 1);
 
974
        case SHADOW_TYPE_INACTIVE_MAX:
 
975
            return decor_shadow_create (xdisplay,
 
976
                                        gdk_x11_screen_get_xscreen (screen),
 
977
                                        1, 1,
 
978
                                        _max_win_extents.left,
 
979
                                        _max_win_extents.right,
 
980
                                        _max_win_extents.top + max_titlebar_height,
 
981
                                        _max_win_extents.bottom,
 
982
                                        _max_win_extents.left - TRANSLUCENT_CORNER_SIZE,
 
983
                                        _max_win_extents.right - TRANSLUCENT_CORNER_SIZE,
 
984
                                        _max_win_extents.top + max_titlebar_height -
 
985
                                        TRANSLUCENT_CORNER_SIZE,
 
986
                                        _max_win_extents.bottom - TRANSLUCENT_CORNER_SIZE,
 
987
                                        &opt_inactive_shadow,
 
988
                                        &max_window_inactive_context,
 
989
                                        draw_border_shape,
 
990
                                        (void *) 1);
 
991
        default:
 
992
            return NULL;
 
993
    }
 
994
 
 
995
    return NULL;
 
996
}
 
997
 
 
998
void
 
999
get_shadow (decor_t *d, gint shadow_type)
 
1000
{
 
1001
}