~smspillaz/compiz/compiz.experimental2

2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
1
/*
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
2
 * Copyright © 2006 Novell, Inc.
3
 *
4
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
6
 * License as published by the Free Software Foundation; either
7
 * version 2 of the License, or (at your option) any later version.
8
 *
9
 * This library is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
12
 * Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15
 * License along with this library; if not, write to the
16
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17
 * Boston, MA 02111-1307, USA.
18
 *
745 by David Reveman
Add author to some headers where it's missing.
19
 * Author: David Reveman <davidr@novell.com>
20
 */
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
21
22
#ifdef HAVE_CONFIG_H
23
#include <config.h>
24
#endif
25
26
#include <stdio.h>
679 by David Reveman
Move DM selection code into libdecoration.
27
#include <stdlib.h>
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
28
#include <math.h>
29
30
#include <decoration.h>
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
31
32
#include <X11/Xatom.h>
679 by David Reveman
Move DM selection code into libdecoration.
33
#include <X11/Xregion.h>
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
34
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
35
int
681 by David Reveman
Move decoration property decoding into libdecoration.
36
decor_version (void)
37
{
38
    return DECOR_INTERFACE_VERSION;
39
}
40
41
/*
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
42
  decoration property
43
  -------------------
44
45
  data[0] = version
46
47
  data[1] = decoration type
1982.1.59 by Dennis Kasprzyk
- Added a type field to the decoration property.
48
49
  data[2] = number of decorations specified in property
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
50
51
  WINDOW_DECORATION_TYPE_WINDOW property
2025 by Dennis Kasprzyk
Added support for 2D decorations.
52
  --------------------------------------
53
  data[3] = input left
54
  data[4] = input right
55
  data[5] = input top
56
  data[6] = input bottom
57
58
  data[7]  = input left when maximized
59
  data[8]  = input right when maximized
60
  data[9]  = input top when maximized
61
  data[10] = input bottom when maximized
62
63
  data[11] = min width
64
  data[12] = min height
65
66
  fields 13 to 15 are only used by the default
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
67
  decorations on the root window
68
69
  data[13] = frame state
70
  data[14] = frame type
71
  data[15] = frame actions
72
73
2025 by Dennis Kasprzyk
Added support for 2D decorations.
74
  WINDOW_DECORATION_TYPE_PIXMAP property
1982.1.59 by Dennis Kasprzyk
- Added a type field to the decoration property.
75
  --------------------------------------
76
77
  data[3] = pixmap
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
78
1982.1.59 by Dennis Kasprzyk
- Added a type field to the decoration property.
79
  extents
2609.7.38 by Sam Spilsbury
Allow semantic difference between frame window geometry and frame size.
80
81
  frame input is used for creating the input area of
82
  the frame window which the client will be
83
  reparented into, border is used for positioning
84
85
  data[4] = frame left
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
86
  data[5] = frame right
87
  data[6] = frame top
88
  data[7] = frame bottom
89
  data[8] = input left
90
  data[9] = input right
91
  data[10] = input top
92
  data[11] = input bottom
93
94
  data[12]  = frame left when maximized
95
  data[13]  = frame right when maximized
96
  data[14]  = frame top when maximized
97
  data[15] = frame bottom when maximized
98
  data[16]  = border left when maximized
99
  data[17]  = border right when maximized
100
  data[18]  = border top when maximized
101
  data[19] = border bottom when maximized
102
103
  data[20] = min width
104
  data[21] = min height
105
106
  fields 22 to 24 are only used by the default
107
  decorations on the root window
108
109
  data[22] = frame state
110
  data[23] = frame type
111
  data[24] = frame actions
112
113
  data[25] = num quads
114
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
115
  flags
116
117
  1st to 4nd bit p1 gravity, 5rd to 8th bit p2 gravity,
118
  9rd and 10th bit alignment, 11rd and 12th bit clamp,
119
  13th bit XX, 14th bit XY, 15th bit YX, 16th bit YY.
120
121
  data[26 + n * 9 + 1] = flags
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
122
  data[26 + n * 9 + 2] = p1 x
123
  data[26 + n * 9 + 3] = p1 y
124
  data[26 + n * 9 + 4] = p2 x
125
  data[26 + n * 9 + 5] = p2 y
126
  data[26 + n * 9 + 6] = widthMax
127
  data[26 + n * 9 + 7] = heightMax
128
  data[26 + n * 9 + 8] = x0
129
  data[26 + n * 9 + 9] = y0
130
 */
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
131
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
132
long *
133
decor_alloc_property (unsigned int n,
134
                      unsigned int type)
135
{
136
    unsigned int  propSize = 0;
2908.3.1 by Daniel van Vugt
Fix all compiler warnings and (optionally) treat all future warnings as errors.
137
    long          *data;
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
138
139
    if (type == WINDOW_DECORATION_TYPE_WINDOW)
140
        propSize = WINDOW_PROP_SIZE;
141
    else if (type == WINDOW_DECORATION_TYPE_PIXMAP)
142
        propSize = BASE_PROP_SIZE + N_QUADS_MAX * QUAD_PROP_SIZE;
143
144
    propSize *= n;
145
    propSize += PROP_HEADER_SIZE;
146
147
    data = calloc (propSize, sizeof (long));
148
149
    data[0]  = DECOR_INTERFACE_VERSION;
150
    data[1]  = type;
151
    data[2]  = n;
152
153
    return data;
154
}
155
156
void
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
157
decor_quads_to_property (long		 *data,
158
			 unsigned int    n,
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
159
			 Pixmap		 pixmap,
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
160
			 decor_extents_t *frame,
2609.7.38 by Sam Spilsbury
Allow semantic difference between frame window geometry and frame size.
161
			 decor_extents_t *border,
162
			 decor_extents_t *max_frame,
163
			 decor_extents_t *max_border,
164
			 int		 min_width,
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
165
			 int		 min_height,
166
			 decor_quad_t    *quad,
167
			 int		 nQuad,
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
168
			 unsigned int	 frame_type,
2733.1.15 by Sam Spilsbury
Fix variable mismatch
169
			 unsigned int    frame_state,
170
			 unsigned int    frame_actions)
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
171
{
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
172
    /* FIXME: Allocating for N_QUAD_MAX is slightly inefficient, but there
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
173
     * isn't really a better way to do this at the moment */
174
    data += PROP_HEADER_SIZE + n * (BASE_PROP_SIZE + QUAD_PROP_SIZE * N_QUADS_MAX);
175
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
176
    memcpy (data++, &pixmap, sizeof (Pixmap));
177
178
    *data++ = frame->left;
2609.7.38 by Sam Spilsbury
Allow semantic difference between frame window geometry and frame size.
179
    *data++ = frame->right;
180
    *data++ = frame->top;
181
    *data++ = frame->bottom;
182
    *data++ = border->left;
183
    *data++ = border->right;
184
    *data++ = border->top;
185
    *data++ = border->bottom;
186
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
187
    *data++ = max_frame->left;
2609.7.38 by Sam Spilsbury
Allow semantic difference between frame window geometry and frame size.
188
    *data++ = max_frame->right;
189
    *data++ = max_frame->top;
190
    *data++ = max_frame->bottom;
191
    *data++ = max_border->left;
192
    *data++ = max_border->right;
193
    *data++ = max_border->top;
194
    *data++ = max_border->bottom;
195
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
196
    *data++ = min_width;
197
    *data++ = min_height;
198
199
    *data++ = frame_type;
2733.1.15 by Sam Spilsbury
Fix variable mismatch
200
    *data++ = frame_state;
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
201
    *data++ = frame_actions;
202
203
    *data++ = nQuad;
204
205
    while (nQuad--)
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
206
    {
207
	*data++ =
208
	    (quad->p1.gravity << 0)    |
209
	    (quad->p2.gravity << 4)    |
210
	    (quad->align      << 8)    |
211
	    (quad->clamp      << 10)   |
212
	    (quad->stretch    << 12)   |
1042.1.4 by Danny Baumann
Added quad stretching interface to libdecoration.
213
	    (quad->m.xx ? XX_MASK : 0) |
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
214
	    (quad->m.xy ? XY_MASK : 0) |
215
	    (quad->m.yx ? YX_MASK : 0) |
216
	    (quad->m.yy ? YY_MASK : 0);
217
218
	*data++ = quad->p1.x;
219
	*data++ = quad->p1.y;
220
	*data++ = quad->p2.x;
221
	*data++ = quad->p2.y;
222
	*data++ = quad->max_width;
223
	*data++ = quad->max_height;
224
	*data++ = quad->m.x0;
225
	*data++ = quad->m.y0;
226
227
	quad++;
228
    }
229
}
230
231
void
2025 by Dennis Kasprzyk
Added support for 2D decorations.
232
decor_gen_window_property (long		   *data,
233
			   unsigned int    n,
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
234
			   decor_extents_t *input,
2025 by Dennis Kasprzyk
Added support for 2D decorations.
235
			   decor_extents_t *max_input,
236
			   int		   min_width,
237
			   int		   min_height,
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
238
			   unsigned int	   frame_type,
2733.1.15 by Sam Spilsbury
Fix variable mismatch
239
			   unsigned int    frame_state,
240
			   unsigned int    frame_actions)
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
241
{
2025 by Dennis Kasprzyk
Added support for 2D decorations.
242
    data += PROP_HEADER_SIZE + n * WINDOW_PROP_SIZE;
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
243
2025 by Dennis Kasprzyk
Added support for 2D decorations.
244
    *data++ = input->left;
245
    *data++ = input->right;
246
    *data++ = input->top;
247
    *data++ = input->bottom;
248
249
    *data++ = max_input->left;
250
    *data++ = max_input->right;
251
    *data++ = max_input->top;
252
    *data++ = max_input->bottom;
253
254
    *data++ = min_width;
255
    *data++ = min_height;
256
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
257
    *data++ = frame_type;
2733.1.15 by Sam Spilsbury
Fix variable mismatch
258
    *data++ = frame_state;
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
259
    *data++ = frame_actions;
260
}
2025 by Dennis Kasprzyk
Added support for 2D decorations.
261
262
int
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
263
decor_property_get_version (long *data)
681 by David Reveman
Move decoration property decoding into libdecoration.
264
{
265
    return (int) *data;
266
}
267
268
int
269
decor_property_get_type (long *data)
2025 by Dennis Kasprzyk
Added support for 2D decorations.
270
{
271
    return (int) data[1];
272
}
273
274
int
275
decor_property_get_num (long *data)
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
276
{
277
    return (int) data[2];
278
}
279
280
int
281
decor_pixmap_property_to_quads (long		 *data,
2025 by Dennis Kasprzyk
Added support for 2D decorations.
282
				unsigned int     nOffset,
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
283
				int		 size,
2025 by Dennis Kasprzyk
Added support for 2D decorations.
284
				Pixmap		 *pixmap,
285
				decor_extents_t  *frame,
2609.7.38 by Sam Spilsbury
Allow semantic difference between frame window geometry and frame size.
286
				decor_extents_t  *border,
287
				decor_extents_t  *max_frame,
288
				decor_extents_t  *max_border,
289
				int		 *min_width,
2025 by Dennis Kasprzyk
Added support for 2D decorations.
290
				int		 *min_height,
291
				unsigned int     *frame_type,
2733.1.15 by Sam Spilsbury
Fix variable mismatch
292
				unsigned int     *frame_state,
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
293
				unsigned int     *frame_actions,
294
				decor_quad_t     *quad)
295
{
681 by David Reveman
Move decoration property decoding into libdecoration.
296
    int i, n, flags;
297
298
    if (size < PROP_HEADER_SIZE + nOffset * (BASE_PROP_SIZE + QUAD_PROP_SIZE + N_QUADS_MAX))
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
299
        return 0;
300
681 by David Reveman
Move decoration property decoding into libdecoration.
301
    if (decor_property_get_version (data) != decor_version ())
302
        return 0;
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
303
681 by David Reveman
Move decoration property decoding into libdecoration.
304
    if (decor_property_get_type (data) != WINDOW_DECORATION_TYPE_PIXMAP)
2025 by Dennis Kasprzyk
Added support for 2D decorations.
305
        return 0;
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
306
1982.1.59 by Dennis Kasprzyk
- Added a type field to the decoration property.
307
    data += PROP_HEADER_SIZE + nOffset * (BASE_PROP_SIZE + N_QUADS_MAX * QUAD_PROP_SIZE);
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
308
2025 by Dennis Kasprzyk
Added support for 2D decorations.
309
    memcpy (pixmap, data++, sizeof (Pixmap));
681 by David Reveman
Move decoration property decoding into libdecoration.
310
311
    frame->left   = *data++;
2609.7.38 by Sam Spilsbury
Allow semantic difference between frame window geometry and frame size.
312
    frame->right  = *data++;
313
    frame->top    = *data++;
314
    frame->bottom = *data++;
315
    border->left   = *data++;
316
    border->right  = *data++;
317
    border->top    = *data++;
318
    border->bottom = *data++;
319
681 by David Reveman
Move decoration property decoding into libdecoration.
320
    max_frame->left   = *data++;
2609.7.38 by Sam Spilsbury
Allow semantic difference between frame window geometry and frame size.
321
    max_frame->right  = *data++;
322
    max_frame->top    = *data++;
323
    max_frame->bottom = *data++;
324
    max_border->left   = *data++;
325
    max_border->right  = *data++;
326
    max_border->top    = *data++;
327
    max_border->bottom = *data++;
328
681 by David Reveman
Move decoration property decoding into libdecoration.
329
    *min_width  = *data++;
330
    *min_height = *data++;
331
332
    *frame_type = *data++;
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
333
    *frame_state = *data++;
334
    *frame_actions = *data++;
335
336
    n = *data++;
337
681 by David Reveman
Move decoration property decoding into libdecoration.
338
    for (i = 0; i < n; i++)
339
    {
340
	flags = *data++;
341
342
	quad->p1.gravity = (flags >> 0) & 0xf;
343
	quad->p2.gravity = (flags >> 4) & 0xf;
344
345
	quad->align   = (flags >> 8)  & 0x3;
1042.1.4 by Danny Baumann
Added quad stretching interface to libdecoration.
346
	quad->clamp   = (flags >> 10) & 0x3;
347
	quad->stretch = (flags >> 12) & 0x3;
348
681 by David Reveman
Move decoration property decoding into libdecoration.
349
	quad->m.xx = (flags & XX_MASK) ? 1.0f : 0.0f;
350
	quad->m.xy = (flags & XY_MASK) ? 1.0f : 0.0f;
351
	quad->m.yx = (flags & YX_MASK) ? 1.0f : 0.0f;
352
	quad->m.yy = (flags & YY_MASK) ? 1.0f : 0.0f;
353
354
	quad->p1.x = *data++;
355
	quad->p1.y = *data++;
356
	quad->p2.x = *data++;
357
	quad->p2.y = *data++;
358
359
	quad->max_width  = *data++;
360
	quad->max_height = *data++;
361
362
	quad->m.x0 = *data++;
363
	quad->m.y0 = *data++;
364
365
	quad++;
366
    }
367
368
    return n;
369
}
370
371
static int
3018.3.1 by Daniel van Vugt
Avoid uninitialized memory reads, which could lead to unpredictable results.
372
decor_point_cmp (const decor_point_t *a, const decor_point_t *b)
373
{
374
    /* Use binary | to avoid branch prediction slow-downs */
375
    return (a->x - b->x) | (a->y - b->y) | (a->gravity - b->gravity);
376
}
377
378
int
3308.7.4 by Sam Spilsbury
A failing test for the shadow properties
379
decor_shadow_options_cmp (const decor_shadow_options_t *a,
380
			  const decor_shadow_options_t *b)
381
{
382
    return (a->shadow_radius != b->shadow_radius) ||
383
	   (a->shadow_opacity != b->shadow_opacity) ||
384
	   (a->shadow_offset_x != b->shadow_offset_x) ||
385
	   (a->shadow_offset_y != b->shadow_offset_y) ||
386
	   memcmp (a->shadow_color, b->shadow_color, sizeof (unsigned short) * 3);
387
}
388
389
static int
3018.3.1 by Daniel van Vugt
Avoid uninitialized memory reads, which could lead to unpredictable results.
390
decor_matrix_cmp (const decor_matrix_t *a, const decor_matrix_t *b)
391
{
392
    return (a->xx != b->xx) ||
3018.3.2 by Daniel van Vugt
Remove memcmp to avoid making assumptions about the compiler.
393
           (a->yx != b->yx) ||
394
           (a->xy != b->xy) ||
395
           (a->yy != b->yy) ||
396
           (a->x0 != b->x0) ||
397
           (a->y0 != b->y0);
398
}
3018.3.1 by Daniel van Vugt
Avoid uninitialized memory reads, which could lead to unpredictable results.
399
400
static int
401
decor_quad_cmp (const decor_quad_t *a, const decor_quad_t *b)
402
{
403
    return decor_point_cmp (&a->p1, &b->p1) ||
404
           decor_point_cmp (&a->p2, &b->p2) ||
405
           decor_matrix_cmp (&a->m, &b->m)  ||
406
           (
407
               (a->max_width  - b->max_width)  |
408
               (a->max_height - b->max_height) |
409
               (a->align      - b->align)      |
410
               (a->clamp      - b->clamp)      |
411
               (a->stretch    - b->stretch)
412
           );
413
}
414
415
int
3308.10.2 by Sam Spilsbury
Added some new utility files for cairo and metacity window decorations for the
416
decor_extents_cmp (const decor_extents_t *a, const decor_extents_t *b)
3018.3.1 by Daniel van Vugt
Avoid uninitialized memory reads, which could lead to unpredictable results.
417
{
418
    /* Use binary | to avoid branch prediction slow-downs */
419
    return (a->left   - b->left)  |
420
           (a->right  - b->right) |
421
           (a->top    - b->top)   |
422
           (a->bottom - b->bottom);
423
}
424
425
/* Returns n for a match, returns -1 for no match */
2974.2.11 by smspillaz
Don't spuriously re-create decorations when we don't need to. Also handle the
426
427
int
428
decor_match_pixmap (long		 *data,
429
		    int		 size,
430
		    Pixmap		 *pixmap,
431
		    decor_extents_t  *frame,
432
		    decor_extents_t  *border,
433
		    decor_extents_t  *max_frame,
434
		    decor_extents_t  *max_border,
435
		    int		 min_width,
436
		    int		 min_height,
437
		    unsigned int     frame_type,
438
		    unsigned int     frame_state,
439
		    unsigned int     frame_actions,
440
		    decor_quad_t     *quad,
441
		    unsigned int     n_quad)
442
{
443
    int n = decor_property_get_num (data);
444
    unsigned int i = 0;
445
446
    for (; i < n; i++)
447
    {
448
	Pixmap cPixmap;
449
	decor_extents_t cFrame, cBorder, cMax_frame, cMax_border;
450
	int cMin_width, cMin_height;
451
	int q;
3018.3.1 by Daniel van Vugt
Avoid uninitialized memory reads, which could lead to unpredictable results.
452
	unsigned int cFrame_type, cFrame_state, cFrame_actions, cNQuad;
2974.2.11 by smspillaz
Don't spuriously re-create decorations when we don't need to. Also handle the
453
	decor_quad_t cQuad[N_QUADS_MAX];
454
	cNQuad = decor_pixmap_property_to_quads (data, i, size, &cPixmap, &cFrame, &cBorder, &cMax_frame,
455
						 &cMax_border, &cMin_width, &cMin_height, &cFrame_type,
456
						 &cFrame_state, &cFrame_actions, cQuad);
457
458
	if (cPixmap != *pixmap)
459
	    continue;
460
461
	if (decor_extents_cmp (&cFrame, frame) ||
3018.3.1 by Daniel van Vugt
Avoid uninitialized memory reads, which could lead to unpredictable results.
462
	    decor_extents_cmp (&cBorder, border) ||
463
	    decor_extents_cmp (&cMax_frame, max_frame) ||
464
	    decor_extents_cmp (&cMax_border, max_border))
465
	    continue;
2974.2.11 by smspillaz
Don't spuriously re-create decorations when we don't need to. Also handle the
466
467
	if (cFrame_type != frame_type ||
468
	    cFrame_state != frame_state ||
469
	    cFrame_actions != frame_actions ||
470
	    cMin_width != min_width ||
471
	    cMin_height != min_height)
472
	    continue;
473
474
	if (cNQuad != n_quad)
475
	    continue;
476
477
	q = 0;
3018.3.1 by Daniel van Vugt
Avoid uninitialized memory reads, which could lead to unpredictable results.
478
	while (q < n_quad && !decor_quad_cmp (&cQuad[q], &quad[q]))
479
	    q++;
480
481
	if (q < n_quad)
482
	    continue;
2974.2.11 by smspillaz
Don't spuriously re-create decorations when we don't need to. Also handle the
483
484
	return n;
485
    }
486
487
    return -1;
488
}
489
490
int
2025 by Dennis Kasprzyk
Added support for 2D decorations.
491
decor_window_property (long	       *data,
492
		       unsigned int    n,
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
493
		       int	       size,
2025 by Dennis Kasprzyk
Added support for 2D decorations.
494
		       decor_extents_t *input,
495
		       decor_extents_t *max_input,
496
		       int	       *min_width,
497
		       int	       *min_height,
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
498
		       unsigned int    *frame_type,
499
		       unsigned int    *frame_state,
500
		       unsigned int    *frame_actions)
501
{
2025 by Dennis Kasprzyk
Added support for 2D decorations.
502
    if (decor_property_get_version (data) != decor_version ())
503
        return 0;
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
504
2025 by Dennis Kasprzyk
Added support for 2D decorations.
505
    if (decor_property_get_type (data) != WINDOW_DECORATION_TYPE_WINDOW)
506
        return 0;
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
507
508
    if (size < PROP_HEADER_SIZE + n * WINDOW_PROP_SIZE)
509
        return 0;
510
511
    data += PROP_HEADER_SIZE + n * WINDOW_PROP_SIZE;
512
2025 by Dennis Kasprzyk
Added support for 2D decorations.
513
    input->left   = *data++;
514
    input->right  = *data++;
515
    input->top    = *data++;
516
    input->bottom = *data++;
517
518
    max_input->left   = *data++;
519
    max_input->right  = *data++;
520
    max_input->top    = *data++;
521
    max_input->bottom = *data++;
522
523
    *min_width  = *data++;
524
    *min_height = *data++;
525
526
    *frame_type = *data++;
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
527
    *frame_state = *data++;
528
    *frame_actions = *data++;
529
530
    return 1;
2025 by Dennis Kasprzyk
Added support for 2D decorations.
531
}
532
533
static int
859 by David Reveman
Add blur utility function to libdecoration.
534
add_blur_boxes (long   *data,
535
		BoxPtr box,
536
		int    n_box,
537
		int    width,
538
		int    height,
539
		int    gravity,
540
		int    offset)
541
{
542
    int x1, y1, x2, y2;
543
    int more_gravity;
544
    int n = n_box;
545
546
    while (n--)
547
    {
548
	x1 = box->x1;
549
	y1 = box->y1;
550
	x2 = box->x2;
551
	y2 = box->y2;
552
553
	if (gravity & (GRAVITY_NORTH | GRAVITY_SOUTH))
554
	{
555
	    if (x1 > offset)
556
	    {
557
		more_gravity = GRAVITY_EAST;
558
		x1 -= width;
559
	    }
560
	    else
561
	    {
562
		more_gravity = GRAVITY_WEST;
563
	    }
564
	}
565
	else
566
	{
567
	    if (y1 > offset)
568
	    {
569
		more_gravity = GRAVITY_SOUTH;
570
		y1 -= height;
571
	    }
572
	    else
573
	    {
574
		more_gravity = GRAVITY_NORTH;
575
	    }
576
	}
577
578
	*data++ = gravity | more_gravity;
579
	*data++ = x1;
580
	*data++ = y1;
581
582
	if (gravity & (GRAVITY_NORTH | GRAVITY_SOUTH))
583
	{
584
	    if (x2 > offset)
585
	    {
586
		more_gravity = GRAVITY_EAST;
587
		x2 -= width;
588
	    }
589
	    else
590
	    {
591
		more_gravity = GRAVITY_WEST;
592
	    }
593
	}
594
	else
595
	{
596
	    if (y2 > offset)
597
	    {
598
		more_gravity = GRAVITY_SOUTH;
599
		y2 -= height;
600
	    }
601
	    else
602
	    {
603
		more_gravity = GRAVITY_NORTH;
604
	    }
605
	}
606
607
	*data++ = gravity | more_gravity;
608
	*data++ = x2;
609
	*data++ = y2;
610
611
	box++;
612
    }
613
614
    return n_box * 6;
615
}
616
617
void
618
decor_region_to_blur_property (long   *data,
619
			       int    threshold,
620
			       int    filter,
621
			       int    width,
622
			       int    height,
623
			       Region top_region,
624
			       int    top_offset,
625
			       Region bottom_region,
626
			       int    bottom_offset,
627
			       Region left_region,
628
			       int    left_offset,
629
			       Region right_region,
630
			       int    right_offset)
631
{
632
    *data++ = threshold;
633
    *data++ = filter;
634
635
    if (top_region)
636
	data += add_blur_boxes (data,
637
				top_region->rects,
638
				top_region->numRects,
639
				width, height,
640
				GRAVITY_NORTH,
641
				top_offset);
642
643
    if (bottom_region)
644
	data += add_blur_boxes (data,
645
				bottom_region->rects,
646
				bottom_region->numRects,
647
				width, height,
648
				GRAVITY_SOUTH,
649
				bottom_offset);
650
651
    if (left_region)
652
	data += add_blur_boxes (data,
653
				left_region->rects,
654
				left_region->numRects,
655
				width, height,
656
				GRAVITY_WEST,
657
				left_offset);
658
659
    if (right_region)
660
	data += add_blur_boxes (data,
661
				right_region->rects,
662
				right_region->numRects,
663
				width, height,
664
				GRAVITY_EAST,
665
				right_offset);
666
}
667
668
void
843 by David Reveman
Move applyGravity function into libdecoration.
669
decor_apply_gravity (int gravity,
670
		     int x,
671
		     int y,
672
		     int width,
673
		     int height,
674
		     int *return_x,
675
		     int *return_y)
676
{
677
    if (gravity & GRAVITY_EAST)
678
    {
679
	x += width;
680
	*return_x = MAX (0, x);
681
    }
682
    else if (gravity & GRAVITY_WEST)
683
    {
684
	*return_x = MIN (width, x);
685
    }
686
    else
687
    {
688
	x += width / 2;
689
	x = MAX (0, x);
690
	x = MIN (width, x);
691
	*return_x = x;
692
    }
693
694
    if (gravity & GRAVITY_SOUTH)
695
    {
696
	y += height;
697
	*return_y = MAX (0, y);
698
    }
699
    else if (gravity & GRAVITY_NORTH)
700
    {
701
	*return_y = MIN (height, y);
702
    }
703
    else
704
    {
705
	y += height / 2;
706
	y = MAX (0, y);
707
	y = MIN (height, y);
708
	*return_y = y;
709
    }
710
}
711
712
int
681 by David Reveman
Move decoration property decoding into libdecoration.
713
decor_set_vert_quad_row (decor_quad_t *q,
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
714
			 int	      top,
715
			 int	      top_corner,
716
			 int	      bottom,
717
			 int	      bottom_corner,
718
			 int	      left,
719
			 int	      right,
720
			 int	      gravity,
721
			 int	      height,
722
			 int	      splitY,
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
723
			 int	      splitGravity,
724
			 double	      x0,
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
725
			 double	      y0,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
726
			 int	      rotation)
727
{
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
728
    int nQuad = 0;
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
729
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
730
    q->p1.x	  = left;
731
    q->p1.y	  = -top;
732
    q->p1.gravity = gravity | GRAVITY_NORTH;
733
    q->p2.x	  = right;
734
    q->p2.y	  = splitY;
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
735
    q->p2.gravity = gravity | splitGravity;
736
    q->max_width  = SHRT_MAX;
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
737
    q->max_height = top + top_corner;
738
    q->align	  = ALIGN_TOP;
739
    q->clamp	  = CLAMP_VERT;
740
    q->stretch    = 0;
1042.1.4 by Danny Baumann
Added quad stretching interface to libdecoration.
741
    q->m.x0	  = x0;
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
742
    q->m.y0	  = y0;
743
744
    if (rotation)
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
745
    {
746
	q->m.xx	= 0.0;
747
	q->m.xy	= 1.0;
748
	q->m.yx	= 1.0;
749
	q->m.yy	= 0.0;
750
    }
751
    else
752
    {
753
	q->m.xx	= 1.0;
754
	q->m.xy	= 0.0;
755
	q->m.yx	= 0.0;
756
	q->m.yy	= 1.0;
757
    }
758
759
    q++; nQuad++;
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
760
761
    q->p1.x	  = left;
762
    q->p1.y	  = top_corner;
763
    q->p1.gravity = gravity | GRAVITY_NORTH;
764
    q->p2.x	  = right;
765
    q->p2.y	  = -bottom_corner;
766
    q->p2.gravity = gravity | GRAVITY_SOUTH;
767
    q->max_width  = SHRT_MAX;
768
    q->max_height = SHRT_MAX;
769
    q->align	  = 0;
770
    q->clamp	  = CLAMP_VERT;
771
    q->stretch    = 0;
1042.1.4 by Danny Baumann
Added quad stretching interface to libdecoration.
772
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
773
    if (rotation)
774
    {
775
	q->m.xx	= 0.0;
776
	q->m.xy	= 0.0;
777
	q->m.yx	= 1.0;
778
	q->m.yy	= 0.0;
779
	q->m.x0	= x0 + top + top_corner;
780
	q->m.y0	= y0;
781
    }
782
    else
783
    {
784
	q->m.xx	= 1.0;
785
	q->m.xy	= 0.0;
786
	q->m.yx	= 0.0;
787
	q->m.yy	= 0.0;
788
	q->m.x0	= x0;
789
	q->m.y0	= y0 + top + top_corner;
790
    }
791
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
792
    q++; nQuad++;
793
794
    q->p1.x	  = left;
795
    q->p1.y	  = splitY;
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
796
    q->p1.gravity = gravity | splitGravity;
797
    q->p2.x	  = right;
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
798
    q->p2.y	  = bottom;
799
    q->p2.gravity = gravity | GRAVITY_SOUTH;
800
    q->max_width  = SHRT_MAX;
801
    q->max_height = bottom_corner + bottom;
802
    q->align	  = ALIGN_BOTTOM;
803
    q->clamp	  = CLAMP_VERT;
804
    q->stretch    = 0;
1042.1.4 by Danny Baumann
Added quad stretching interface to libdecoration.
805
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
806
    if (rotation)
807
    {
808
	q->m.xx	= 0.0;
809
	q->m.xy	= 1.0;
810
	q->m.yx	= 1.0;
811
	q->m.yy	= 0.0;
812
	q->m.x0	= x0 + height;
813
	q->m.y0	= y0;
814
    }
815
    else
816
    {
817
	q->m.xx	= 1.0;
818
	q->m.xy	= 0.0;
819
	q->m.yx	= 0.0;
820
	q->m.yy	= 1.0;
821
	q->m.x0	= x0;
822
	q->m.y0	= y0 + height;
823
    }
824
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
825
    nQuad++;
826
827
    return nQuad;
828
}
829
830
int
831
decor_set_horz_quad_line (decor_quad_t *q,
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
832
			  int	       left,
833
			  int	       left_corner,
834
			  int	       right,
835
			  int	       right_corner,
836
			  int	       top,
837
			  int	       bottom,
838
			  int	       gravity,
839
			  int	       width,
840
			  int	       splitX,
841
			  int	       splitGravity,
842
			  double       x0,
843
			  double       y0)
844
{
845
    int nQuad = 0;
846
847
    q->p1.x	  = -left;
848
    q->p1.y	  = top;
849
    q->p1.gravity = gravity | GRAVITY_WEST;
850
    q->p2.x	  = splitX;
851
    q->p2.y	  = bottom;
852
    q->p2.gravity = gravity | splitGravity;
853
    q->max_width  = left + left_corner;
854
    q->max_height = SHRT_MAX;
855
    q->align	  = ALIGN_LEFT;
856
    q->clamp	  = 0;
857
    q->stretch    = 0;
1042.1.4 by Danny Baumann
Added quad stretching interface to libdecoration.
858
    q->m.xx	  = 1.0;
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
859
    q->m.xy	  = 0.0;
860
    q->m.yx	  = 0.0;
861
    q->m.yy	  = 1.0;
862
    q->m.x0	  = x0;
863
    q->m.y0	  = y0;
864
865
    q++; nQuad++;
866
867
    q->p1.x	  = left_corner;
868
    q->p1.y	  = top;
869
    q->p1.gravity = gravity | GRAVITY_WEST;
870
    q->p2.x	  = -right_corner;
871
    q->p2.y	  = bottom;
872
    q->p2.gravity = gravity | GRAVITY_EAST;
873
    q->max_width  = SHRT_MAX;
874
    q->max_height = SHRT_MAX;
875
    q->align	  = 0;
876
    q->clamp	  = 0;
877
    q->stretch    = 0;
1042.1.4 by Danny Baumann
Added quad stretching interface to libdecoration.
878
    q->m.xx	  = 0.0;
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
879
    q->m.xy	  = 0.0;
880
    q->m.yx	  = 0.0;
881
    q->m.yy	  = 1.0;
882
    q->m.x0	  = x0 + left + left_corner;
883
    q->m.y0	  = y0;
884
885
    q++; nQuad++;
886
887
    q->p1.x	  = splitX;
888
    q->p1.y	  = top;
889
    q->p1.gravity = gravity | splitGravity;
890
    q->p2.x	  = right;
891
    q->p2.y	  = bottom;
892
    q->p2.gravity = gravity | GRAVITY_EAST;
893
    q->max_width  = right_corner + right;
894
    q->max_height = SHRT_MAX;
895
    q->align	  = ALIGN_RIGHT;
896
    q->clamp	  = 0;
897
    q->stretch    = 0;
1042.1.4 by Danny Baumann
Added quad stretching interface to libdecoration.
898
    q->m.xx	  = 1.0;
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
899
    q->m.xy	  = 0.0;
900
    q->m.yx	  = 0.0;
901
    q->m.yy	  = 1.0;
902
    q->m.x0	  = x0 + width;
903
    q->m.y0	  = y0;
904
905
    nQuad++;
906
907
    return nQuad;
908
}
909
910
int
911
decor_set_lSrS_window_quads (decor_quad_t    *q,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
912
			     decor_context_t *c,
913
			     decor_layout_t  *l)
914
{
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
915
    int lh, rh, splitY, n, nQuad = 0;
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
916
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
917
    splitY = (c->top_corner_space - c->bottom_corner_space) / 2;
918
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
919
    if (l->rotation)
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
920
    {
921
	lh = l->left.x2 - l->left.x1;
922
	rh = l->right.x2 - l->right.x1;
923
    }
924
    else
925
    {
926
	lh = l->left.y2 - l->left.y1;
927
	rh = l->right.y2 - l->right.y1;
928
    }
929
930
    /* left quads */
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
931
    n = decor_set_vert_quad_row (q,
932
				 0,
933
				 c->top_corner_space,
934
				 0,
935
				 c->bottom_corner_space,
936
				 -c->left_space,
937
				 0,
938
				 GRAVITY_WEST,
939
				 lh,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
940
				 splitY,
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
941
				 0,
942
				 l->left.x1,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
943
				 l->left.y1,
944
				 l->rotation);
945
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
946
    q += n; nQuad += n;
947
948
    /* right quads */
949
    n = decor_set_vert_quad_row (q,
950
				 0,
951
				 c->top_corner_space,
952
				 0,
953
				 c->bottom_corner_space,
954
				 0,
955
				 c->right_space,
956
				 GRAVITY_EAST,
957
				 rh,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
958
				 splitY,
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
959
				 0,
960
				 l->right.x1,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
961
				 l->right.y1,
962
				 l->rotation);
963
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
964
    nQuad += n;
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
965
966
    return nQuad;
967
}
968
969
int
970
decor_set_lSrStSbS_window_quads (decor_quad_t    *q,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
971
				 decor_context_t *c,
972
				 decor_layout_t  *l)
973
{
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
974
    int splitX, n, nQuad = 0;
975
976
    splitX = (c->left_corner_space - c->right_corner_space) / 2;
977
978
    /* top quads */
979
    n = decor_set_horz_quad_line (q,
980
				  c->left_space,
981
				  c->left_corner_space,
982
				  c->right_space,
983
				  c->right_corner_space,
984
				  -c->top_space,
985
				  0,
986
				  GRAVITY_NORTH,
987
				  l->top.x2 - l->top.x1,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
988
				  splitX,
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
989
				  0,
990
				  l->top.x1,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
991
				  l->top.y1);
992
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
993
    q += n; nQuad += n;
994
995
    n = decor_set_lSrS_window_quads (q, c, l);
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
996
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
997
    q += n; nQuad += n;
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
998
999
    /* bottom quads */
1000
    n = decor_set_horz_quad_line (q,
1001
				  c->left_space,
1002
				  c->left_corner_space,
1003
				  c->right_space,
1004
				  c->right_corner_space,
1005
				  0,
1006
				  c->bottom_space,
1007
				  GRAVITY_SOUTH,
1008
				  l->bottom.x2 - l->bottom.x1,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
1009
				  splitX,
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
1010
				  0,
1011
				  l->bottom.x1,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
1012
				  l->bottom.y1);
1013
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
1014
    nQuad += n;
1015
1016
    return nQuad;
1017
}
1018
1019
int
1020
decor_set_lSrStXbS_window_quads (decor_quad_t    *q,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
1021
				 decor_context_t *c,
1022
				 decor_layout_t  *l,
1023
				 int		 top_stretch_offset)
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
1024
{
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
1025
    int splitX, n, nQuad = 0;
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
1026
    int top_left, top_right;
1027
1028
    splitX = (c->left_corner_space - c->right_corner_space) / 2;
1029
1030
    top_left  = top_stretch_offset;
1031
    top_right = l->top.x2 - l->top.x1 -
1032
	c->left_space - c->right_space - top_left - 1;
1033
1034
    /* top quads */
1035
    n = decor_set_horz_quad_line (q,
1036
				  c->left_space,
1037
				  top_left,
1038
				  c->right_space,
1039
				  top_right,
1040
				  -c->top_space,
1041
				  0,
1042
				  GRAVITY_NORTH,
1043
				  l->top.x2 - l->top.x1,
1044
				  -top_right,
658 by David Reveman
Stretch decorations from south-east instead.
1045
				  GRAVITY_EAST,
1046
				  l->top.x1,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
1047
				  l->top.y1);
1048
1049
    q += n; nQuad += n;
1050
1051
    n = decor_set_lSrS_window_quads (q, c, l);
1052
1053
    q += n; nQuad += n;
1054
1055
    /* bottom quads */
1056
    n = decor_set_horz_quad_line (q,
1057
				  c->left_space,
1058
				  c->left_corner_space,
1059
				  c->right_space,
1060
				  c->right_corner_space,
1061
				  0,
1062
				  c->bottom_space,
1063
				  GRAVITY_SOUTH,
1064
				  l->bottom.x2 - l->bottom.x1,
1065
				  splitX,
1066
				  0,
1067
				  l->bottom.x1,
1068
				  l->bottom.y1);
1069
1070
    nQuad += n;
1071
1072
    return nQuad;
1073
}
1074
1075
int
1076
decor_set_lSrStSbX_window_quads (decor_quad_t    *q,
1077
				 decor_context_t *c,
1078
				 decor_layout_t  *l,
1079
				 int		 bottom_stretch_offset)
1080
{
1081
    int splitX, n, nQuad = 0;
1082
    int bottom_left, bottom_right;
1083
1084
    splitX = (c->left_corner_space - c->right_corner_space) / 2;
1085
1086
    bottom_left  = bottom_stretch_offset;
1087
    bottom_right = l->bottom.x2 - l->bottom.x1 -
1088
	c->left_space - c->right_space - bottom_left - 1;
1089
1090
    /* top quads */
1091
    n = decor_set_horz_quad_line (q,
1092
				  c->left_space,
1093
				  c->left_corner_space,
1094
				  c->right_space,
1095
				  c->right_corner_space,
1096
				  -c->top_space,
1097
				  0,
1098
				  GRAVITY_NORTH,
1099
				  l->top.x2 - l->top.x1,
1100
				  splitX,
1101
				  0,
1102
				  l->top.x1,
1103
				  l->top.y1);
1104
1105
    q += n; nQuad += n;
1106
1107
    n = decor_set_lSrS_window_quads (q, c, l);
1108
1109
    q += n; nQuad += n;
1110
1111
    /* bottom quads */
1112
    n = decor_set_horz_quad_line (q,
1113
				  c->left_space,
1114
				  bottom_left,
1115
				  c->right_space,
1116
				  bottom_right,
1117
				  0,
1118
				  c->bottom_space,
1119
				  GRAVITY_SOUTH,
1120
				  l->bottom.x2 - l->bottom.x1,
1121
				  -bottom_right,
658 by David Reveman
Stretch decorations from south-east instead.
1122
				  GRAVITY_EAST,
1123
				  l->bottom.x1,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
1124
				  l->bottom.y1);
1125
1126
    nQuad += n;
1127
1128
    return nQuad;
1129
}
1130
1131
int
1132
decor_set_lXrXtXbX_window_quads (decor_quad_t    *q,
1133
				 decor_context_t *c,
1134
				 decor_layout_t  *l,
1135
				 int		 left_stretch_offset,
1136
				 int		 right_stretch_offset,
1137
				 int		 top_stretch_offset,
1138
				 int		 bottom_stretch_offset)
1139
{
1140
    int lh, rh, n, nQuad = 0;
1141
    int left_top, left_bottom;
1142
    int right_top, right_bottom;
1143
    int top_left, top_right;
1144
    int bottom_left, bottom_right;
1145
1146
    top_left  = top_stretch_offset;
1147
    top_right = l->top.x2 - l->top.x1 -
1148
	c->left_space - c->right_space - top_left - 1;
1149
1150
    bottom_left  = bottom_stretch_offset;
1151
    bottom_right = l->bottom.x2 - l->bottom.x1 -
1152
	c->left_space - c->right_space - bottom_left - 1;
1153
1154
    if (l->rotation)
1155
    {
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
1156
	lh = l->left.x2 - l->left.x1;
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
1157
	rh = l->right.x2 - l->right.x1;
1158
    }
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
1159
    else
1160
    {
1161
	lh = l->left.y2 - l->left.y1;
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
1162
	rh = l->right.y2 - l->right.y1;
1163
    }
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
1164
1165
    left_top    = left_stretch_offset;
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
1166
    left_bottom = lh - left_top - 1;
1167
1168
    right_top    = right_stretch_offset;
1169
    right_bottom = rh - right_top - 1;
1170
1171
1172
    /* top quads */
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
1173
    n = decor_set_horz_quad_line (q,
1174
				  c->left_space,
1175
				  top_left,
1176
				  c->right_space,
1177
				  top_right,
1178
				  -c->top_space,
1179
				  0,
1180
				  GRAVITY_NORTH,
1181
				  l->top.x2 - l->top.x1,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
1182
				  -top_right,
658 by David Reveman
Stretch decorations from south-east instead.
1183
				  GRAVITY_EAST,
1184
				  l->top.x1,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
1185
				  l->top.y1);
1186
1187
    q += n; nQuad += n;
1188
1189
    /* left quads */
1190
    n = decor_set_vert_quad_row (q,
1191
				 0,
1192
				 left_top,
1193
				 0,
1194
				 left_bottom,
1195
				 -c->left_space,
1196
				 0,
1197
				 GRAVITY_WEST,
1198
				 lh,
1199
				 -left_bottom,
658 by David Reveman
Stretch decorations from south-east instead.
1200
				 GRAVITY_SOUTH,
1201
				 l->left.x1,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
1202
				 l->left.y1,
1203
				 l->rotation);
1204
1205
    q += n; nQuad += n;
1206
1207
    /* right quads */
1208
    n = decor_set_vert_quad_row (q,
1209
				 0,
1210
				 right_top,
1211
				 0,
1212
				 right_bottom,
1213
				 0,
1214
				 c->right_space,
1215
				 GRAVITY_EAST,
1216
				 rh,
1217
				 -right_bottom,
658 by David Reveman
Stretch decorations from south-east instead.
1218
				 GRAVITY_SOUTH,
1219
				 l->right.x1,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
1220
				 l->right.y1,
1221
				 l->rotation);
1222
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
1223
    q += n; nQuad += n;
1224
1225
    /* bottom quads */
1226
    n = decor_set_horz_quad_line (q,
1227
				  c->left_space,
1228
				  bottom_left,
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
1229
				  c->right_space,
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
1230
				  bottom_right,
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
1231
				  0,
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
1232
				  c->bottom_space,
1233
				  GRAVITY_SOUTH,
1234
				  l->bottom.x2 - l->bottom.x1,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
1235
				  -bottom_right,
658 by David Reveman
Stretch decorations from south-east instead.
1236
				  GRAVITY_EAST,
1237
				  l->bottom.x1,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
1238
				  l->bottom.y1);
1239
627 by David Reveman
Add libdecoration and move some initial code from gtk-window-decorator into it.
1240
    nQuad += n;
1241
1242
    return nQuad;
1243
}
1244
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
1245
#if INT_MAX != LONG_MAX
1246
1247
static int errors;
1248
1249
static int
1250
error_handler (Display *xdisplay,
1251
	       XErrorEvent *event)
1252
{
1253
    errors++;
1254
    return 0;
1255
}
1256
1257
/* XRenderSetPictureFilter used to be broken on LP64. This
1258
 * works with either the broken or fixed version.
1259
 */
1260
static void
1261
XRenderSetPictureFilter_wrapper (Display *dpy,
1262
				 Picture picture,
1263
				 char    *filter,
1264
				 XFixed  *params,
1265
				 int     nparams)
1266
{
1267
    int (*old) (Display *, XErrorEvent *);
1268
1269
    errors = 0;
1270
1271
    old = XSetErrorHandler (error_handler);
1272
1273
    XRenderSetPictureFilter (dpy, picture, filter, params, nparams);
1274
    XSync (dpy, False);
1275
1276
    XSetErrorHandler (old);
1277
1278
    if (errors)
1279
    {
1280
	long *long_params = malloc (sizeof (long) * nparams);
1281
	int  i;
1282
1283
	for (i = 0; i < nparams; i++)
1284
	    long_params[i] = params[i];
1285
1286
	XRenderSetPictureFilter (dpy, picture, filter,
1287
				 (XFixed *) long_params, nparams);
1288
	free (long_params);
1289
    }
1290
}
1291
1292
#define XRenderSetPictureFilter XRenderSetPictureFilter_wrapper
1293
#endif
1294
1295
static void
1296
set_picture_transform (Display *xdisplay,
1297
		       Picture p,
1298
		       int     dx,
1299
		       int     dy)
1300
{
1301
    XTransform transform = {
1302
	{
1303
	    { 1 << 16, 0,       -dx << 16 },
1304
	    { 0,       1 << 16, -dy << 16 },
1305
	    { 0,       0,         1 << 16 },
1306
	}
1307
    };
1308
1309
    XRenderSetPictureTransform (xdisplay, p, &transform);
1310
}
1311
1312
static void
648 by David Reveman
Improve shadow code performance by adding clipping and avoiding opacity
1313
set_picture_clip (Display *xdisplay,
1314
		  Picture p,
1315
		  int     width,
1316
		  int	  height,
1317
		  int     clipX1,
1318
		  int     clipY1,
1319
		  int     clipX2,
1320
		  int     clipY2)
1321
{
1322
    XRectangle clip[4];
1323
1324
    clip[0].x      = 0;
1325
    clip[0].y      = 0;
1326
    clip[0].width  = width;
1327
    clip[0].height = clipY1;
1328
1329
    clip[1].x      = 0;
1330
    clip[1].y      = clipY2;
1331
    clip[1].width  = width;
1332
    clip[1].height = height - clipY2;
1333
1334
    clip[2].x      = 0;
1335
    clip[2].y      = clipY1;
1336
    clip[2].width  = clipX1;
1337
    clip[2].height = clipY2 - clipY1;
1338
1339
    clip[3].x      = clipX2;
1340
    clip[3].y      = clipY1;
1341
    clip[3].width  = width - clipX2;
1342
    clip[3].height = clipY2 - clipY1;
1343
1344
    XRenderSetPictureClipRectangles (xdisplay, p, 0, 0, clip, 4);
1345
}
1346
1347
static void
1348
set_no_picture_clip (Display *xdisplay,
1349
		     Picture p)
651 by David Reveman
Rewrote decoration opacity code and moved it to libdecoration.
1350
{
648 by David Reveman
Improve shadow code performance by adding clipping and avoiding opacity
1351
    XRectangle clip;
1352
1353
    clip.x      = 0;
1354
    clip.y      = 0;
1355
    clip.width  = SHRT_MAX;
651 by David Reveman
Rewrote decoration opacity code and moved it to libdecoration.
1356
    clip.height = SHRT_MAX;
1357
648 by David Reveman
Improve shadow code performance by adding clipping and avoiding opacity
1358
    XRenderSetPictureClipRectangles (xdisplay, p, 0, 0, &clip, 1);
1359
}
1360
1361
static XFixed *
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
1362
create_gaussian_kernel (double radius,
1363
			double sigma,
1364
			double alpha,
1365
			int    *r_size)
1366
{
1367
    XFixed *params;
1368
    double *amp, scale, x_scale, fx, sum;
1369
    int    size, half_size, x, i, n;
1370
1371
    scale = 1.0f / (2.0f * M_PI * sigma * sigma);
1372
    half_size = alpha + 0.5f;
1373
1374
    if (half_size == 0)
1375
	half_size = 1;
1376
1377
    size = half_size * 2 + 1;
1378
    x_scale = 2.0f * radius / size;
1379
1380
    if (size < 3)
1381
	return NULL;
1382
1383
    n = size;
1384
1385
    amp = malloc (sizeof (double) * n);
1386
    if (!amp)
1387
	return NULL;
1388
1389
    n += 2;
1390
1391
    params = malloc (sizeof (XFixed) * n);
1392
    if (!params)
1393
    {
767 by David Reveman
Free memory allocated earlier if out-of-memory. Very unlikely to happen.
1394
	free (amp);
1395
	return NULL;
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
1396
    }
767 by David Reveman
Free memory allocated earlier if out-of-memory. Very unlikely to happen.
1397
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
1398
    i   = 0;
1399
    sum = 0.0f;
1400
1401
    for (x = 0; x < size; x++)
1402
    {
1403
	fx = x_scale * (x - half_size);
1404
1405
	amp[i] = scale * exp ((-1.0f * (fx * fx)) / (2.0f * sigma * sigma));
1406
1407
	sum += amp[i];
1408
1409
	i++;
1410
    }
1411
1412
    /* normalize */
1413
    if (sum != 0.0)
1414
	sum = 1.0 / sum;
1415
1416
    params[0] = params[1] = 0;
1417
1418
    for (i = 2; i < n; i++)
1419
	params[i] = XDoubleToFixed (amp[i - 2] * sum);
646 by David Reveman
Move more code into libdecoration.
1420
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
1421
    free (amp);
1422
1423
    *r_size = size;
1424
1425
    return params;
1426
}
1427
1428
#define SIGMA(r) ((r) / 2.0)
1429
#define ALPHA(r) (r)
1430
1431
decor_shadow_t *
1432
decor_shadow_create (Display		    *xdisplay,
708 by David Reveman
Add reference counting and fixup function names.
1433
		     Screen		    *screen,
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
1434
		     int		    width,
1435
		     int		    height,
1436
		     int		    left,
1437
		     int		    right,
1438
		     int		    top,
1439
		     int		    bottom,
1440
		     int		    solid_left,
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
1441
		     int		    solid_right,
1442
		     int		    solid_top,
1443
		     int		    solid_bottom,
1444
		     decor_shadow_options_t *opt,
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
1445
		     decor_context_t	    *c,
1446
		     decor_draw_func_t	    draw,
646 by David Reveman
Move more code into libdecoration.
1447
		     void		    *closure)
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
1448
{
1449
    static XRenderColor white = { 0xffff, 0xffff, 0xffff, 0xffff };
648 by David Reveman
Improve shadow code performance by adding clipping and avoiding opacity
1450
    XRenderPictFormat   *format;
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
1451
    Pixmap		pixmap;
1452
    Picture		src, dst, tmp;
1453
    XFixed		opacity, *params;
646 by David Reveman
Move more code into libdecoration.
1454
    XFilters		*filters;
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
1455
    char		*filter = NULL;
1456
    int			size, n_params = 0;
1457
    XRenderColor	color;
1458
    int			shadow_offset_x;
1459
    int			shadow_offset_y;
1460
    Pixmap		d_pixmap;
1461
    int			d_width;
1462
    int			d_height;
1463
    Window		xroot = screen->root;
1464
    decor_shadow_t	*shadow;
1465
    int			clipX1, clipY1, clipX2, clipY2;
648 by David Reveman
Improve shadow code performance by adding clipping and avoiding opacity
1466
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
1467
    shadow = malloc (sizeof (decor_shadow_t));
1468
    if (!shadow)
1469
	return NULL;
1470
1471
    shadow->ref_count = 1;
708 by David Reveman
Add reference counting and fixup function names.
1472
1473
    shadow->pixmap  = 0;
642 by David Reveman
Expose decor_shadow_t struct and add pixmap to this struct.
1474
    shadow->picture = 0;
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
1475
    shadow->width   = 0;
1476
    shadow->height  = 0;
1477
1478
    shadow_offset_x = opt->shadow_offset_x;
1479
    shadow_offset_y = opt->shadow_offset_y;
1480
1481
    /* compute a gaussian convolution kernel */
1482
    params = create_gaussian_kernel (opt->shadow_radius,
1483
				     SIGMA (opt->shadow_radius),
1484
				     ALPHA (opt->shadow_radius),
1485
				     &size);
1486
    if (!params)
1487
	shadow_offset_x = shadow_offset_y = size = 0;
1488
1489
    if (opt->shadow_radius <= 0.0 &&
1490
	shadow_offset_x == 0	  &&
1491
	shadow_offset_y == 0)
1492
	size = 0;
1493
1494
    n_params = size + 2;
1495
    size     = size / 2;
1496
1497
    c->extents.left   = left;
646 by David Reveman
Move more code into libdecoration.
1498
    c->extents.right  = right;
1499
    c->extents.top    = top;
1500
    c->extents.bottom = bottom;
1501
1502
    c->left_space   = left   + size - shadow_offset_x;
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
1503
    c->right_space  = right  + size + shadow_offset_x;
1504
    c->top_space    = top    + size - shadow_offset_y;
1505
    c->bottom_space = bottom + size + shadow_offset_y;
1506
1507
    c->left_space   = MAX (left,   c->left_space);
1508
    c->right_space  = MAX (right,  c->right_space);
1509
    c->top_space    = MAX (top,    c->top_space);
1510
    c->bottom_space = MAX (bottom, c->bottom_space);
1511
1512
    c->left_corner_space   = MAX (1, size - solid_left   + shadow_offset_x);
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
1513
    c->right_corner_space  = MAX (1, size - solid_right  - shadow_offset_x);
1514
    c->top_corner_space    = MAX (1, size - solid_top    + shadow_offset_y);
1515
    c->bottom_corner_space = MAX (1, size - solid_bottom - shadow_offset_y);
1516
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
1517
    width  = MAX (width, c->left_corner_space + c->right_corner_space);
646 by David Reveman
Move more code into libdecoration.
1518
    height = MAX (height, c->top_corner_space + c->bottom_corner_space);
1519
1520
    width  = MAX (1, width);
1521
    height = MAX (1, height);
1522
1523
    d_width  = c->left_space + width + c->right_space;
1524
    d_height = c->top_space + height + c->bottom_space;
1525
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
1526
    /* all pixmaps are ARGB32 */
1527
    format = XRenderFindStandardFormat (xdisplay, PictStandardARGB32);
1528
1529
    /* no shadow */
1530
    if (size <= 0)
1531
    {
1532
	if (params)
1533
	    free (params);
1534
1535
	return shadow;
1536
    }
1537
1538
    pixmap = XCreatePixmap (xdisplay, xroot, d_width, d_height, 32);
1539
    if (!pixmap)
1540
    {
1541
	free (params);
1542
	return shadow;
1543
    }
1544
1545
    /* query server for convolution filter */
1546
    filters = XRenderQueryFilters (xdisplay, pixmap);
1547
    if (filters)
1548
    {
1549
	int i;
1550
1551
	for (i = 0; i < filters->nfilter; i++)
1552
	{
1553
	    if (strcmp (filters->filter[i], FilterConvolution) == 0)
1554
	    {
1555
		filter = (char *) FilterConvolution;
1556
		break;
1557
	    }
1558
	}
1559
1560
	XFree (filters);
1561
    }
1562
1563
    if (!filter)
1564
    {
1565
	XFreePixmap (xdisplay, pixmap);
1566
	free (params);
1567
1568
	return shadow;
1569
    }
1570
1571
    /* create pixmap for temporary decorations */
1572
    d_pixmap = XCreatePixmap (xdisplay, xroot, d_width, d_height, 32);
1573
    if (!d_pixmap)
1574
    {
1575
	XFreePixmap (xdisplay, pixmap);
646 by David Reveman
Move more code into libdecoration.
1576
	free (params);
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
1577
1578
	return shadow;
1579
    }
1580
1581
    src = XRenderCreateSolidFill (xdisplay, &white);
648 by David Reveman
Improve shadow code performance by adding clipping and avoiding opacity
1582
    dst = XRenderCreatePicture (xdisplay, d_pixmap, format, 0, NULL);
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
1583
    tmp = XRenderCreatePicture (xdisplay, pixmap, format, 0, NULL);
1584
1585
    /* draw decoration */
1586
    (*draw) (xdisplay, d_pixmap, dst, d_width, d_height, c, closure);
646 by David Reveman
Move more code into libdecoration.
1587
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
1588
    /* first pass */
1589
    params[0] = (n_params - 2) << 16;
1590
    params[1] = 1 << 16;
1591
1592
    clipX1 = c->left_space + size;
648 by David Reveman
Improve shadow code performance by adding clipping and avoiding opacity
1593
    clipY1 = c->top_space  + size;
1594
    clipX2 = d_width - c->right_space - size;
1595
    clipY2 = d_height - c->bottom_space - size;
1596
1597
    if (clipX1 < clipX2 && clipY1 < clipY2)
1598
	set_picture_clip (xdisplay, tmp, d_width, d_height,
1599
			  clipX1, clipY1, clipX2, clipY2);
1600
1601
    set_picture_transform (xdisplay, dst, shadow_offset_x, 0);
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
1602
    XRenderSetPictureFilter (xdisplay, dst, filter, params, n_params);
1603
    XRenderComposite (xdisplay,
1604
		      PictOpSrc,
1605
		      src,
1606
		      dst,
1607
		      tmp,
1608
		      0, 0,
1609
		      0, 0,
1610
		      0, 0,
1611
		      d_width, d_height);
1612
1613
    set_no_picture_clip (xdisplay, tmp);
651 by David Reveman
Rewrote decoration opacity code and moved it to libdecoration.
1614
648 by David Reveman
Improve shadow code performance by adding clipping and avoiding opacity
1615
    XRenderFreePicture (xdisplay, src);
1616
1617
    /* second pass */
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
1618
    params[0] = 1 << 16;
1619
    params[1] = (n_params - 2) << 16;
1620
1621
    opacity = XDoubleToFixed (opt->shadow_opacity);
648 by David Reveman
Improve shadow code performance by adding clipping and avoiding opacity
1622
    if (opacity < (1 << 16))
1623
    {
1624
	/* apply opacity as shadow color if less than 1.0 */
1625
	color.red   = (opt->shadow_color[0] * opacity) >> 16;
1626
	color.green = (opt->shadow_color[1] * opacity) >> 16;
1627
	color.blue  = (opt->shadow_color[2] * opacity) >> 16;
1628
	color.alpha = opacity;
1629
1630
	opacity = 1 << 16;
1631
    }
1632
    else
1633
    {
1634
	/* shadow color */
1635
	color.red   = opt->shadow_color[0];
1636
	color.green = opt->shadow_color[1];
1637
	color.blue  = opt->shadow_color[2];
1638
	color.alpha = 0xffff;
1639
    }
1640
1641
    src = XRenderCreateSolidFill (xdisplay, &color);
1642
1643
    clipX1 = c->left_space;
1644
    clipY1 = c->top_space;
1645
    clipX2 = d_width - c->right_space;
1646
    clipY2 = d_height - c->bottom_space;
1647
1648
    if (clipX1 < clipX2 && clipY1 < clipY2)
1649
	set_picture_clip (xdisplay, dst, d_width, d_height,
1650
			  clipX1, clipY1, clipX2, clipY2);
1651
1652
    set_picture_transform (xdisplay, tmp, 0, shadow_offset_y);
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
1653
    XRenderSetPictureFilter (xdisplay, tmp, filter, params, n_params);
1654
    XRenderComposite (xdisplay,
1655
		      PictOpSrc,
1656
		      src,
1657
		      tmp,
1658
		      dst,
1659
		      0, 0,
1660
		      0, 0,
1661
		      0, 0,
1662
		      d_width, d_height);
1663
1664
    set_no_picture_clip (xdisplay, dst);
651 by David Reveman
Rewrote decoration opacity code and moved it to libdecoration.
1665
648 by David Reveman
Improve shadow code performance by adding clipping and avoiding opacity
1666
    XRenderFreePicture (xdisplay, src);
1667
1668
    if (opacity != (1 << 16))
646 by David Reveman
Move more code into libdecoration.
1669
    {
1670
	XFixed p[3];
1671
1672
	p[0] = 1 << 16;
1673
	p[1] = 1 << 16;
1674
	p[2] = opacity;
1675
1676
	if (clipX1 < clipX2 && clipY1 < clipY2)
648 by David Reveman
Improve shadow code performance by adding clipping and avoiding opacity
1677
	    set_picture_clip (xdisplay, tmp, d_width, d_height,
1678
			      clipX1, clipY1, clipX2, clipY2);
1679
1680
	/* apply opacity */
646 by David Reveman
Move more code into libdecoration.
1681
	set_picture_transform (xdisplay, dst, 0, 0);
1682
	XRenderSetPictureFilter (xdisplay, dst, filter, p, 3);
1683
	XRenderComposite (xdisplay,
1684
			  PictOpSrc,
1685
			  dst,
1686
			  None,
1687
			  tmp,
1688
			  0, 0,
1689
			  0, 0,
1690
			  0, 0,
1691
			  d_width, d_height);
1692
1693
	XFreePixmap (xdisplay, d_pixmap);
1694
	shadow->pixmap = pixmap;
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
1695
    }
646 by David Reveman
Move more code into libdecoration.
1696
    else
1697
    {
1698
	XFreePixmap (xdisplay, pixmap);
1699
	shadow->pixmap = d_pixmap;
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
1700
    }
646 by David Reveman
Move more code into libdecoration.
1701
1702
    XRenderFreePicture (xdisplay, tmp);
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
1703
    XRenderFreePicture (xdisplay, dst);
1704
1705
    shadow->picture = XRenderCreatePicture (xdisplay, shadow->pixmap,
1706
					    format, 0, NULL);
1707
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
1708
    shadow->width  = d_width;
646 by David Reveman
Move more code into libdecoration.
1709
    shadow->height = d_height;
1710
1711
    free (params);
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
1712
1713
    return shadow;
639 by David Reveman
Move drop-shadow code from gtk-window-decorator to libdecoration.
1714
}
1715
1716
void
1717
decor_shadow_destroy (Display	     *xdisplay,
708 by David Reveman
Add reference counting and fixup function names.
1718
		      decor_shadow_t *shadow)
707 by David Reveman
Move decor_destroy_shadow.
1719
{
1720
    shadow->ref_count--;
708 by David Reveman
Add reference counting and fixup function names.
1721
    if (shadow->ref_count)
1722
	return;
1723
1724
    if (shadow->picture)
707 by David Reveman
Move decor_destroy_shadow.
1725
	XRenderFreePicture (xdisplay, shadow->picture);
1726
1727
    if (shadow->pixmap)
1728
	XFreePixmap (xdisplay, shadow->pixmap);
1729
1730
    free (shadow);
1731
}
1732
1733
void
1734
decor_shadow_reference (decor_shadow_t *shadow)
708 by David Reveman
Add reference counting and fixup function names.
1735
{
1736
    shadow->ref_count++;
1737
}
1738
1739
void
1740
decor_draw_simple (Display	   *xdisplay,
672 by David Reveman
Move draw_simple_shape function into libdecoration.
1741
		   Pixmap	   pixmap,
1742
		   Picture	   picture,
1743
		   int		   width,
1744
		   int		   height,
1745
		   decor_context_t *c,
1746
		   void		   *closure)
1747
{
1748
    static XRenderColor clear = { 0x0000, 0x0000, 0x0000, 0x0000 };
1749
    static XRenderColor white = { 0xffff, 0xffff, 0xffff, 0xffff };
1750
1751
    XRenderFillRectangle (xdisplay, PictOpSrc, picture, &clear,
1752
			  0,
1753
			  0,
1754
			  width,
1755
			  height);
1756
    XRenderFillRectangle (xdisplay, PictOpSrc, picture, &white,
1757
			  c->left_space - c->extents.left,
1758
			  c->top_space - c->extents.top,
1759
			  width - c->left_space - c->right_space +
1760
			  c->extents.left + c->extents.right,
1761
			  height - c->top_space - c->bottom_space +
1762
			  c->extents.top + c->extents.bottom);
1763
}
1764
1765
void
1766
decor_get_default_layout (decor_context_t *c,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
1767
			  int	          width,
1768
			  int	          height,
1769
			  decor_layout_t  *layout)
1770
{
1771
    width  = MAX (width, c->left_corner_space + c->right_corner_space);
1772
    height = MAX (height, c->top_corner_space + c->bottom_corner_space);
1773
1774
    width += c->left_space + c->right_space;
1775
1776
    layout->top.x1  = 0;
1777
    layout->top.y1  = 0;
1778
    layout->top.x2  = width;
1779
    layout->top.y2  = c->top_space;
1780
    layout->top.pad = 0;
1781
1782
    layout->left.x1  = 0;
1783
    layout->left.y1  = c->top_space;
1784
    layout->left.x2  = c->left_space;
1785
    layout->left.y2  = c->top_space + height;
1786
    layout->left.pad = 0;
1787
1788
    layout->right.x1  = width - c->right_space;
1789
    layout->right.y1  = c->top_space;
1790
    layout->right.x2  = width;
1791
    layout->right.y2  = c->top_space + height;
1792
    layout->right.pad = 0;
1793
1794
    layout->bottom.x1  = 0;
1795
    layout->bottom.y1  = height + c->top_space;
1796
    layout->bottom.x2  = width;
1797
    layout->bottom.y2  = height + c->top_space + c->bottom_space;
1798
    layout->bottom.pad = 0;
1799
1800
    layout->width  = width;
1801
    layout->height = height + c->top_space + c->bottom_space;
1802
1803
    layout->rotation = 0;
1804
}
1805
1806
void
1807
decor_get_best_layout (decor_context_t *c,
1808
		       int	       width,
1809
		       int	       height,
1810
		       decor_layout_t  *layout)
1811
{
1812
    int y;
1813
1814
    /* use default layout when no left and right extents */
1815
    if (c->extents.left == 0 && c->extents.right == 0)
1816
    {
1817
	decor_get_default_layout (c, width, 1, layout);
1818
	return;
1819
    }
1820
1821
    width  = MAX (width, c->left_corner_space + c->right_corner_space);
1822
    height = MAX (height, c->top_corner_space + c->bottom_corner_space);
1823
1824
    width += c->left_space + c->right_space;
1825
1826
    if (width >= (height + 2))
1827
    {
1828
	int max;
1829
1830
	layout->width = width;
1831
1832
	layout->top.x1 = 0;
1833
	layout->top.y1 = 0;
1834
	layout->top.x2 = width;
1835
	layout->top.y2 = c->top_space;
1836
1837
	y = c->top_space;
1838
1839
	max = MAX (c->left_space, c->right_space);
1840
	if (max < height)
1841
	{
1842
	    layout->rotation = 1;
1843
1844
	    y += 2;
1845
1846
	    layout->top.pad    = PAD_BOTTOM;
1847
	    layout->bottom.pad = PAD_TOP;
1848
	    layout->left.pad   = PAD_TOP | PAD_BOTTOM | PAD_LEFT | PAD_RIGHT;
1849
	    layout->right.pad  = PAD_TOP | PAD_BOTTOM | PAD_LEFT | PAD_RIGHT;
1850
1851
	    layout->left.x1 = 1;
1852
	    layout->left.y1 = y;
1853
	    layout->left.x2 = 1 + height;
1854
	    layout->left.y2 = y + c->left_space;
1855
1856
	    if ((height + 2) <= (width / 2))
1857
	    {
1858
		layout->right.x1 = height + 3;
1859
		layout->right.y1 = y;
1860
		layout->right.x2 = height + 3 + height;
1861
		layout->right.y2 = y + c->right_space;
1862
1863
		y += max + 2;
1864
	    }
1865
	    else
1866
	    {
1867
		y += c->left_space + 2;
1868
1869
		layout->right.x1 = 1;
1870
		layout->right.y1 = y;
1871
		layout->right.x2 = 1 + height;
1872
		layout->right.y2 = y + c->right_space;
1873
1874
		y += c->right_space + 2;
1875
	    }
1876
	}
1877
	else
1878
	{
1879
	    layout->rotation = 0;
2733.1.6 by Sam Spilsbury
Update API to allow multiple frames in one property (frame caching,
1880
1881
	    layout->top.pad    = 0;
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
1882
	    layout->bottom.pad = 0;
1883
	    layout->left.pad   = 0;
1884
	    layout->right.pad  = 0;
1885
1886
	    layout->left.x1 = 0;
1887
	    layout->left.y1 = y;
1888
	    layout->left.x2 = c->left_space;
1889
	    layout->left.y2 = y + height;
1890
1891
	    layout->right.x1 = width - c->right_space;
1892
	    layout->right.y1 = y;
1893
	    layout->right.x2 = width;
1894
	    layout->right.y2 = y + height;
1895
1896
	    y += height;
1897
	}
1898
1899
	layout->bottom.x1 = 0;
1900
	layout->bottom.y1 = y;
1901
	layout->bottom.x2 = width;
1902
	layout->bottom.y2 = y + c->bottom_space;
1903
1904
	y += c->bottom_space;
1905
    }
1906
    else
1907
    {
1908
	layout->rotation = 1;
1909
1910
	layout->left.pad   = PAD_TOP | PAD_BOTTOM | PAD_LEFT | PAD_RIGHT;
1911
	layout->right.pad  = PAD_TOP | PAD_BOTTOM | PAD_LEFT | PAD_RIGHT;
1912
1913
	layout->top.x1 = 0;
1914
	layout->top.y1 = 0;
1915
	layout->top.x2 = width;
1916
	layout->top.y2 = c->top_space;
1917
1918
	if (((width * 2) + 3) <= (height + 2))
1919
	{
1920
	    layout->width = height + 2;
1921
1922
	    layout->top.pad    = PAD_BOTTOM | PAD_RIGHT;
1923
	    layout->bottom.pad = PAD_TOP | PAD_BOTTOM | PAD_RIGHT | PAD_LEFT;
1924
1925
	    layout->bottom.x1 = width + 2;
1926
	    layout->bottom.y1 = 1;
1927
	    layout->bottom.x2 = width + 2 + width;
1928
	    layout->bottom.y2 = 1 + c->bottom_space;
1929
1930
	    y = MAX (c->top_space, 1 + c->bottom_space) + 2;
1931
1932
	    layout->left.x1 = 1;
1933
	    layout->left.y1 = y;
1934
	    layout->left.x2 = 1 + height;
1935
	    layout->left.y2 = y + c->left_space;
1936
1937
	    y += c->left_space + 2;
1938
1939
	    layout->right.x1 = 1;
1940
	    layout->right.y1 = y;
1941
	    layout->right.x2 = 1 + height;
1942
	    layout->right.y2 = y + c->right_space;
1943
1944
	    y += c->right_space;
1945
	}
1946
	else
1947
	{
1948
	    layout->width = height + 2;
1949
1950
	    layout->top.pad    = PAD_BOTTOM | PAD_RIGHT;
1951
	    layout->bottom.pad = PAD_TOP | PAD_RIGHT;
1952
1953
	    y = c->top_space + 2;
1954
1955
	    layout->left.x1 = 1;
1956
	    layout->left.y1 = y;
1957
	    layout->left.x2 = 1 + height;
1958
	    layout->left.y2 = y + c->left_space;
1959
1960
	    y += c->left_space + 2;
1961
1962
	    layout->right.x1 = 1;
1963
	    layout->right.y1 = y;
1964
	    layout->right.x2 = 1 + height;
1965
	    layout->right.y2 = y + c->right_space;
1966
1967
	    y += c->right_space + 2;
1968
1969
	    layout->bottom.x1 = 0;
1970
	    layout->bottom.y1 = y;
1971
	    layout->bottom.x2 = width;
1972
	    layout->bottom.y2 = y + c->bottom_space;
1973
1974
	    y += c->bottom_space;
1975
	}
1976
    }
1977
1978
    layout->height = y;
1979
}
1980
1981
static XTransform xident = {
1982
    {
1983
	{ 1 << 16, 0,             0 },
1984
	{ 0,       1 << 16,       0 },
1985
	{ 0,       0,       1 << 16 },
1986
    }
1987
};
1988
1989
void
1990
decor_fill_picture_extents_with_shadow (Display	        *xdisplay,
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
1991
					decor_shadow_t  *shadow,
1992
					decor_context_t *context,
1993
					Picture	        picture,
1994
					decor_layout_t  *layout)
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
1995
{
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
1996
    int w, h, left, right, top, bottom, width, height;
1289 by Roland Baer
Removed unused code
1997
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
1998
    if (!shadow->picture)
705 by David Reveman
Return early if there's no shadow picture.
1999
	return;
2000
2001
    width = layout->top.x2 - layout->top.x1;
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2002
    if (layout->rotation)
2003
	height = layout->left.x2 - layout->left.x1;
2004
    else
2005
	height = layout->left.y2 - layout->left.y1;
2006
2007
    height += context->top_space + context->bottom_space;
2008
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
2009
    left   = context->left_space   + context->left_corner_space;
2010
    right  = context->right_space  + context->right_corner_space;
2011
    top    = context->top_space    + context->top_corner_space;
2012
    bottom = context->bottom_space + context->bottom_corner_space;
2013
2014
    if (width - left - right < 0)
2015
    {
2016
	left = width / 2;
2017
	right = width - left;
2018
    }
2019
2020
    if (height - top - bottom < 0)
2021
    {
2022
	top = height / 2;
2023
	bottom = height - top;
2024
    }
2025
2026
    w = width - left - right;
2027
    h = height - top - bottom;
2028
2029
    /* top left */
2030
    XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2031
		      0, 0,
2032
		      0, 0,
2033
		      layout->top.x1, layout->top.y1,
2034
		      left, context->top_space);
2035
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
2036
    /* top right */
2037
    XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2038
		      shadow->width - right, 0,
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
2039
		      0, 0,
2040
		      layout->top.x2 - right, layout->top.y1,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2041
		      right, context->top_space);
2042
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
2043
    /* bottom left */
2044
    XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2045
		      0, shadow->height - context->bottom_space,
2046
		      0, 0,
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
2047
		      layout->bottom.x1, layout->bottom.y1,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2048
		      left, context->bottom_space);
2049
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
2050
    /* bottom right */
2051
    XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2052
		      shadow->width - right,
2053
		      shadow->height - context->bottom_space,
2054
		      0, 0,
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
2055
		      layout->bottom.x2 - right, layout->bottom.y1,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2056
		      right, context->bottom_space);
2057
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
2058
    if (w > 0)
2059
    {
2060
	int sw = shadow->width - left - right;
2061
	int sx = left;
2062
2063
	if (sw != w)
2064
	{
2065
	    XTransform t = {
2066
		{
2067
		    { (sw << 16) / w,       0, left << 16 },
2068
		    {              0, 1 << 16,          0 },
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2069
		    {              0,       0,    1 << 16 },
2070
		}
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
2071
	    };
2072
2073
	    sx = 0;
2074
2075
	    XRenderSetPictureTransform (xdisplay, shadow->picture, &t);
2076
	}
2077
2078
	/* top */
2079
	XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2080
			  sx, 0,
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
2081
			  0, 0,
2082
			  layout->top.x1 + left, layout->top.y1,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2083
			  w, context->top_space);
2084
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
2085
	/* bottom */
2086
	XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2087
			  sx, shadow->height - context->bottom_space,
2088
			  0, 0,
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
2089
			  layout->bottom.x1 + left, layout->bottom.y1,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2090
			  w, context->bottom_space);
2091
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
2092
	if (sw != w)
2093
	    XRenderSetPictureTransform (xdisplay, shadow->picture, &xident);
2094
    }
2095
2096
    if (layout->rotation)
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2097
    {
2098
	XTransform t = {
2099
	    {
2100
		{       0, 1 << 16,       0 },
2101
		{ 1 << 16,       0,       0 },
2102
		{       0,       0, 1 << 16 }
2103
	    }
2104
	};
2105
2106
	t.matrix[1][2] = context->top_space << 16;
2107
2108
	XRenderSetPictureTransform (xdisplay, shadow->picture, &t);
2109
2110
	/* left top */
2111
	XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture,
2112
			  0, 0,
2113
			  0, 0,
2114
			  layout->left.x1,
2115
			  layout->left.y1,
2116
			  top - context->top_space, context->left_space);
2117
2118
	t.matrix[0][2] = (shadow->width - context->right_space) << 16;
2119
2120
	XRenderSetPictureTransform (xdisplay, shadow->picture, &t);
2121
2122
	/* right top */
2123
	XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture,
2124
			  0, 0,
2125
			  0, 0,
2126
			  layout->right.x1,
2127
			  layout->right.y1,
2128
			  top - context->top_space, context->right_space);
2129
2130
	XRenderSetPictureTransform (xdisplay, shadow->picture, &xident);
2131
    }
2132
    else
2133
    {
2134
	/* left top */
2135
	XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture,
2136
			  0, context->top_space,
2137
			  0, 0,
2138
			  layout->left.x1, layout->left.y1,
2139
			  context->left_space, top - context->top_space);
2140
2141
	/* right top */
2142
	XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture,
2143
			  shadow->width - context->right_space,
2144
			  context->top_space,
2145
			  0, 0,
2146
			  layout->right.x1, layout->right.y1,
2147
			  context->right_space, top - context->top_space);
2148
    }
2149
2150
    if (layout->rotation)
2151
    {
2152
	XTransform t = {
2153
	    {
2154
		{       0, 1 << 16,       0 },
2155
		{ 1 << 16,       0,       0 },
2156
		{       0,       0, 1 << 16 }
2157
	    }
2158
	};
2159
2160
	t.matrix[1][2] = (shadow->height - bottom) << 16;
2161
2162
	XRenderSetPictureTransform (xdisplay, shadow->picture, &t);
2163
2164
	/* left bottom */
2165
	XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture,
2166
			  0, 0,
2167
			  0, 0,
2168
			  layout->left.x2 - (bottom - context->bottom_space),
2169
			  layout->left.y1,
2170
			  bottom - context->bottom_space, context->left_space);
2171
2172
	t.matrix[0][2] = (shadow->width - context->right_space) << 16;
2173
2174
	XRenderSetPictureTransform (xdisplay, shadow->picture, &t);
2175
2176
	/* right bottom */
2177
	XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture,
2178
			  0, 0,
2179
			  0, 0,
2180
			  layout->right.x2 - (bottom - context->bottom_space),
2181
			  layout->right.y1,
2182
			  bottom - context->bottom_space, context->right_space);
2183
2184
	XRenderSetPictureTransform (xdisplay, shadow->picture, &xident);
2185
    }
2186
    else
2187
    {
2188
	/* left bottom */
2189
	XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture,
2190
			  0, shadow->height - bottom,
2191
			  0, 0,
2192
			  layout->left.x1,
2193
			  layout->left.y2 - (bottom - context->bottom_space),
2194
			  context->left_space, bottom - context->bottom_space);
2195
2196
	/* right bottom */
2197
	XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture,
2198
			  shadow->width - context->right_space,
2199
			  shadow->height - bottom,
2200
			  0, 0,
2201
			  layout->right.x1,
2202
			  layout->right.y2 - (bottom - context->bottom_space),
2203
			  context->right_space, bottom - context->bottom_space);
2204
    }
2205
2206
    if (h > 0)
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
2207
    {
2208
	int sh = shadow->height - top - bottom;
2209
2210
	if (layout->rotation)
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2211
	{
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
2212
	    XTransform t = {
2213
		{
2214
		    {              0, 1 << 16,       0 },
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2215
		    { (sh << 16) / h,       0,       0 },
2216
		    {              0,       0, 1 << 16 }
2217
		}
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
2218
	    };
2219
2220
	    t.matrix[1][2] = top << 16;
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2221
2222
	    XRenderSetPictureTransform (xdisplay, shadow->picture, &t);
2223
2224
	    /* left */
2225
	    XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture,
2226
			      0, 0,
2227
			      0, 0,
2228
			      layout->left.x1 + (top - context->top_space),
2229
			      layout->left.y1,
2230
			      h, context->left_space);
2231
2232
	    t.matrix[0][2] = (shadow->width - context->right_space) << 16;
2233
2234
	    XRenderSetPictureTransform (xdisplay, shadow->picture, &t);
2235
2236
	    /* right */
2237
	    XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture,
2238
			      0, 0,
2239
			      0, 0,
2240
			      layout->right.x1 + (top - context->top_space),
2241
			      layout->right.y1,
2242
			      h, context->right_space);
2243
2244
	    XRenderSetPictureTransform (xdisplay, shadow->picture, &xident);
649 by David Reveman
Rewrite and move a lot more code into libdecoration.
2245
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2246
	}
2247
	else
2248
	{
2249
	    int sy = top;
2250
2251
	    if (sh != h)
2252
	    {
2253
		XTransform t = {
2254
		    {
2255
			{ 1 << 16,              0,         0 },
2256
			{       0, (sh << 16) / h, top << 16 },
2257
			{       0,              0,   1 << 16 },
2258
		    }
2259
		};
2260
2261
		sy = 0;
2262
2263
		XRenderSetPictureTransform (xdisplay, shadow->picture, &t);
2264
	    }
2265
2266
	    /* left */
2267
	    XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture,
2268
			      0, sy,
2269
			      0, 0,
2270
			      layout->left.x1,
2271
			      layout->left.y1 + (top - context->top_space),
2272
			      context->left_space, h);
2273
2274
	    /* right */
2275
	    XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture,
2276
			      shadow->width - context->right_space, sy,
712 by David Reveman
Fix typo that caused shadow of right window border to sometimes be rendered
2277
			      0, 0,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2278
			      layout->right.x2 - context->right_space,
2279
			      layout->right.y1 + (top - context->top_space),
2280
			      context->right_space, h);
2281
2282
	    if (sh != h)
2283
		XRenderSetPictureTransform (xdisplay, shadow->picture, &xident);
2284
	}
2285
    }
2286
}
2287
2288
static void
2289
_decor_pad_border_picture (Display     *xdisplay,
2290
			   Picture     dst,
2291
			   decor_box_t *box)
2292
{
2293
    int x1, y1, x2, y2;
2294
2295
    x1 = box->x1;
2296
    y1 = box->y1;
2297
    x2 = box->x2;
2298
    y2 = box->y2;
2299
2300
    if (box->pad & PAD_TOP)
2301
    {
2302
	XRenderComposite (xdisplay, PictOpSrc, dst, None, dst,
2303
			  x1, y1,
2304
			  0, 0,
2305
			  x1, y1 - 1,
2306
			  x2 - x1, 1);
2307
2308
	y1--;
2309
    }
2310
2311
    if (box->pad & PAD_BOTTOM)
2312
    {
2313
	XRenderComposite (xdisplay, PictOpSrc, dst, None, dst,
2314
			  x1, y2 - 1,
2315
			  0, 0,
2316
			  x1, y2,
2317
			  x2 - x1, 1);
2318
2319
	y2++;
2320
    }
2321
2322
    if (box->pad & PAD_LEFT)
2323
    {
2324
	XRenderComposite (xdisplay, PictOpSrc, dst, None, dst,
2325
			  x1, y1,
2326
			  0, 0,
2327
			  x1 - 1, y1,
2328
			  1, y2 - y1);
2329
    }
2330
2331
    if (box->pad & PAD_RIGHT)
2332
    {
2333
	XRenderComposite (xdisplay, PictOpSrc, dst, None, dst,
2334
			  x2 - 1, y1,
2335
			  0, 0,
2336
			  x2, y1,
2337
			  1, y2 - y1);
2338
    }
2339
}
2340
2341
#ifndef HAVE_XRENDER_0_9_3
800 by David Reveman
Check version of libXrender and workaround gradient issue if older
2342
/* XRenderCreateLinearGradient and XRenderCreateRadialGradient used to be
2343
 * broken. Flushing Xlib's output buffer before calling one of these
2344
 * functions will avoid this specific issue.
2345
 */
2346
static Picture
2347
XRenderCreateLinearGradient_wrapper (Display		   *xdisplay,
2348
				     const XLinearGradient *gradient,
2349
				     const XFixed	   *stops,
2350
				     const XRenderColor	   *colors,
2351
				     int		   nStops)
2352
{
2353
    XFlush (xdisplay);
2354
2355
    return XRenderCreateLinearGradient (xdisplay, gradient,
2356
					stops, colors, nStops);
2357
}
2358
2359
static Picture
2360
XRenderCreateRadialGradient_wrapper (Display		   *xdisplay,
2361
				     const XRadialGradient *gradient,
2362
				     const XFixed	   *stops,
2363
				     const XRenderColor	   *colors,
2364
				     int		   nStops)
2365
{
2366
    XFlush (xdisplay);
2367
2368
    return XRenderCreateRadialGradient (xdisplay, gradient,
2369
					stops, colors, nStops);
2370
}
2371
2372
#define XRenderCreateLinearGradient XRenderCreateLinearGradient_wrapper
2373
#define XRenderCreateRadialGradient XRenderCreateRadialGradient_wrapper
2374
#endif
2375
2376
static void
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2377
_decor_blend_horz_border_picture (Display	  *xdisplay,
2378
				  decor_context_t *context,
2379
				  Picture	  src,
2380
				  int	          xSrc,
2381
				  int	          ySrc,
2382
				  Picture	  dst,
2383
				  decor_layout_t  *layout,
2384
				  Region	  region,
2385
				  unsigned short  alpha,
2386
				  int	          shade_alpha,
2387
				  int		  x1,
2388
				  int		  y1,
2389
				  int		  x2,
2390
				  int		  y2,
2391
				  int		  dy,
2392
				  int		  direction,
1932 by Dennis Kasprzyk
Merged decor_blend_(top|bottom|left|right)_border_picture function into one common function.
2393
				  int             ignore_src_alpha)
2394
{
651 by David Reveman
Rewrote decoration opacity code and moved it to libdecoration.
2395
    XRenderColor color[3] = {
2396
	{ 0xffff, 0xffff, 0xffff, 0xffff },
2397
	{  alpha,  alpha,  alpha,  alpha },
1932 by Dennis Kasprzyk
Merged decor_blend_(top|bottom|left|right)_border_picture function into one common function.
2398
	{    0x0,    0x0,    0x0, 0xffff }
2399
    };
651 by David Reveman
Rewrote decoration opacity code and moved it to libdecoration.
2400
    int		 op = PictOpSrc, gop = PictOpSrc;
1932 by Dennis Kasprzyk
Merged decor_blend_(top|bottom|left|right)_border_picture function into one common function.
2401
    int		 left, right;
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2402
2403
    left   = context->extents.left;
2404
    right  = context->extents.right;
2405
2406
    XOffsetRegion (region, x1, y1);
2407
    XRenderSetPictureClipRegion (xdisplay, dst, region);
651 by David Reveman
Rewrote decoration opacity code and moved it to libdecoration.
2408
    XOffsetRegion (region, -x1, -y1);
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2409
2410
    if (ignore_src_alpha)
1932 by Dennis Kasprzyk
Merged decor_blend_(top|bottom|left|right)_border_picture function into one common function.
2411
    {
2412
	XRenderComposite (xdisplay, PictOpSrc, src, None, dst,
2413
			  xSrc, ySrc,
2414
			  0, 0,
2415
			  x1, y1,
2416
			  x2 - x1, y2 - y1);
2417
	XRenderFillRectangle (xdisplay, PictOpAdd, dst, &color[2], x1, y1,
2418
			      x2 - x1, y2 - y1);
2419
	gop = PictOpInReverse;
2420
    }
2421
2422
    if (alpha != 0xffff)
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2423
    {
2424
	op = PictOpIn;
2425
2426
	if (shade_alpha)
2427
	{
2428
	    static XFixed	     stop[2] = { 0, 1 << 16 };
2429
	    XTransform		     transform = {
2430
		{
2431
		    { 1 << 16,       0,       0 },
2432
		    {       0, 1 << 16,       0 },
2433
		    {       0,       0, 1 << 16 }
2434
		}
2435
	    };
2436
	    Picture		     grad;
2437
	    XLinearGradient	     linear;
2438
	    XRadialGradient	     radial;
2439
	    XRenderPictureAttributes attrib;
2440
2441
	    attrib.repeat = RepeatPad;
2442
2443
	    radial.inner.x	= 0;
2444
	    radial.inner.y	= 0;
2445
	    radial.inner.radius = 0;
2446
	    radial.outer.x	= 0;
2447
	    radial.outer.y	= 0;
2448
2449
	    /* left */
2450
	    radial.outer.radius = left << 16;
2451
2452
	    grad = XRenderCreateRadialGradient (xdisplay,
2453
						&radial,
2454
						stop,
2455
						color,
2456
						2);
2457
2458
	    transform.matrix[1][1] = (left << 16) / dy;
2459
	    transform.matrix[0][2] = -left << 16;
2460
2461
	    if (direction < 0)
2462
		transform.matrix[1][2] = -left << 16;
2463
2464
	    XRenderSetPictureTransform (xdisplay, grad, &transform);
2465
	    XRenderChangePicture (xdisplay, grad, CPRepeat, &attrib);
2466
2467
	    XRenderComposite (xdisplay, gop, grad, None, dst,
1932 by Dennis Kasprzyk
Merged decor_blend_(top|bottom|left|right)_border_picture function into one common function.
2468
			      0, 0,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2469
			      0, 0,
2470
			      x1, y1,
2471
			      left, dy);
2472
2473
	    XRenderFreePicture (xdisplay, grad);
2474
2475
	    /* middle */
2476
	    linear.p1.x = 0;
2477
	    linear.p2.x = 0;
2478
2479
	    if (direction > 0)
2480
	    {
2481
		linear.p1.y = 0;
2482
		linear.p2.y = dy << 16;
2483
	    }
2484
	    else
2485
	    {
2486
		linear.p1.y = dy << 16;
2487
		linear.p2.y = 0;
2488
	    }
2489
2490
	    grad = XRenderCreateLinearGradient (xdisplay,
2491
						&linear,
2492
						stop,
2493
						color,
2494
						2);
2495
2496
	    XRenderChangePicture (xdisplay, grad, CPRepeat, &attrib);
2497
2498
	    XRenderComposite (xdisplay, gop, grad, None, dst,
1932 by Dennis Kasprzyk
Merged decor_blend_(top|bottom|left|right)_border_picture function into one common function.
2499
			      0, 0,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2500
			      0, 0,
2501
			      x1 + left, y1,
2502
			      (x2 - x1) - left - right, dy);
2503
2504
	    XRenderFreePicture (xdisplay, grad);
2505
2506
	    /* right */
2507
	    radial.outer.radius = right << 16;
2508
2509
	    grad = XRenderCreateRadialGradient (xdisplay,
2510
						&radial,
2511
						stop,
2512
						color,
2513
						2);
2514
2515
	    transform.matrix[1][1] = (right << 16) / dy;
2516
	    transform.matrix[0][2] = 1 << 16;
2517
2518
	    if (direction < 0)
2519
		transform.matrix[1][2] = -right << 16;
2520
2521
	    XRenderSetPictureTransform (xdisplay, grad, &transform);
2522
	    XRenderChangePicture (xdisplay, grad, CPRepeat, &attrib);
2523
2524
	    XRenderComposite (xdisplay, gop, grad, None, dst,
1932 by Dennis Kasprzyk
Merged decor_blend_(top|bottom|left|right)_border_picture function into one common function.
2525
			      0, 0,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2526
			      0, 0,
2527
			      x2 - right, y1,
2528
			      right, dy);
2529
2530
	    XRenderFreePicture (xdisplay, grad);
2531
	}
2532
	else
2533
	{
2534
	    XRenderFillRectangle (xdisplay, gop, dst, &color[1],
1932 by Dennis Kasprzyk
Merged decor_blend_(top|bottom|left|right)_border_picture function into one common function.
2535
				  x1, y1, x2 - x1, y2 - y1);
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2536
	}
2537
    }
2538
2539
    if (!ignore_src_alpha)
1932 by Dennis Kasprzyk
Merged decor_blend_(top|bottom|left|right)_border_picture function into one common function.
2540
	XRenderComposite (xdisplay, op, src, None, dst,
2541
			  xSrc, ySrc,
2542
			  0, 0,
2543
			  x1, y1,
2544
			  x2 - x1, y2 - y1);
2545
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2546
    set_no_picture_clip (xdisplay, dst);
2547
}
2548
2549
static void
2550
_decor_blend_vert_border_picture (Display	  *xdisplay,
2551
				  decor_context_t *context,
2552
				  Picture	  src,
2553
				  int	          xSrc,
2554
				  int	          ySrc,
2555
				  Picture	  dst,
2556
				  decor_layout_t  *layout,
2557
				  Region	  region,
2558
				  unsigned short  alpha,
2559
				  int	          shade_alpha,
2560
				  int		  x1,
2561
				  int		  y1,
2562
				  int		  x2,
2563
				  int		  y2,
2564
				  int		  direction,
1932 by Dennis Kasprzyk
Merged decor_blend_(top|bottom|left|right)_border_picture function into one common function.
2565
				  int             ignore_src_alpha)
2566
{
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2567
    XRenderColor color[3] = {
2568
	{ 0xffff, 0xffff, 0xffff, 0xffff },
2569
	{  alpha,  alpha,  alpha,  alpha },
1932 by Dennis Kasprzyk
Merged decor_blend_(top|bottom|left|right)_border_picture function into one common function.
2570
	{    0x0,    0x0,    0x0, 0xffff }
2571
    };
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2572
    int		 op = PictOpSrc, gop = PictOpSrc;
1932 by Dennis Kasprzyk
Merged decor_blend_(top|bottom|left|right)_border_picture function into one common function.
2573
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2574
    if (layout->rotation)
2575
    {
2576
	Region     rotated_region;
2577
	XRectangle rect;
2578
	BoxPtr     pBox = region->rects;
2579
	int	   nBox = region->numRects;
2580
2581
	rotated_region = XCreateRegion ();
2582
2583
	while (nBox--)
2584
	{
2585
	    rect.x      = x1 + pBox->y1;
2586
	    rect.y	= y1 + pBox->x1;
2587
	    rect.width  = pBox->y2 - pBox->y1;
2588
	    rect.height = pBox->x2 - pBox->x1;
2589
2590
	    XUnionRectWithRegion (&rect, rotated_region, rotated_region);
2591
2592
	    pBox++;
2593
	}
2594
2595
	XRenderSetPictureClipRegion (xdisplay, dst, rotated_region);
2596
	XDestroyRegion (rotated_region);
2597
    }
2598
    else
2599
    {
2600
	XOffsetRegion (region, x1, y1);
2601
	XRenderSetPictureClipRegion (xdisplay, dst, region);
2602
	XOffsetRegion (region, -x1, -y1);
2603
    }
2604
2605
    if (ignore_src_alpha)
1932 by Dennis Kasprzyk
Merged decor_blend_(top|bottom|left|right)_border_picture function into one common function.
2606
    {
2607
	if (layout->rotation)
2608
	{
2609
	    XTransform t = {
2610
		{
2611
		    {       0, 1 << 16,       0 },
2612
		    { 1 << 16,       0,       0 },
2613
		    {       0,       0, 1 << 16 }
2614
		}
2615
	    };
2616
2617
	    t.matrix[0][2] = xSrc << 16;
2618
	    t.matrix[1][2] = ySrc << 16;
2619
2620
	    XRenderSetPictureTransform (xdisplay, src, &t);
2621
2622
	    XRenderComposite (xdisplay, PictOpSrc, src, None, dst,
2623
			      0, 0,
2624
			      0, 0,
2625
			      x1, y1, x2 - x1, y2 - y1);
2626
	    XRenderFillRectangle (xdisplay, PictOpAdd, dst, &color[2], x1, y1,
2627
			          x2 - x1, y2 - y1);
2628
2629
	    XRenderSetPictureTransform (xdisplay, src, &xident);
2630
	}
2631
	else
2632
	{
2633
	    XRenderComposite (xdisplay, PictOpSrc, src, None, dst,
2634
			      xSrc, ySrc,
2635
			      0, 0,
2636
			      x1, y1, x2 - x1, y2 - y1);
2637
	    XRenderFillRectangle (xdisplay, PictOpAdd, dst, &color[2], x1, y1,
2638
			      x2 - x1, y2 - y1);
2639
	}
2640
	gop = PictOpInReverse;
2641
    }
2642
2308 by Danny Baumann
Whitespace fixes.
2643
    if (alpha != 0xffff)
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2644
    {
2645
	op = PictOpIn;
2646
2647
	if (shade_alpha)
2648
	{
2649
	    static XFixed	     stop[2] = { 0, 1 << 16 };
2650
	    Picture		     grad;
2651
	    XLinearGradient	     linear;
2652
	    XRenderPictureAttributes attrib;
2653
2654
	    attrib.repeat = RepeatPad;
2655
2656
	    if (layout->rotation)
2657
	    {
2658
		linear.p1.x = 0;
2659
		linear.p2.x = 0;
2660
2661
		if (direction < 0)
2662
		{
2663
		    linear.p1.y = 0;
2664
		    linear.p2.y = (y2 - y1) << 16;
2665
		}
2666
		else
2667
		{
2668
		    linear.p1.y = (y2 - y1) << 16;
2669
		    linear.p2.y = 0 << 16;
2670
		}
2671
	    }
2672
	    else
2673
	    {
2674
		linear.p1.y = 0;
2675
		linear.p2.y = 0;
2676
2677
		if (direction < 0)
2678
		{
2679
		    linear.p1.x = 0;
2680
		    linear.p2.x = (x2 - x1) << 16;
2681
		}
2682
		else
2683
		{
2684
		    linear.p1.x = (x2 - x1) << 16;
2685
		    linear.p2.x = 0;
2686
		}
2687
	    }
2688
2689
	    grad = XRenderCreateLinearGradient (xdisplay,
2690
						&linear,
2691
						stop,
2692
						color,
2693
						2);
2694
2695
	    XRenderChangePicture (xdisplay, grad, CPRepeat, &attrib);
2696
2697
	    XRenderComposite (xdisplay, gop, grad, None, dst,
1932 by Dennis Kasprzyk
Merged decor_blend_(top|bottom|left|right)_border_picture function into one common function.
2698
			      0, 0,
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2699
			      0, 0,
2700
			      x1, y1,
2701
			      x2 - x1, y2 - y1);
2702
2703
	    XRenderFreePicture (xdisplay, grad);
2704
	}
2705
	else
2706
	{
2707
	    XRenderFillRectangle (xdisplay, gop, dst, &color[1],
1932 by Dennis Kasprzyk
Merged decor_blend_(top|bottom|left|right)_border_picture function into one common function.
2708
				  x1, y1, x2 - x1, y2 - y1);
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2709
	}
2710
    }
2711
2712
    if (!ignore_src_alpha)
1932 by Dennis Kasprzyk
Merged decor_blend_(top|bottom|left|right)_border_picture function into one common function.
2713
    {
2714
	if (layout->rotation)
2715
	{
2716
	    XTransform t = {
2717
		{
2718
		    {       0, 1 << 16,       0 },
2719
		    { 1 << 16,       0,       0 },
2720
		    {       0,       0, 1 << 16 }
2721
		}
2722
	    };
2723
2724
	    t.matrix[0][2] = xSrc << 16;
2725
	    t.matrix[1][2] = ySrc << 16;
2726
2727
	    XRenderSetPictureTransform (xdisplay, src, &t);
2728
2729
	    XRenderComposite (xdisplay, op, src, None, dst,
2730
			    0, 0,
2731
			    0, 0,
2732
			    x1, y1, x2 - x1, y2 - y1);
2733
2734
	    XRenderSetPictureTransform (xdisplay, src, &xident);
2735
	}
2736
	else
2737
	{
2738
	    XRenderComposite (xdisplay, op, src, None, dst,
2739
			    xSrc, ySrc,
2740
			    0, 0,
2741
			    x1, y1, x2 - x1, y2 - y1);
2742
	}
2743
    }
653 by David Reveman
Finish libdecoration implementation and move gtk-window-decorator over to
2744
2745
    set_no_picture_clip (xdisplay, dst);
2746
}
2747
2748
void
2749
decor_blend_border_picture (Display	    *xdisplay,
1932 by Dennis Kasprzyk
Merged decor_blend_(top|bottom|left|right)_border_picture function into one common function.
2750
			    decor_context_t *context,
2751
			    Picture	    src,
2752
			    int	            xSrc,
2753
			    int	            ySrc,
2754
			    Picture	    dst,
2755
			    decor_layout_t  *layout,
2756
			    unsigned int    border,
2757
			    Region	    region,
2758
			    unsigned short  alpha,
2759
			    int	            shade_alpha,
2760
			    int             ignore_src_alpha)
2761
{
2762
    int left, right, bottom, top;
2763
    int x1, y1, x2, y2;
2764
2765
    left   = context->extents.left;
2766
    right  = context->extents.right;
2767
    top    = context->extents.top;
2768
    bottom = context->extents.bottom;
2769
2770
    switch (border)
2771
    {
2772
    case BORDER_TOP:
2773
	x1 = layout->top.x1 + context->left_space - left;
2774
	y1 = layout->top.y1 + context->top_space - top;
2775
	x2 = layout->top.x2 - context->right_space + right;
2776
	y2 = layout->top.y2;
2777
2778
	_decor_blend_horz_border_picture (xdisplay,
2779
					context,
2780
					src,
2781
					xSrc,
2782
					ySrc,
2783
					dst,
2784
					layout,
2785
					region,
2786
					alpha,
2787
					shade_alpha,
2788
					x1,
2789
					y1,
2790
					x2,
2791
					y2,
2792
					top,
2793
					-1,
2794
					ignore_src_alpha);
2795
2796
	_decor_pad_border_picture (xdisplay, dst, &layout->top);
2797
	break;
2798
    case BORDER_BOTTOM:
2799
	x1 = layout->bottom.x1 + context->left_space - left;
2800
	y1 = layout->bottom.y1;
2801
	x2 = layout->bottom.x2 - context->right_space + right;
2802
	y2 = layout->bottom.y1 + bottom;
2803
2804
	_decor_blend_horz_border_picture (xdisplay,
2805
					context,
2806
					src,
2807
					xSrc,
2808
					ySrc,
2809
					dst,
2810
					layout,
2811
					region,
2812
					alpha,
2813
					shade_alpha,
2814
					x1,
2815
					y1,
2816
					x2,
2817
					y2,
2818
					bottom,
2819
					1,
2820
					ignore_src_alpha);
2821
2822
	_decor_pad_border_picture (xdisplay, dst, &layout->bottom);
2823
	break;
2824
    case BORDER_LEFT:
2825
	x1 = layout->left.x1;
2826
	y1 = layout->left.y1;
2827
	x2 = layout->left.x2;
2828
	y2 = layout->left.y2;
2829
2830
	if (layout->rotation)
2831
	    y1 += context->left_space - context->extents.left;
2832
	else
2833
	    x1 += context->left_space - context->extents.left;
2834
2835
	_decor_blend_vert_border_picture (xdisplay,
2836
					context,
2837
					src,
2838
					xSrc,
2839
					ySrc,
2840
					dst,
2841
					layout,
2842
					region,
2843
					alpha,
2844
					shade_alpha,
2845
					x1,
2846
					y1,
2847
					x2,
2848
					y2,
2849
					1,
2850
					ignore_src_alpha);
2851
2852
	_decor_pad_border_picture (xdisplay, dst, &layout->left);
2853
	break;
2854
    case BORDER_RIGHT:
2855
	x1 = layout->right.x1;
2856
	y1 = layout->right.y1;
2857
	x2 = layout->right.x2;
2858
	y2 = layout->right.y2;
2859
2860
	if (layout->rotation)
2861
	    y2 -= context->right_space - context->extents.right;
2862
	else
2863
	    x2 -= context->right_space - context->extents.right;
2864
2865
	_decor_blend_vert_border_picture (xdisplay,
2866
					context,
2867
					src,
2868
					xSrc,
2869
					ySrc,
2870
					dst,
2871
					layout,
2872
					region,
2873
					alpha,
2874
					shade_alpha,
2875
					x1,
2876
					y1,
2877
					x2,
2878
					y2,
2879
					-1,
2880
					ignore_src_alpha);
2881
2882
	_decor_pad_border_picture (xdisplay, dst, &layout->right);
2883
	break;
2884
    default:
2885
	break;
2886
    }
2887
}
651 by David Reveman
Rewrote decoration opacity code and moved it to libdecoration.
2888
679 by David Reveman
Move DM selection code into libdecoration.
2889
int
2890
decor_post_pending (Display *xdisplay,
3132.2.1 by smspillaz
Unrevert r3131 and potentially fix LP#996901 in the process
2891
		    Window  client,
2892
		    unsigned int frame_type,
3602.2.21 by Sam Spilsbury
Rename postDeletePixmap to destroyUnusedPixmap and implement the glue code
2893
		    unsigned int frame_state,
3132.2.1 by smspillaz
Unrevert r3131 and potentially fix LP#996901 in the process
2894
		    unsigned int frame_actions)
2895
{
2896
    XEvent event;
2897
2898
    Atom   decor_pending  = XInternAtom (xdisplay, DECOR_PIXMAP_PENDING_ATOM_NAME, FALSE);
3602.2.14 by Sam Spilsbury
Put the strings behind common identifiers
2899
3132.2.1 by smspillaz
Unrevert r3131 and potentially fix LP#996901 in the process
2900
    /* Send a client message indicating that a new
2901
     * decoration can be generated for this window
2902
     */
2903
    event.xclient.type	       = ClientMessage;
2904
    event.xclient.window       = client;
2905
    event.xclient.message_type = decor_pending;
2906
    event.xclient.format       = 32;
2907
    event.xclient.data.l[0]    = frame_type;
2908
    event.xclient.data.l[1]    = frame_state;
2909
    event.xclient.data.l[2]    = frame_actions;
2910
    event.xclient.data.l[3]    = 0;
2911
    event.xclient.data.l[4]    = 0;
2912
2913
    XSendEvent (xdisplay, DefaultRootWindow (xdisplay), 0,
2914
		StructureNotifyMask, &event);
2915
2916
    return 1;
2917
}
2918
2919
int
2920
decor_post_generate_request (Display *xdisplay,
2921
			     Window  client,
2922
			     unsigned int frame_type,
2923
			     unsigned int frame_state,
2924
			     unsigned int frame_actions)
2925
{
2926
    XEvent event;
2927
2928
    Atom   decor_request  = XInternAtom (xdisplay, DECOR_REQUEST_PIXMAP_ATOM_NAME, FALSE);
3602.2.14 by Sam Spilsbury
Put the strings behind common identifiers
2929
3132.2.1 by smspillaz
Unrevert r3131 and potentially fix LP#996901 in the process
2930
    /* Send a client message indicating that a new
2931
     * decoration can be generated for this window
2932
     */
2933
    event.xclient.type	       = ClientMessage;
2934
    event.xclient.window       = client;
2935
    event.xclient.message_type = decor_request;
2936
    event.xclient.format       = 32;
2937
    event.xclient.data.l[0]    = frame_type;
2938
    event.xclient.data.l[1]    = frame_state;
2939
    event.xclient.data.l[2]    = frame_actions;
2940
    event.xclient.data.l[3]    = 0;
2941
    event.xclient.data.l[4]    = 0;
2942
2943
    XSendEvent (xdisplay, DefaultRootWindow (xdisplay), 0,
2944
		StructureNotifyMask, &event);
2945
2946
    return 1;
2947
}
2948
2949
int
2950
decor_post_delete_pixmap (Display *xdisplay,
2951
			  Window window,
3602.2.14 by Sam Spilsbury
Put the strings behind common identifiers
2952
			  Pixmap  pixmap)
3132.2.1 by smspillaz
Unrevert r3131 and potentially fix LP#996901 in the process
2953
{
2954
    XEvent event;
2955
2956
    Atom   decor_delete_pixmap  = XInternAtom (xdisplay, DECOR_DELETE_PIXMAP_ATOM_NAME, FALSE);
3602.2.14 by Sam Spilsbury
Put the strings behind common identifiers
2957
3132.2.1 by smspillaz
Unrevert r3131 and potentially fix LP#996901 in the process
2958
    /* Send a client message indicating that this
3602.2.14 by Sam Spilsbury
Put the strings behind common identifiers
2959
     * pixmap is no longer in use and can be removed
2960
     */
3132.2.1 by smspillaz
Unrevert r3131 and potentially fix LP#996901 in the process
2961
    event.xclient.type	       = ClientMessage;
2962
    event.xclient.window       = window;
3602.2.14 by Sam Spilsbury
Put the strings behind common identifiers
2963
    event.xclient.message_type = decor_delete_pixmap;
3132.2.1 by smspillaz
Unrevert r3131 and potentially fix LP#996901 in the process
2964
    event.xclient.format       = 32;
2965
    event.xclient.data.l[0]    = pixmap;
2966
    event.xclient.data.l[1]    = 0;
2967
    event.xclient.data.l[2]    = 0;
2968
    event.xclient.data.l[3]    = 0;
2969
    event.xclient.data.l[4]    = 0;
2970
2971
    XSendEvent (xdisplay, DefaultRootWindow (xdisplay), 0,
2972
		StructureNotifyMask, &event);
2973
2974
    return 1;
2975
}
2976
3602.2.14 by Sam Spilsbury
Put the strings behind common identifiers
2977
int
3132.2.1 by smspillaz
Unrevert r3131 and potentially fix LP#996901 in the process
2978
decor_acquire_dm_session (Display    *xdisplay,
1262 by David Reveman
Fix type of name argument.
2979
			  int	     screen,
2980
			  const char *name,
2981
			  int	     replace_current_dm,
2982
			  Time	     *timestamp)
2983
{
679 by David Reveman
Move DM selection code into libdecoration.
2984
    XEvent		 event;
2985
    XSetWindowAttributes attr;
2986
    Window		 current_dm_sn_owner, new_dm_sn_owner;
2987
    Atom		 dm_sn_atom;
2988
    Atom		 manager_atom;
2989
    Atom		 dm_name_atom;
2990
    Atom		 utf8_string_atom;
2991
    Time		 dm_sn_timestamp;
2992
    char		 buf[128];
2993
2994
    manager_atom = XInternAtom (xdisplay, "MANAGER", FALSE);
2995
    dm_name_atom = XInternAtom (xdisplay, "_COMPIZ_DM_NAME", 0);
1705 by Dennis Kasprzyk
Use _COMPIZ_ prefix for all non stadardized decoration manager atom names.
2996
679 by David Reveman
Move DM selection code into libdecoration.
2997
    utf8_string_atom = XInternAtom (xdisplay, "UTF8_STRING", 0);
2998
2999
    snprintf (buf, 128, "_COMPIZ_DM_S%d", screen);
3570.3.1 by MC Return
Followed a recommendation of Coverity and replaced sprintf () with snprintf () with a buffer size of 128, as the definition says char buf[128]
3000
    dm_sn_atom = XInternAtom (xdisplay, buf, 0);
679 by David Reveman
Move DM selection code into libdecoration.
3001
3002
    current_dm_sn_owner = XGetSelectionOwner (xdisplay, dm_sn_atom);
3003
3004
    if (current_dm_sn_owner != None)
3005
    {
3006
	if (!replace_current_dm)
3007
	    return DECOR_ACQUIRE_STATUS_OTHER_DM_RUNNING;
3008
3009
	XSelectInput (xdisplay, current_dm_sn_owner, StructureNotifyMask);
3010
    }
3011
3012
    attr.override_redirect = TRUE;
3013
    attr.event_mask	   = PropertyChangeMask;
3014
3015
    new_dm_sn_owner =
3016
	XCreateWindow (xdisplay, XRootWindow (xdisplay, screen),
3017
		       -100, -100, 1, 1, 0,
3018
		       CopyFromParent, CopyFromParent,
3019
		       CopyFromParent,
3020
		       CWOverrideRedirect | CWEventMask,
3021
		       &attr);
3022
3023
    XChangeProperty (xdisplay,
3024
		     new_dm_sn_owner,
3025
		     dm_name_atom,
3026
		     utf8_string_atom, 8,
3027
		     PropModeReplace,
3028
		     (unsigned char *) name,
3029
		     strlen (name));
3030
3031
    XWindowEvent (xdisplay,
3032
		  new_dm_sn_owner,
3033
		  PropertyChangeMask,
3034
		  &event);
3035
3036
    dm_sn_timestamp = event.xproperty.time;
3037
3038
    XSetSelectionOwner (xdisplay, dm_sn_atom, new_dm_sn_owner,
3039
			dm_sn_timestamp);
3040
3041
    if (XGetSelectionOwner (xdisplay, dm_sn_atom) != new_dm_sn_owner)
3042
    {
3043
	XDestroyWindow (xdisplay, new_dm_sn_owner);
3044
3045
	return DECOR_ACQUIRE_STATUS_FAILED;
3046
    }
3047
3048
    /* Send client message indicating that we are now the DM */
3049
    event.xclient.type	       = ClientMessage;
3050
    event.xclient.window       = XRootWindow (xdisplay, screen);
3051
    event.xclient.message_type = manager_atom;
3052
    event.xclient.format       = 32;
3053
    event.xclient.data.l[0]    = dm_sn_timestamp;
3054
    event.xclient.data.l[1]    = dm_sn_atom;
3055
    event.xclient.data.l[2]    = 0;
3056
    event.xclient.data.l[3]    = 0;
3057
    event.xclient.data.l[4]    = 0;
3058
3059
    XSendEvent (xdisplay, XRootWindow (xdisplay, screen), 0,
3060
		StructureNotifyMask, &event);
3061
3062
    /* Wait for old decoration manager to go away */
3063
    if (current_dm_sn_owner != None)
3064
    {
3065
	do {
3066
	    XWindowEvent (xdisplay, current_dm_sn_owner,
3067
			  StructureNotifyMask, &event);
3068
	} while (event.type != DestroyNotify);
3069
    }
3070
3071
    *timestamp = dm_sn_timestamp;
3072
3073
    return DECOR_ACQUIRE_STATUS_SUCCESS;
3074
}
3075
3076
void
3077
decor_set_dm_check_hint (Display *xdisplay,
3078
			 int	 screen,
2025 by Dennis Kasprzyk
Added support for 2D decorations.
3079
			 int     supports)
3080
{
679 by David Reveman
Move DM selection code into libdecoration.
3081
    XSetWindowAttributes attrs;
3082
    unsigned long	 data;
3083
    Window		 xroot;
3084
    Atom		 atom;
3085
    Atom		 type_pixmap_atom;
2025 by Dennis Kasprzyk
Added support for 2D decorations.
3086
    Atom		 type_window_atom;
3087
    Atom		 type_supported_atom;
3088
    Atom		 supported_deco_atoms[2];
3089
    int                  i;
3090
3091
    type_supported_atom = XInternAtom (xdisplay, DECOR_TYPE_ATOM_NAME, 0);
3092
    type_pixmap_atom = XInternAtom (xdisplay, DECOR_TYPE_PIXMAP_ATOM_NAME, 0);
3093
    type_window_atom = XInternAtom (xdisplay, DECOR_TYPE_WINDOW_ATOM_NAME, 0);
3094
3095
    if (!supports)
3096
	return;
3097
679 by David Reveman
Move DM selection code into libdecoration.
3098
    attrs.override_redirect = 1;
3099
    attrs.event_mask	    = PropertyChangeMask;
3100
3101
    xroot = RootWindow (xdisplay, screen);
3102
3103
    data = XCreateWindow (xdisplay,
3104
			  xroot,
3105
			  -100, -100, 1, 1,
3106
			  0,
3107
			  CopyFromParent,
3108
			  CopyFromParent,
3109
			  (Visual *) CopyFromParent,
3110
			  CWOverrideRedirect | CWEventMask,
3111
			  &attrs);
3112
3113
    i = 0;
2025 by Dennis Kasprzyk
Added support for 2D decorations.
3114
    if (supports & WINDOW_DECORATION_TYPE_PIXMAP)
3115
    {
3116
	supported_deco_atoms[i] = type_pixmap_atom;
3117
	i++;
3118
    }
3119
    if (supports & WINDOW_DECORATION_TYPE_WINDOW)
3120
    {
3121
	supported_deco_atoms[i] = type_window_atom;
3122
	i++;
3123
    }
3124
    XChangeProperty (xdisplay,
3125
		     data,
3126
		     type_supported_atom,
3127
		     XA_ATOM, 32,
3128
		     PropModeReplace,
3129
		     (unsigned char *) supported_deco_atoms,
3130
		     i);
3131
3132
    atom = XInternAtom (xdisplay, DECOR_SUPPORTING_DM_CHECK_ATOM_NAME, 0);
1710 by Danny Baumann
Make decoration atom names part of the decoration interface.
3133
679 by David Reveman
Move DM selection code into libdecoration.
3134
    XChangeProperty (xdisplay, xroot,
3135
		     atom,
3136
		     XA_WINDOW,
3137
		     32, PropModeReplace, (unsigned char *) &data, 1);
3138
}
3139
3140
/* from fvwm2, Copyright Matthias Clasen, Dominik Vogt */
3141
static int
3142
convert_property (Display *xdisplay,
3143
		  Window  w,
3144
		  Atom    target,
3145
		  Atom    property,
3146
		  Time    dm_sn_timestamp)
3147
{
3148
3149
static const unsigned short N_TARGETS = 4;
3338.4.9 by MC Return
Replace #defines, part X
3150
679 by David Reveman
Move DM selection code into libdecoration.
3151
    Atom conversion_targets[N_TARGETS];
3152
3153
    conversion_targets[0] = XInternAtom (xdisplay, "TARGETS", 0);
3154
    conversion_targets[1] = XInternAtom (xdisplay, "MULTIPLE", 0);
3155
    conversion_targets[2] = XInternAtom (xdisplay, "TIMESTAMP", 0);
3156
    conversion_targets[3] = XInternAtom (xdisplay, "VERSION", 0);
3157
3158
    if (target == conversion_targets[0])
3159
	XChangeProperty (xdisplay, w, property,
3160
			 XA_ATOM, 32, PropModeReplace,
3161
			 (unsigned char *) conversion_targets, N_TARGETS);
3162
    else if (target == conversion_targets[2])
3163
	XChangeProperty (xdisplay, w, property,
3164
			 XA_INTEGER, 32, PropModeReplace,
3165
			 (unsigned char *) &dm_sn_timestamp, 1);
3166
    else if (target == conversion_targets[3])
3167
    {
3302.2.1 by MC Return
Reduced the scope of the variable 'icccm_version'
3168
	long icccm_version[] = { 2, 0 };
3169
	XChangeProperty (xdisplay, w, property,
679 by David Reveman
Move DM selection code into libdecoration.
3170
			 XA_INTEGER, 32, PropModeReplace,
3171
			 (unsigned char *) icccm_version, 2);
3172
    }
3302.2.1 by MC Return
Reduced the scope of the variable 'icccm_version'
3173
    else
679 by David Reveman
Move DM selection code into libdecoration.
3174
	return 0;
3175
3176
    /* Be sure the PropertyNotify has arrived so we
3177
     * can send SelectionNotify
3178
     */
3179
    XSync (xdisplay, 0);
3180
3181
    return 1;
3182
}
3183
3184
void
3185
decor_handle_selection_request (Display *xdisplay,
3186
				XEvent  *event,
3187
				Time    timestamp)
3188
{
3189
    XSelectionEvent reply;
3190
    Atom	    multiple_atom;
3191
    Atom	    atom_pair_atom;
3192
3193
    reply.type	    = SelectionNotify;
3194
    reply.display   = xdisplay;
3195
    reply.requestor = event->xselectionrequest.requestor;
3196
    reply.selection = event->xselectionrequest.selection;
3197
    reply.target    = event->xselectionrequest.target;
3198
    reply.property  = None;
3199
    reply.time	    = event->xselectionrequest.time;
3200
3201
    multiple_atom  = XInternAtom (xdisplay, "MULTIPLE", 0);
3202
    atom_pair_atom = XInternAtom (xdisplay, "ATOM_PAIR", 0);
3203
3204
    if (event->xselectionrequest.target == multiple_atom)
3205
    {
3206
	if (event->xselectionrequest.property != None)
3207
	{
3208
	    Atom	  type, *adata;
3209
	    int		  i, format;
3210
	    unsigned long num, rest;
3211
	    unsigned char *data;
3212
3213
	    if (XGetWindowProperty (xdisplay,
3214
				    event->xselectionrequest.requestor,
3215
				    event->xselectionrequest.property,
3216
				    0, 256, FALSE,
3217
				    atom_pair_atom,
3218
				    &type, &format, &num, &rest,
3219
				    &data) != Success)
3220
		return;
3221
3222
	    /* FIXME: to be 100% correct, should deal with rest > 0,
3223
	     * but since we have 4 possible targets, we will hardly ever
3224
	     * meet multiple requests with a length > 8
3225
	     */
3226
	    adata = (Atom *) data;
3227
	    i = 0;
3228
	    while (i < (int) num)
3229
	    {
3230
		if (!convert_property (xdisplay,
3231
				       event->xselectionrequest.requestor,
3232
				       adata[i], adata[i + 1],
3233
				       timestamp))
3234
		    adata[i + 1] = None;
3235
3236
		i += 2;
3237
	    }
3238
3239
	    XChangeProperty (xdisplay,
3240
			     event->xselectionrequest.requestor,
3241
			     event->xselectionrequest.property,
3242
			     atom_pair_atom,
3243
			     32, PropModeReplace, data, num);
3244
	}
3245
    }
3246
    else
3247
    {
3248
	if (event->xselectionrequest.property == None)
3249
	    event->xselectionrequest.property = event->xselectionrequest.target;
3250
3251
	if (convert_property (xdisplay,
3252
			      event->xselectionrequest.requestor,
3253
			      event->xselectionrequest.target,
3254
			      event->xselectionrequest.property,
3255
			      timestamp))
3256
	    reply.property = event->xselectionrequest.property;
3257
    }
3258
3259
    XSendEvent (xdisplay,
3260
		event->xselectionrequest.requestor,
3261
		FALSE, 0L, (XEvent *) &reply);
3262
}
3263
3264
int
3265
decor_handle_selection_clear (Display *xdisplay,
3266
			      XEvent  *xevent,
3267
			      int     screen)
3268
{
3269
    Atom dm_sn_atom;
3270
    char buf[128];
3271
3272
    snprintf (buf, 128, "_COMPIZ_DM_S%d", screen);
3360.4.50 by Sam Spilsbury
Unrevert changes which shouldn't have been reverted
3273
    dm_sn_atom = XInternAtom (xdisplay, buf, 0);
679 by David Reveman
Move DM selection code into libdecoration.
3274
3275
    if (xevent->xselectionclear.selection == dm_sn_atom)
3276
	return DECOR_SELECTION_GIVE_UP;
3277
3278
    return DECOR_SELECTION_KEEP;
3279
}
3280