Merge lp:~unity-team/compiz/x-sru5 into lp:compiz/0.9.13

Proposed by Marco Trevisan (Treviño)
Status: Superseded
Proposed branch: lp:~unity-team/compiz/x-sru5
Merge into: lp:compiz/0.9.13
Diff against target: 1684 lines (+1650/-0) (has conflicts)
3 files modified
debian/changelog (+93/-0)
gtk/window-decorator/decorator.c (+2/-0)
gtk/window-decorator/metacity.c.OTHER (+1555/-0)
Text conflict in debian/changelog
Contents conflict in gtk/window-decorator/metacity.c
To merge this branch: bzr merge lp:~unity-team/compiz/x-sru5
Reviewer Review Type Date Requested Status
Compiz Maintainers Pending
Review via email: mp+326393@code.launchpad.net

Commit message

Releasing SRU5 for Ubuntu 16.04

To post a comment you must log in.
lp:~unity-team/compiz/x-sru5 updated
4027. By Marco Trevisan (Treviño)

unity-lowgfx: use better effect for grid

4028. By Marco Trevisan (Treviño)

debian/changelog: add missing bug references

4029. By Alberts Muktupāvels

Use AnyPropertyType when getting _MOTIF_WM_HINTS property.

4030. By Marco Trevisan (Treviño)

move: damage all the border area in outline mode and ignore transparent colors

Also we don't really need to damage at every X event. It's just about doing it
right the firs time, by including the exceeding space.
Also optimize damanging in outline-mode, by only touching such regions

Plus add some optimizations when not blending, as we don't care about the alpha channel

4031. By Marco Trevisan (Treviño)

grid: ignore alpha in colors when not blending, and fix animations

The fade-out animation was still happening when the duration was set to 1,
while it was broken when it was 0. Fixed both.

In unity-lowgfx.ini set the animation duration to 0 in grid and d not
draw stretched windows. Enable blending again as it's really not
expensive in this case, while not having it, really makes the user
experience a lot poorer.

4032. By Marco Trevisan (Treviño)

resize: add support for disabling transparency and avoid over-damaging in outline mode

4033. By Marco Trevisan (Treviño)

Screen: add averageColor to get the current desktop average color

We get the value from the root window and we parse it using regex.
Also use this in 'move', 'resize' and 'grid' plugins by default, doing the
appropriate lightening / darkening to make this working properly
on the desktop surface

4034. By Marco Trevisan (Treviño)

Bumping micro version

4035. By Marco Trevisan (Treviño)

debian: go back setting COMPIZ_CONFIG_PROFILE in X11 scripts

4036. By Marco Trevisan (Treviño)

debian: tune unity-lowgfx profile and add upgrades

4037. By Marco Trevisan (Treviño)

unity-lowgfx.ini: remove unsupported unity option

Unmerged revisions

4037. By Marco Trevisan (Treviño)

unity-lowgfx.ini: remove unsupported unity option

4036. By Marco Trevisan (Treviño)

debian: tune unity-lowgfx profile and add upgrades

4035. By Marco Trevisan (Treviño)

debian: go back setting COMPIZ_CONFIG_PROFILE in X11 scripts

4034. By Marco Trevisan (Treviño)

Bumping micro version

4033. By Marco Trevisan (Treviño)

Screen: add averageColor to get the current desktop average color

We get the value from the root window and we parse it using regex.
Also use this in 'move', 'resize' and 'grid' plugins by default, doing the
appropriate lightening / darkening to make this working properly
on the desktop surface

4032. By Marco Trevisan (Treviño)

resize: add support for disabling transparency and avoid over-damaging in outline mode

4031. By Marco Trevisan (Treviño)

grid: ignore alpha in colors when not blending, and fix animations

The fade-out animation was still happening when the duration was set to 1,
while it was broken when it was 0. Fixed both.

In unity-lowgfx.ini set the animation duration to 0 in grid and d not
draw stretched windows. Enable blending again as it's really not
expensive in this case, while not having it, really makes the user
experience a lot poorer.

4030. By Marco Trevisan (Treviño)

move: damage all the border area in outline mode and ignore transparent colors

Also we don't really need to damage at every X event. It's just about doing it
right the firs time, by including the exceeding space.
Also optimize damanging in outline-mode, by only touching such regions

Plus add some optimizations when not blending, as we don't care about the alpha channel

4029. By Alberts Muktupāvels

Use AnyPropertyType when getting _MOTIF_WM_HINTS property.

4028. By Marco Trevisan (Treviño)

debian/changelog: add missing bug references

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/changelog'
--- debian/changelog 2017-06-16 15:17:48 +0000
+++ debian/changelog 2017-06-27 23:27:37 +0000
@@ -1,3 +1,4 @@
1<<<<<<< TREE
1compiz (1:0.9.13.1+17.10.20170616-0ubuntu1) artful; urgency=medium2compiz (1:0.9.13.1+17.10.20170616-0ubuntu1) artful; urgency=medium
23
3 [ Martin Wimpress ]4 [ Martin Wimpress ]
@@ -326,6 +327,98 @@
326327
327 -- Matthias Klose <doko@ubuntu.com> Sat, 23 Apr 2016 00:01:37 +0000328 -- Matthias Klose <doko@ubuntu.com> Sat, 23 Apr 2016 00:01:37 +0000
328329
330=======
331compiz (1:0.9.12.2+16.04.20160823-0ubuntu2) UNRELEASED; urgency=medium
332
333 [ Eleni Maria Stea ]
334 * Added option to disable blend in grid plugin
335 * Move: add options for showing only the window shape (filled or not)
336
337 [ Marco Trevisan (Treviño) ]
338 * debian/65compiz_profile-on-session: don't export
339 COMPIZ_CONFIG_PROFILE in unity
340
341 [ Alberts Muktupāvels ]
342 * Ensure that surfaces used by metacity theme have device scale set to
343 1 . (LP: #1530277) (LP: #1530277)
344
345 [ Martin Wimpress ]
346 * mate: Avoid artefacts of Windows Thumbnail Previews (LP: #1606369)
347
348 -- Eleni Maria Stea <elenimaria.stea@canonical.com> Tue, 27 Jun 2017 18:49:59 +0200
349
350compiz (1:0.9.12.2+16.04.20160823-0ubuntu1) xenial; urgency=medium
351
352 [ Andrea Azzarone ]
353 * [expo] limit scroll to workarea. (LP: #913880)
354
355 -- Marco Trevisan (Treviño) <mail@3v1n0.net> Tue, 23 Aug 2016 16:06:02 +0000
356
357compiz (1:0.9.12.2+16.04.20160801.3-0ubuntu1) xenial; urgency=medium
358
359 [ Andrea Azzarone ]
360 * Don't activate expo if not needed (1x1 setup) (LP: #1606254)
361 * Don't crash if gsettings key is not found. Default value will be
362 used. (LP: #1044662)
363 * focusDefaultWindow: focus Most Recently Used (MRU) window and
364 fallback to the top window in case MRU list is not available. (LP:
365 #1073488, LP: #1459671)
366
367 [ Marco Trevisan (Treviño) ]
368 * Unity MigrationScript: sync gsettings on exit, and only use dconf on
369 failure (LP: #1605011)
370
371 -- Marco Trevisan (Treviño) <mail@3v1n0.net> Mon, 01 Aug 2016 13:41:42 +0000
372
373compiz (1:0.9.12.2+16.04.20160714-0ubuntu1) xenial; urgency=medium
374
375 [ Eleni Maria Stea ]
376 * Added options for no animation in expo and scale plugins. They skip
377 the intermediate fading steps that force several redraws.
378 * Added a new option in show desktop plugin that skips the fade
379 animation: useful when performance is more important than eyecandy.
380
381 [ Marco Trevisan (Treviño) ]
382 * debian: add unity-lowgfx profile to compizconfig (LP: #1598770)
383 * Composite: use C++ goodness for managing damaging rectangles
384 * ccsGSettingsBackend: don't try to update setting if wrapper is not
385 found
386 * migration scripts: remove unsupported plugins for all the unity
387 profiles
388
389 -- Marco Trevisan (Treviño) <mail@3v1n0.net> Thu, 14 Jul 2016 16:00:57 +0000
390
391compiz (1:0.9.12.2+16.04.20160526-0ubuntu1) xenial; urgency=medium
392
393 [ Andrea Azzarone ]
394 * Add an option to notify that a key press is actually an "auto
395 repeat" one. (LP: #1572241)
396
397 [ Alberts Muktupāvels ]
398 * OpenGL: use the number of Opaque windows around to decide whether
399 paint the bg or not (LP: #1574866)
400
401 [ Marco Trevisan (Treviño) ]
402 * Scale: use the selectedWindow as starting point when focusing a
403 window (LP: #1575168)
404 * Scale: allow to iterate through windows using Tab key
405 * Window: call stateChangeNotify when compiz state changed but before
406 changing the WM state (LP: #1521302)
407
408 [ Eleni Maria Stea ]
409 * Expo, Scale: add support for bottom offsets (LP: #1562346, LP:
410 #1573897)
411
412 [ handsome_feng ]
413 * Add a YBottomOffset value when stretch maximized windows。 (LP:
414 #1562348)
415
416 [ CI Train Bot ]
417 * No-change rebuild.
418
419 -- Marco Trevisan (Treviño) <mail@3v1n0.net> Thu, 26 May 2016 00:12:16 +0000
420
421>>>>>>> MERGE-SOURCE
329compiz (1:0.9.12.2+16.04.20160415-0ubuntu1) xenial; urgency=medium422compiz (1:0.9.12.2+16.04.20160415-0ubuntu1) xenial; urgency=medium
330423
331 [ Martin Wimpress ]424 [ Martin Wimpress ]
332425
=== modified file 'debian/mate.ini'
=== modified file 'gtk/window-decorator/decorator.c'
--- gtk/window-decorator/decorator.c 2017-04-02 17:32:10 +0000
+++ gtk/window-decorator/decorator.c 2017-06-27 23:27:37 +0000
@@ -553,6 +553,8 @@
553 }553 }
554#endif554#endif
555555
556 // FIXME: this should match the current monitor scaling!
557 cairo_surface_set_device_scale (buffer_surface, 1, 1);
556 gdk_flush ();558 gdk_flush ();
557559
558 /* Handle failure */560 /* Handle failure */
559561
=== added file 'gtk/window-decorator/metacity.c.OTHER'
--- gtk/window-decorator/metacity.c.OTHER 1970-01-01 00:00:00 +0000
+++ gtk/window-decorator/metacity.c.OTHER 2017-06-27 23:27:37 +0000
@@ -0,0 +1,1555 @@
1/*
2 * Copyright © 2006 Novell, Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 *
19 * Author: David Reveman <davidr@novell.com>
20 *
21 * 2D Mode: Copyright © 2010 Sam Spilsbury <smspillaz@gmail.com>
22 * Frames Management: Copright © 2011 Canonical Ltd.
23 * Authored By: Sam Spilsbury <sam.spilsbury@canonical.com>
24 */
25
26#include "gtk-window-decorator.h"
27
28#ifdef USE_METACITY
29
30MetaButtonLayout meta_button_layout;
31
32static gboolean
33meta_button_present (MetaButtonLayout *button_layout,
34 MetaButtonFunction function)
35{
36 int i;
37
38 for (i = 0; i < MAX_BUTTONS_PER_CORNER; ++i)
39 if (button_layout->left_buttons[i] == function)
40 return TRUE;
41
42 for (i = 0; i < MAX_BUTTONS_PER_CORNER; ++i)
43 if (button_layout->right_buttons[i] == function)
44 return TRUE;
45
46 return FALSE;
47}
48
49static void
50decor_update_meta_window_property (decor_t *d,
51 MetaTheme *theme,
52 MetaFrameFlags flags,
53 MetaFrameType type,
54 Region top,
55 Region bottom,
56 Region left,
57 Region right)
58{
59 long *data;
60 GdkDisplay *display;
61 Display *xdisplay;
62 gint nQuad;
63 decor_extents_t win_extents;
64 decor_extents_t frame_win_extents;
65 decor_extents_t max_win_extents;
66 decor_extents_t frame_max_win_extents;
67 decor_quad_t quads[N_QUADS_MAX];
68 unsigned int nOffset;
69 unsigned int frame_type;
70 unsigned int frame_state;
71 unsigned int frame_actions;
72 gint w;
73 gint lh;
74 gint rh;
75 gint top_stretch_offset;
76 gint bottom_stretch_offset;
77 gint left_stretch_offset;
78 gint right_stretch_offset;
79
80 display = gdk_display_get_default ();
81 xdisplay = gdk_x11_display_get_xdisplay (display);
82
83 nOffset = 1;
84
85 frame_type = populate_frame_type (d);
86 frame_state = populate_frame_state (d);
87 frame_actions = populate_frame_actions (d);
88
89 win_extents = frame_win_extents = d->frame->win_extents;
90 max_win_extents = frame_max_win_extents = d->frame->max_win_extents;
91
92 /* Add the invisible grab area padding, but only for
93 * pixmap type decorations */
94 if (!d->frame_window)
95 {
96 GdkScreen *screen;
97 MetaStyleInfo *style_info;
98 MetaFrameBorders borders;
99
100 screen = gtk_widget_get_screen (d->frame->style_window_rgba);
101 style_info = meta_theme_create_style_info (screen, d->gtk_theme_variant);
102
103 meta_theme_get_frame_borders (theme, style_info, type,
104 d->frame->text_height,
105 flags, &borders);
106
107 if (flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE)
108 {
109 frame_win_extents.left += borders.invisible.left;
110 frame_win_extents.right += borders.invisible.right;
111 frame_max_win_extents.left += borders.invisible.left;
112 frame_max_win_extents.right += borders.invisible.right;
113 }
114
115 if (flags & META_FRAME_ALLOWS_VERTICAL_RESIZE)
116 {
117 frame_win_extents.bottom += borders.invisible.bottom;
118 frame_win_extents.top += borders.invisible.top;
119 frame_max_win_extents.bottom += borders.invisible.bottom;
120 frame_max_win_extents.top += borders.invisible.top;
121 }
122
123 meta_style_info_unref (style_info);
124 }
125
126 w = d->border_layout.top.x2 - d->border_layout.top.x1 -
127 d->context->left_space - d->context->right_space;
128
129 if (d->border_layout.rotation)
130 lh = d->border_layout.left.x2 - d->border_layout.left.x1;
131 else
132 lh = d->border_layout.left.y2 - d->border_layout.left.y1;
133
134 if (d->border_layout.rotation)
135 rh = d->border_layout.right.x2 - d->border_layout.right.x1;
136 else
137 rh = d->border_layout.right.y2 - d->border_layout.right.y1;
138
139 left_stretch_offset = lh / 2;
140 right_stretch_offset = rh / 2;
141 top_stretch_offset = w - d->button_width - 1;
142 bottom_stretch_offset = (d->border_layout.bottom.x2 - d->border_layout.bottom.x1 -
143 d->context->left_space - d->context->right_space) / 2;
144
145 nQuad = decor_set_lXrXtXbX_window_quads (quads, d->context, &d->border_layout,
146 left_stretch_offset, right_stretch_offset,
147 top_stretch_offset, bottom_stretch_offset);
148
149 win_extents.top += d->frame->titlebar_height;
150 frame_win_extents.top += d->frame->titlebar_height;
151 max_win_extents.top += d->frame->max_titlebar_height;
152 frame_max_win_extents.top += d->frame->max_titlebar_height;
153
154 if (d->frame_window)
155 {
156 data = decor_alloc_property (nOffset, WINDOW_DECORATION_TYPE_WINDOW);
157 decor_gen_window_property (data, nOffset - 1, &win_extents, &max_win_extents,
158 20, 20, frame_type, frame_state, frame_actions);
159 }
160 else
161 {
162 data = decor_alloc_property (nOffset, WINDOW_DECORATION_TYPE_PIXMAP);
163 decor_quads_to_property (data, nOffset - 1, cairo_xlib_surface_get_drawable (d->surface),
164 &frame_win_extents, &win_extents,
165 &frame_max_win_extents, &max_win_extents,
166 ICON_SPACE + d->button_width,
167 0, quads, nQuad, frame_type, frame_state, frame_actions);
168 }
169
170 gdk_error_trap_push ();
171
172 XChangeProperty (xdisplay, d->prop_xid, win_decor_atom, XA_INTEGER,
173 32, PropModeReplace, (guchar *) data,
174 PROP_HEADER_SIZE + BASE_PROP_SIZE + QUAD_PROP_SIZE * N_QUADS_MAX);
175 gdk_display_sync (display);
176
177 gdk_error_trap_pop_ignored ();
178
179 free (data);
180
181 decor_update_blur_property (d, w, lh,
182 top, top_stretch_offset,
183 bottom, bottom_stretch_offset,
184 left, left_stretch_offset,
185 right, right_stretch_offset);
186}
187
188static void
189meta_get_corner_radius (const MetaFrameGeometry *fgeom,
190 int *top_left_radius,
191 int *top_right_radius,
192 int *bottom_left_radius,
193 int *bottom_right_radius)
194{
195 *top_left_radius = fgeom->top_left_corner_rounded_radius;
196 *top_right_radius = fgeom->top_right_corner_rounded_radius;
197 *bottom_left_radius = fgeom->bottom_left_corner_rounded_radius;
198 *bottom_right_radius = fgeom->bottom_right_corner_rounded_radius;
199}
200
201static int
202radius_to_width (int radius,
203 int i)
204{
205 float r1 = sqrt (radius) + radius;
206 float r2 = r1 * r1 - (r1 - (i + 0.5)) * (r1 - (i + 0.5));
207
208 return floor (0.5f + r1 - sqrt (r2));
209}
210
211static Region
212meta_get_top_border_region (const MetaFrameGeometry *fgeom,
213 int width)
214{
215 Region corners_xregion;
216 Region border_xregion;
217 XRectangle xrect;
218 int top_left_radius;
219 int top_right_radius;
220 int bottom_left_radius;
221 int bottom_right_radius;
222 int w;
223 int i;
224 int height;
225
226 corners_xregion = XCreateRegion ();
227
228 meta_get_corner_radius (fgeom, &top_left_radius, &top_right_radius,
229 &bottom_left_radius, &bottom_right_radius);
230
231 width = width - fgeom->borders.invisible.left - fgeom->borders.invisible.right;
232 height = fgeom->borders.visible.top;
233
234 if (top_left_radius)
235 {
236 for (i = 0; i < top_left_radius; ++i)
237 {
238 w = radius_to_width (top_left_radius, i);
239
240 xrect.x = 0;
241 xrect.y = i;
242 xrect.width = w;
243 xrect.height = 1;
244
245 XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion);
246 }
247 }
248
249 if (top_right_radius)
250 {
251 for (i = 0; i < top_right_radius; ++i)
252 {
253 w = radius_to_width (top_right_radius, i);
254
255 xrect.x = width - w;
256 xrect.y = i;
257 xrect.width = w;
258 xrect.height = 1;
259
260 XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion);
261 }
262 }
263
264 border_xregion = XCreateRegion ();
265
266 xrect.x = 0;
267 xrect.y = 0;
268 xrect.width = width;
269 xrect.height = height;
270
271 XUnionRectWithRegion (&xrect, border_xregion, border_xregion);
272
273 XSubtractRegion (border_xregion, corners_xregion, border_xregion);
274
275 XDestroyRegion (corners_xregion);
276
277 return border_xregion;
278}
279
280static Region
281meta_get_bottom_border_region (const MetaFrameGeometry *fgeom,
282 int width)
283{
284 Region corners_xregion;
285 Region border_xregion;
286 XRectangle xrect;
287 int top_left_radius;
288 int top_right_radius;
289 int bottom_left_radius;
290 int bottom_right_radius;
291 int w;
292 int i;
293 int height;
294
295 corners_xregion = XCreateRegion ();
296
297 meta_get_corner_radius (fgeom, &top_left_radius, &top_right_radius,
298 &bottom_left_radius, &bottom_right_radius);
299
300 width = width - fgeom->borders.invisible.left - fgeom->borders.invisible.right;
301 height = fgeom->borders.visible.bottom;
302
303 if (bottom_left_radius)
304 {
305 for (i = 0; i < bottom_left_radius; ++i)
306 {
307 w = radius_to_width (bottom_left_radius, i);
308
309 xrect.x = 0;
310 xrect.y = height - i - 1;
311 xrect.width = w;
312 xrect.height = 1;
313
314 XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion);
315 }
316 }
317
318 if (bottom_right_radius)
319 {
320 for (i = 0; i < bottom_right_radius; ++i)
321 {
322 w = radius_to_width (bottom_right_radius, i);
323
324 xrect.x = width - w;
325 xrect.y = height - i - 1;
326 xrect.width = w;
327 xrect.height = 1;
328
329 XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion);
330 }
331 }
332
333 border_xregion = XCreateRegion ();
334
335 xrect.x = 0;
336 xrect.y = 0;
337 xrect.width = width;
338 xrect.height = height;
339
340 XUnionRectWithRegion (&xrect, border_xregion, border_xregion);
341
342 XSubtractRegion (border_xregion, corners_xregion, border_xregion);
343
344 XDestroyRegion (corners_xregion);
345
346 return border_xregion;
347}
348
349static Region
350meta_get_left_border_region (const MetaFrameGeometry *fgeom,
351 int height)
352{
353 Region border_xregion;
354 XRectangle xrect;
355
356 border_xregion = XCreateRegion ();
357
358 xrect.x = 0;
359 xrect.y = 0;
360 xrect.width = fgeom->borders.visible.left;
361 xrect.height = height - fgeom->borders.total.top - fgeom->borders.total.bottom;
362
363 XUnionRectWithRegion (&xrect, border_xregion, border_xregion);
364
365 return border_xregion;
366}
367
368static Region
369meta_get_right_border_region (const MetaFrameGeometry *fgeom,
370 int height)
371{
372 Region border_xregion;
373 XRectangle xrect;
374
375 border_xregion = XCreateRegion ();
376
377 xrect.x = 0;
378 xrect.y = 0;
379 xrect.width = fgeom->borders.visible.right;
380 xrect.height = height - fgeom->borders.total.top - fgeom->borders.total.bottom;
381
382 XUnionRectWithRegion (&xrect, border_xregion, border_xregion);
383
384 return border_xregion;
385}
386
387static MetaButtonState
388meta_button_state (int state)
389{
390 if (state & IN_EVENT_WINDOW)
391 {
392 if (state & PRESSED_EVENT_WINDOW)
393 return META_BUTTON_STATE_PRESSED;
394
395 return META_BUTTON_STATE_PRELIGHT;
396 }
397
398 return META_BUTTON_STATE_NORMAL;
399}
400
401static MetaButtonType
402meta_function_to_type (MetaButtonFunction function)
403{
404 switch (function)
405 {
406 case META_BUTTON_FUNCTION_MENU:
407 return META_BUTTON_TYPE_MENU;
408 case META_BUTTON_FUNCTION_MINIMIZE:
409 return META_BUTTON_TYPE_MINIMIZE;
410 case META_BUTTON_FUNCTION_MAXIMIZE:
411 return META_BUTTON_TYPE_MAXIMIZE;
412 case META_BUTTON_FUNCTION_CLOSE:
413 return META_BUTTON_TYPE_CLOSE;
414 case META_BUTTON_FUNCTION_SHADE:
415 return META_BUTTON_TYPE_SHADE;
416 case META_BUTTON_FUNCTION_ABOVE:
417 return META_BUTTON_TYPE_ABOVE;
418 case META_BUTTON_FUNCTION_STICK:
419 return META_BUTTON_TYPE_STICK;
420 case META_BUTTON_FUNCTION_UNSHADE:
421 return META_BUTTON_TYPE_UNSHADE;
422 case META_BUTTON_FUNCTION_UNABOVE:
423 return META_BUTTON_TYPE_UNABOVE;
424 case META_BUTTON_FUNCTION_UNSTICK:
425 return META_BUTTON_TYPE_UNSTICK;
426 default:
427 break;
428 }
429
430 return META_BUTTON_TYPE_LAST;
431}
432
433static MetaButtonState
434meta_button_state_for_button_type (decor_t *d,
435 MetaButtonType type)
436{
437 switch (type)
438 {
439 case META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND:
440 type = meta_function_to_type (meta_button_layout.left_buttons[0]);
441 break;
442 case META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND:
443 type = meta_function_to_type (meta_button_layout.left_buttons[1]);
444 break;
445 case META_BUTTON_TYPE_LEFT_RIGHT_BACKGROUND:
446 type = meta_function_to_type (meta_button_layout.left_buttons[2]);
447 break;
448 case META_BUTTON_TYPE_RIGHT_LEFT_BACKGROUND:
449 type = meta_function_to_type (meta_button_layout.right_buttons[0]);
450 break;
451 case META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND:
452 type = meta_function_to_type (meta_button_layout.right_buttons[1]);
453 break;
454 case META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND:
455 type = meta_function_to_type (meta_button_layout.right_buttons[2]);
456 default:
457 break;
458 }
459
460 switch (type)
461 {
462 case META_BUTTON_TYPE_CLOSE:
463 return meta_button_state (d->button_states[BUTTON_CLOSE]);
464 case META_BUTTON_TYPE_MAXIMIZE:
465 return meta_button_state (d->button_states[BUTTON_MAX]);
466 case META_BUTTON_TYPE_MINIMIZE:
467 return meta_button_state (d->button_states[BUTTON_MIN]);
468 case META_BUTTON_TYPE_MENU:
469 return meta_button_state (d->button_states[BUTTON_MENU]);
470 case META_BUTTON_TYPE_SHADE:
471 return meta_button_state (d->button_states[BUTTON_SHADE]);
472 case META_BUTTON_TYPE_ABOVE:
473 return meta_button_state (d->button_states[BUTTON_ABOVE]);
474 case META_BUTTON_TYPE_STICK:
475 return meta_button_state (d->button_states[BUTTON_STICK]);
476 case META_BUTTON_TYPE_UNSHADE:
477 return meta_button_state (d->button_states[BUTTON_UNSHADE]);
478 case META_BUTTON_TYPE_UNABOVE:
479 return meta_button_state (d->button_states[BUTTON_UNABOVE]);
480 case META_BUTTON_TYPE_UNSTICK:
481 return meta_button_state (d->button_states[BUTTON_UNSTICK]);
482 default:
483 break;
484 }
485
486 return META_BUTTON_STATE_NORMAL;
487}
488
489static void
490meta_get_decoration_geometry (decor_t *d,
491 MetaTheme *theme,
492 MetaFrameFlags *flags,
493 MetaFrameGeometry *fgeom,
494 MetaButtonLayout *button_layout,
495 MetaFrameType frame_type)
496{
497 GdkScreen *screen;
498 MetaStyleInfo *style_info;
499 gint client_width;
500 gint client_height;
501
502 if (!(frame_type < META_FRAME_TYPE_LAST))
503 frame_type = META_FRAME_TYPE_NORMAL;
504
505 if (meta_button_layout_set)
506 {
507 *button_layout = meta_button_layout;
508 }
509 else
510 {
511 gint i;
512
513 button_layout->left_buttons[0] = META_BUTTON_FUNCTION_MENU;
514
515 for (i = 1; i < MAX_BUTTONS_PER_CORNER; ++i)
516 button_layout->left_buttons[i] = META_BUTTON_FUNCTION_LAST;
517
518 button_layout->right_buttons[0] = META_BUTTON_FUNCTION_MINIMIZE;
519 button_layout->right_buttons[1] = META_BUTTON_FUNCTION_MAXIMIZE;
520 button_layout->right_buttons[2] = META_BUTTON_FUNCTION_CLOSE;
521
522 for (i = 3; i < MAX_BUTTONS_PER_CORNER; ++i)
523 button_layout->right_buttons[i] = META_BUTTON_FUNCTION_LAST;
524 }
525
526 *flags = 0;
527
528 if (d->actions & WNCK_WINDOW_ACTION_CLOSE)
529 *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_DELETE;
530
531 if (d->actions & WNCK_WINDOW_ACTION_MINIMIZE)
532 *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_MINIMIZE;
533
534 if (d->actions & WNCK_WINDOW_ACTION_MAXIMIZE)
535 *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_MAXIMIZE;
536
537 *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_MENU;
538
539 if (d->actions & WNCK_WINDOW_ACTION_RESIZE)
540 {
541 if (!(d->state & WNCK_WINDOW_STATE_MAXIMIZED_VERTICALLY))
542 *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_VERTICAL_RESIZE;
543 if (!(d->state & WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY))
544 *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_HORIZONTAL_RESIZE;
545 }
546
547 if (d->actions & WNCK_WINDOW_ACTION_MOVE)
548 *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_MOVE;
549
550 if (d->actions & WNCK_WINDOW_ACTION_MAXIMIZE)
551 *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_MAXIMIZE;
552
553 if (d->actions & WNCK_WINDOW_ACTION_SHADE)
554 *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_SHADE;
555
556 if (d->active)
557 *flags |= (MetaFrameFlags ) META_FRAME_HAS_FOCUS;
558
559 if ((d->state & META_MAXIMIZED) == META_MAXIMIZED)
560 *flags |= (MetaFrameFlags ) META_FRAME_MAXIMIZED;
561
562 if (d->state & WNCK_WINDOW_STATE_STICKY)
563 *flags |= (MetaFrameFlags ) META_FRAME_STUCK;
564
565 if (d->state & WNCK_WINDOW_STATE_FULLSCREEN)
566 *flags |= (MetaFrameFlags ) META_FRAME_FULLSCREEN;
567
568 if (d->state & WNCK_WINDOW_STATE_SHADED)
569 *flags |= (MetaFrameFlags ) META_FRAME_SHADED;
570
571 if (d->state & WNCK_WINDOW_STATE_ABOVE)
572 *flags |= (MetaFrameFlags ) META_FRAME_ABOVE;
573
574 client_width = d->border_layout.top.x2 - d->border_layout.top.x1;
575 client_width -= d->context->right_space + d->context->left_space;
576
577 if (d->border_layout.rotation)
578 client_height = d->border_layout.left.x2 - d->border_layout.left.x1;
579 else
580 client_height = d->border_layout.left.y2 - d->border_layout.left.y1;
581
582 screen = gtk_widget_get_screen (d->frame->style_window_rgba);
583 style_info = meta_theme_create_style_info (screen, d->gtk_theme_variant);
584
585 meta_theme_calc_geometry (theme, style_info, frame_type, d->frame->text_height,
586 *flags, client_width, client_height,
587 button_layout, fgeom);
588
589 meta_style_info_unref (style_info);
590}
591
592void
593meta_draw_window_decoration (decor_t *d)
594{
595 GdkDisplay *display;
596 GdkScreen *screen;
597 Display *xdisplay;
598 cairo_surface_t *surface;
599 Picture src;
600 MetaButtonState button_states [META_BUTTON_TYPE_LAST];
601 MetaButtonLayout button_layout;
602 MetaFrameGeometry fgeom;
603 MetaFrameFlags flags;
604 MetaFrameType frame_type;
605 MetaTheme *theme;
606 MetaStyleInfo *style_info;
607 GtkStyleContext *context;
608 cairo_t *cr;
609 gint i;
610 Region top_region;
611 Region bottom_region;
612 Region left_region;
613 Region right_region;
614 gdouble meta_active_opacity;
615 gdouble meta_inactive_opacity;
616 gboolean meta_active_shade_opacity;
617 gboolean meta_inactive_shade_opacity;
618 double alpha;
619 gboolean shade_alpha;
620 MetaFrameStyle *frame_style;
621 GtkWidget *style_window;
622 GdkRGBA bg_rgba;
623
624 if (!d->surface || !d->picture)
625 return;
626
627 display = gdk_display_get_default ();
628 xdisplay = gdk_x11_display_get_xdisplay (display);
629
630 top_region = NULL;
631 bottom_region = NULL;
632 left_region = NULL;
633 right_region = NULL;
634
635 g_object_get (settings, "metacity-active-opacity", &meta_active_opacity, NULL);
636 g_object_get (settings, "metacity-inactive-opacity", &meta_inactive_opacity, NULL);
637 g_object_get (settings, "metacity-active-shade-opacity", &meta_active_shade_opacity, NULL);
638 g_object_get (settings, "metacity-inactive-shade-opacity", &meta_inactive_shade_opacity, NULL);
639
640 alpha = (d->active) ? meta_active_opacity : meta_inactive_opacity;
641 shade_alpha = (d->active) ? meta_active_shade_opacity : meta_inactive_shade_opacity;
642
643 if (decoration_alpha == 1.0)
644 alpha = 1.0;
645
646 if (cairo_xlib_surface_get_depth (d->surface) == 32)
647 style_window = d->frame->style_window_rgba;
648 else
649 style_window = d->frame->style_window_rgb;
650
651 context = gtk_widget_get_style_context (style_window);
652
653 cr = cairo_create (d->buffer_surface ? d->buffer_surface : d->surface);
654
655 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
656
657 theme = meta_theme_get_current ();
658
659 frame_type = meta_frame_type_from_string (d->frame->type);
660
661 if (frame_type == META_FRAME_TYPE_LAST)
662 frame_type = META_FRAME_TYPE_NORMAL;
663
664 meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout,
665 frame_type);
666
667 if ((d->prop_xid || !d->buffer_surface) && !d->frame_window)
668 draw_shadow_background (d, cr, d->shadow, d->context);
669
670 for (i = 0; i < META_BUTTON_TYPE_LAST; ++i)
671 button_states[i] = meta_button_state_for_button_type (d, i);
672
673 frame_style = meta_theme_get_frame_style (theme, frame_type, flags);
674
675 gtk_style_context_get_background_color (context, GTK_STATE_FLAG_NORMAL, &bg_rgba);
676 bg_rgba.alpha = 1.0;
677
678 if (frame_style->window_background_color)
679 {
680 meta_color_spec_render (frame_style->window_background_color,
681 context, &bg_rgba);
682
683 bg_rgba.alpha = frame_style->window_background_alpha / 255.0;
684 }
685
686 /* Draw something that will be almost invisible to user. This is hacky way
687 * to fix invisible decorations. */
688 cairo_set_source_rgba (cr, 0, 0, 0, 0.01);
689 cairo_rectangle (cr, 0, 0, 1, 1);
690 cairo_fill (cr);
691 /* ------------ */
692
693 cairo_destroy (cr);
694
695 if (d->frame_window)
696 surface = create_surface (fgeom.width, fgeom.height, d->frame->style_window_rgb);
697 else
698 surface = create_surface (fgeom.width, fgeom.height, d->frame->style_window_rgba);
699
700 // FIXME: this should match the current monitor scaling!
701 cairo_surface_set_device_scale (surface, 1, 1);
702 cr = cairo_create (surface);
703 gdk_cairo_set_source_rgba (cr, &bg_rgba);
704 cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
705
706 src = XRenderCreatePicture (xdisplay, cairo_xlib_surface_get_drawable (surface),
707 get_format_for_surface (d, surface), 0, NULL);
708
709 screen = gtk_widget_get_screen (d->frame->style_window_rgba);
710 style_info = meta_theme_create_style_info (screen, d->gtk_theme_variant);
711
712 cairo_paint (cr);
713 meta_theme_draw_frame (theme, style_info, cr, frame_type, flags,
714 fgeom.width - fgeom.borders.total.left - fgeom.borders.total.right,
715 fgeom.height - fgeom.borders.total.top - fgeom.borders.total.bottom,
716 d->layout, d->frame->text_height, &button_layout,
717 button_states, d->icon_pixbuf, NULL);
718
719 meta_style_info_unref (style_info);
720
721 if (fgeom.borders.visible.top)
722 {
723 top_region = meta_get_top_border_region (&fgeom, fgeom.width);
724
725 decor_blend_border_picture (xdisplay, d->context, src,
726 fgeom.borders.invisible.left,
727 fgeom.borders.invisible.top,
728 d->picture, &d->border_layout,
729 BORDER_TOP, top_region,
730 alpha * 0xffff, shade_alpha, 0);
731 }
732
733 if (fgeom.borders.visible.bottom)
734 {
735 bottom_region = meta_get_bottom_border_region (&fgeom, fgeom.width);
736
737 decor_blend_border_picture (xdisplay, d->context, src,
738 fgeom.borders.invisible.left,
739 fgeom.height - fgeom.borders.total.bottom,
740 d->picture, &d->border_layout,
741 BORDER_BOTTOM, bottom_region,
742 alpha * 0xffff, shade_alpha, 0);
743 }
744
745 if (fgeom.borders.visible.left)
746 {
747 left_region = meta_get_left_border_region (&fgeom, fgeom.height);
748
749 decor_blend_border_picture (xdisplay, d->context, src,
750 fgeom.borders.invisible.left,
751 fgeom.borders.total.top,
752 d->picture, &d->border_layout,
753 BORDER_LEFT, left_region,
754 alpha * 0xffff, shade_alpha, 0);
755 }
756
757 if (fgeom.borders.visible.right)
758 {
759 right_region = meta_get_right_border_region (&fgeom, fgeom.height);
760
761 decor_blend_border_picture (xdisplay, d->context, src,
762 fgeom.width - fgeom.borders.total.right,
763 fgeom.borders.total.top,
764 d->picture, &d->border_layout,
765 BORDER_RIGHT, right_region,
766 alpha * 0xffff, shade_alpha, 0);
767 }
768
769 cairo_destroy (cr);
770 cairo_surface_destroy (surface);
771 XRenderFreePicture (xdisplay, src);
772
773 copy_to_front_buffer (d);
774
775 if (d->frame_window)
776 {
777 GdkWindow *gdk_frame_window;
778 GdkPixbuf *pixbuf;
779
780 gdk_frame_window = gtk_widget_get_window (d->decor_window);
781
782 pixbuf = gdk_pixbuf_get_from_surface (d->surface, 0, 0, d->width, d->height);
783 gtk_image_set_from_pixbuf (GTK_IMAGE (d->decor_image), pixbuf);
784 g_object_unref (pixbuf);
785
786 gdk_window_move_resize (gdk_frame_window,
787 d->context->left_corner_space - 1,
788 d->context->top_corner_space - 1,
789 d->width,
790 d->height);
791
792 gdk_window_lower (gdk_frame_window);
793 }
794
795 if (d->prop_xid)
796 {
797 /* translate from frame to client window space */
798 if (top_region)
799 XOffsetRegion (top_region, -fgeom.borders.total.left, -fgeom.borders.total.top);
800 if (bottom_region)
801 XOffsetRegion (bottom_region, -fgeom.borders.total.left, 0);
802 if (left_region)
803 XOffsetRegion (left_region, -fgeom.borders.total.left, 0);
804
805 decor_update_meta_window_property (d, theme, flags, frame_type,
806 top_region, bottom_region,
807 left_region, right_region);
808
809 d->prop_xid = 0;
810 }
811
812 if (top_region)
813 XDestroyRegion (top_region);
814 if (bottom_region)
815 XDestroyRegion (bottom_region);
816 if (left_region)
817 XDestroyRegion (left_region);
818 if (right_region)
819 XDestroyRegion (right_region);
820}
821
822static void
823meta_calc_button_size (decor_t *d)
824{
825 MetaTheme *theme;
826 MetaFrameType frame_type;
827 MetaFrameFlags flags;
828 MetaFrameGeometry fgeom;
829 MetaButtonLayout button_layout;
830 gint i, min_x, x, y, w, h, width;
831
832 if (!d->context)
833 {
834 d->button_width = 0;
835 return;
836 }
837
838 theme = meta_theme_get_current ();
839
840 frame_type = meta_frame_type_from_string (d->frame->type);
841 if (!(frame_type < META_FRAME_TYPE_LAST))
842 frame_type = META_FRAME_TYPE_NORMAL;
843
844 meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout,
845 frame_type);
846
847 width = d->border_layout.top.x2 - d->border_layout.top.x1 -
848 d->context->left_space - d->context->right_space +
849 fgeom.borders.total.left + fgeom.borders.total.right;
850
851 min_x = width;
852
853 for (i = 0; i < 3; ++i)
854 {
855 static guint button_actions[3] = {
856 WNCK_WINDOW_ACTION_CLOSE,
857 WNCK_WINDOW_ACTION_MAXIMIZE,
858 WNCK_WINDOW_ACTION_MINIMIZE
859 };
860
861 if (d->actions & button_actions[i])
862 {
863 if (meta_get_button_position (d, i, width, 256, &x, &y, &w, &h))
864 {
865 if (x > width / 2 && x < min_x)
866 min_x = x;
867 }
868 }
869 }
870
871 d->button_width = width - min_x;
872}
873
874static MetaButtonFunction
875button_to_meta_button_function (gint i)
876{
877 switch (i)
878 {
879 case BUTTON_MENU:
880 return META_BUTTON_FUNCTION_MENU;
881 case BUTTON_MIN:
882 return META_BUTTON_FUNCTION_MINIMIZE;
883 case BUTTON_MAX:
884 return META_BUTTON_FUNCTION_MAXIMIZE;
885 case BUTTON_CLOSE:
886 return META_BUTTON_FUNCTION_CLOSE;
887 case BUTTON_SHADE:
888 return META_BUTTON_FUNCTION_SHADE;
889 case BUTTON_ABOVE:
890 return META_BUTTON_FUNCTION_ABOVE;
891 case BUTTON_STICK:
892 return META_BUTTON_FUNCTION_STICK;
893 case BUTTON_UNSHADE:
894 return META_BUTTON_FUNCTION_UNSHADE;
895 case BUTTON_UNABOVE:
896 return META_BUTTON_FUNCTION_UNABOVE;
897 case BUTTON_UNSTICK:
898 return META_BUTTON_FUNCTION_UNSTICK;
899 default:
900 break;
901 }
902
903 return META_BUTTON_FUNCTION_LAST;
904}
905
906gboolean
907meta_get_button_position (decor_t *d,
908 gint i,
909 gint width,
910 gint height,
911 gint *x,
912 gint *y,
913 gint *w,
914 gint *h)
915{
916 MetaButtonLayout button_layout;
917 MetaFrameGeometry fgeom;
918 MetaFrameType frame_type;
919 MetaFrameFlags flags;
920 MetaTheme *theme;
921 MetaButtonFunction button_function;
922 MetaButtonSpace *space;
923
924 if (!d->context)
925 {
926 /* undecorated windows implicitly have no buttons */
927 return FALSE;
928 }
929
930 theme = meta_theme_get_current ();
931
932 frame_type = meta_frame_type_from_string (d->frame->type);
933 if (!(frame_type < META_FRAME_TYPE_LAST))
934 frame_type = META_FRAME_TYPE_NORMAL;
935
936 meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout,
937 frame_type);
938
939 button_function = button_to_meta_button_function (i);
940 if (!meta_button_present (&button_layout, button_function))
941 return FALSE;
942
943 switch (i)
944 {
945 case BUTTON_MENU:
946 space = &fgeom.menu_rect;
947 break;
948 case BUTTON_MIN:
949 space = &fgeom.min_rect;
950 break;
951 case BUTTON_MAX:
952 space = &fgeom.max_rect;
953 break;
954 case BUTTON_CLOSE:
955 space = &fgeom.close_rect;
956 break;
957 case BUTTON_SHADE:
958 space = &fgeom.shade_rect;
959 break;
960 case BUTTON_ABOVE:
961 space = &fgeom.above_rect;
962 break;
963 case BUTTON_STICK:
964 space = &fgeom.stick_rect;
965 break;
966 case BUTTON_UNSHADE:
967 space = &fgeom.unshade_rect;
968 break;
969 case BUTTON_UNABOVE:
970 space = &fgeom.unabove_rect;
971 break;
972 case BUTTON_UNSTICK:
973 space = &fgeom.unstick_rect;
974 break;
975 default:
976 return FALSE;
977 }
978
979 if (!space->clickable.width && !space->clickable.height)
980 return FALSE;
981
982 *x = space->clickable.x;
983 *y = space->clickable.y;
984 *w = space->clickable.width;
985 *h = space->clickable.height;
986
987 if (d->frame_window)
988 {
989 *x += d->frame->win_extents.left + 4;
990 *y += d->frame->win_extents.top + 2;
991 }
992
993 return TRUE;
994}
995
996gfloat
997meta_get_title_scale (decor_frame_t *frame)
998{
999 MetaTheme *theme;
1000 MetaFrameType type;
1001 MetaFrameFlags flags;
1002
1003 theme = meta_theme_get_current ();
1004 type = meta_frame_type_from_string (frame->type);
1005 flags = 0xc33; /* fixme */
1006
1007 if (type == META_FRAME_TYPE_LAST)
1008 return 1.0f;
1009
1010 gfloat scale = meta_theme_get_title_scale (theme, type, flags);
1011
1012 return scale;
1013}
1014
1015gboolean
1016meta_calc_decoration_size (decor_t *d,
1017 gint w,
1018 gint h,
1019 gint name_width,
1020 gint *width,
1021 gint *height)
1022{
1023 decor_layout_t layout;
1024 decor_context_t *context;
1025 decor_shadow_t *shadow;
1026
1027 if (!d->decorated)
1028 return FALSE;
1029
1030 if ((d->state & META_MAXIMIZED) == META_MAXIMIZED)
1031 {
1032 if (!d->frame_window)
1033 {
1034 if (d->active)
1035 {
1036 context = &d->frame->max_window_context_active;
1037 shadow = d->frame->max_border_shadow_active;
1038 }
1039 else
1040 {
1041 context = &d->frame->max_window_context_inactive;
1042 shadow = d->frame->max_border_shadow_inactive;
1043 }
1044 }
1045 else
1046 {
1047 context = &d->frame->max_window_context_no_shadow;
1048 shadow = d->frame->max_border_no_shadow;
1049 }
1050 }
1051 else
1052 {
1053 if (!d->frame_window)
1054 {
1055 if (d->active)
1056 {
1057 context = &d->frame->window_context_active;
1058 shadow = d->frame->border_shadow_active;
1059 }
1060 else
1061 {
1062 context = &d->frame->window_context_inactive;
1063 shadow = d->frame->border_shadow_inactive;
1064 }
1065 }
1066 else
1067 {
1068 context = &d->frame->window_context_no_shadow;
1069 shadow = d->frame->border_no_shadow;
1070 }
1071 }
1072
1073 if (!d->frame_window)
1074 {
1075 decor_get_best_layout (context, w, h, &layout);
1076
1077 if (context != d->context || memcmp (&layout, &d->border_layout, sizeof (layout)))
1078 {
1079 *width = layout.width;
1080 *height = layout.height;
1081
1082 d->border_layout = layout;
1083 d->context = context;
1084 d->shadow = shadow;
1085
1086 meta_calc_button_size (d);
1087
1088 return TRUE;
1089 }
1090 }
1091 else
1092 {
1093 if ((d->state & META_MAXIMIZED) == META_MAXIMIZED)
1094 decor_get_default_layout (context, d->client_width,
1095 d->client_height - d->frame->titlebar_height,
1096 &layout);
1097 else
1098 decor_get_default_layout (context, d->client_width,
1099 d->client_height, &layout);
1100
1101 *width = layout.width;
1102 *height = layout.height;
1103
1104 d->border_layout = layout;
1105 d->shadow = shadow;
1106 d->context = context;
1107
1108 meta_calc_button_size (d);
1109
1110 return TRUE;
1111 }
1112
1113 return FALSE;
1114}
1115
1116#define TOP_RESIZE_HEIGHT 2
1117#define RESIZE_EXTENDS 15
1118
1119void
1120meta_get_event_window_position (decor_t *d,
1121 gint i,
1122 gint j,
1123 gint width,
1124 gint height,
1125 gint *x,
1126 gint *y,
1127 gint *w,
1128 gint *h)
1129{
1130 MetaButtonLayout button_layout;
1131 MetaFrameGeometry fgeom;
1132 MetaFrameFlags flags;
1133 MetaTheme *theme;
1134
1135 theme = meta_theme_get_current ();
1136
1137 meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout,
1138 meta_frame_type_from_string (d->frame->type));
1139
1140 width += fgeom.borders.total.right + fgeom.borders.total.left;
1141 height += fgeom.borders.total.top + fgeom.borders.total.bottom;
1142
1143 switch (i)
1144 {
1145 case 2: /* bottom */
1146 switch (j)
1147 {
1148 case 2: /* bottom right */
1149 *x = width - fgeom.borders.total.right - RESIZE_EXTENDS;
1150 *y = height - fgeom.borders.total.bottom - RESIZE_EXTENDS;
1151
1152 if (d->frame_window)
1153 {
1154 *x += d->frame->win_extents.left + 2;
1155 *y += d->frame->win_extents.top + 2;
1156 }
1157
1158 *w = fgeom.borders.total.right + RESIZE_EXTENDS;
1159 *h = fgeom.borders.total.bottom + RESIZE_EXTENDS;
1160 break;
1161 case 1: /* bottom */
1162 *x = fgeom.borders.total.left + RESIZE_EXTENDS;
1163 *y = height - fgeom.borders.total.bottom;
1164
1165 if (d->frame_window)
1166 *y += d->frame->win_extents.top + 2;
1167
1168 *w = width - fgeom.borders.total.left - fgeom.borders.total.right - (2 * RESIZE_EXTENDS);
1169 *h = fgeom.borders.total.bottom;
1170 break;
1171 case 0: /* bottom left */
1172 default:
1173 *x = 0;
1174 *y = height - fgeom.borders.total.bottom - RESIZE_EXTENDS;
1175
1176 if (d->frame_window)
1177 {
1178 *x += d->frame->win_extents.left + 4;
1179 *y += d->frame->win_extents.bottom + 2;
1180 }
1181
1182 *w = fgeom.borders.total.left + RESIZE_EXTENDS;
1183 *h = fgeom.borders.total.bottom + RESIZE_EXTENDS;
1184 break;
1185 }
1186 break;
1187 case 1: /* middle */
1188 switch (j)
1189 {
1190 case 2: /* right */
1191 *x = width - fgeom.borders.total.right;
1192 *y = fgeom.borders.total.top + RESIZE_EXTENDS;
1193
1194 if (d->frame_window)
1195 *x += d->frame->win_extents.left + 2;
1196
1197 *w = fgeom.borders.total.right;
1198 *h = height - fgeom.borders.total.top - fgeom.borders.total.bottom - (2 * RESIZE_EXTENDS);
1199 break;
1200 case 1: /* middle */
1201 *x = fgeom.borders.total.left;
1202 *y = fgeom.title_rect.y + TOP_RESIZE_HEIGHT;
1203 *w = width - fgeom.borders.total.left - fgeom.borders.total.right;
1204 *h = height - fgeom.top_titlebar_edge - fgeom.borders.total.bottom;
1205 break;
1206 case 0: /* left */
1207 default:
1208 *x = 0;
1209 *y = fgeom.borders.total.top + RESIZE_EXTENDS;
1210
1211 if (d->frame_window)
1212 *x += d->frame->win_extents.left + 4;
1213
1214 *w = fgeom.borders.total.left;
1215 *h = height - fgeom.borders.total.top - fgeom.borders.total.bottom - (2 * RESIZE_EXTENDS);
1216 break;
1217 }
1218 break;
1219 case 0: /* top */
1220 default:
1221 switch (j)
1222 {
1223 case 2: /* top right */
1224 *x = width - fgeom.borders.total.right - RESIZE_EXTENDS;
1225 *y = 0;
1226
1227 if (d->frame_window)
1228 {
1229 *x += d->frame->win_extents.left + 2;
1230 *y += d->frame->win_extents.top + 2 - fgeom.title_rect.height;
1231 }
1232
1233 *w = fgeom.borders.total.right + RESIZE_EXTENDS;
1234 *h = fgeom.borders.total.top + RESIZE_EXTENDS;
1235 break;
1236 case 1: /* top */
1237 *x = fgeom.borders.total.left + RESIZE_EXTENDS;
1238 *y = 0;
1239
1240 if (d->frame_window)
1241 *y += d->frame->win_extents.top + 2;
1242
1243 *w = width - fgeom.borders.total.left - fgeom.borders.total.right - (2 * RESIZE_EXTENDS);
1244 *h = fgeom.borders.total.top - fgeom.title_rect.height;
1245 break;
1246 case 0: /* top left */
1247 default:
1248 *x = 0;
1249 *y = 0;
1250
1251 if (d->frame_window)
1252 {
1253 *x += d->frame->win_extents.left + 4;
1254 *y += d->frame->win_extents.top + 2 - fgeom.title_rect.height;
1255 }
1256
1257 *w = fgeom.borders.total.left + RESIZE_EXTENDS;
1258 *h = fgeom.borders.total.top + RESIZE_EXTENDS;
1259 break;
1260 }
1261 break;
1262 }
1263
1264 if (!(flags & META_FRAME_ALLOWS_VERTICAL_RESIZE))
1265 {
1266 /* turn off top and bottom event windows */
1267 if (i == 0 || i == 2)
1268 *w = *h = 0;
1269 }
1270
1271 if (!(flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE))
1272 {
1273 /* turn off left and right event windows */
1274 if (j == 0 || j == 2)
1275 *w = *h = 0;
1276 }
1277}
1278
1279static MetaButtonFunction
1280meta_button_function_from_string (const char *str)
1281{
1282 if (strcmp (str, "menu") == 0)
1283 return META_BUTTON_FUNCTION_MENU;
1284 else if (strcmp (str, "appmenu") == 0)
1285 return META_BUTTON_FUNCTION_APPMENU;
1286 else if (strcmp (str, "minimize") == 0)
1287 return META_BUTTON_FUNCTION_MINIMIZE;
1288 else if (strcmp (str, "maximize") == 0)
1289 return META_BUTTON_FUNCTION_MAXIMIZE;
1290 else if (strcmp (str, "close") == 0)
1291 return META_BUTTON_FUNCTION_CLOSE;
1292 else if (strcmp (str, "shade") == 0)
1293 return META_BUTTON_FUNCTION_SHADE;
1294 else if (strcmp (str, "above") == 0)
1295 return META_BUTTON_FUNCTION_ABOVE;
1296 else if (strcmp (str, "stick") == 0)
1297 return META_BUTTON_FUNCTION_STICK;
1298 else if (strcmp (str, "unshade") == 0)
1299 return META_BUTTON_FUNCTION_UNSHADE;
1300 else if (strcmp (str, "unabove") == 0)
1301 return META_BUTTON_FUNCTION_UNABOVE;
1302 else if (strcmp (str, "unstick") == 0)
1303 return META_BUTTON_FUNCTION_UNSTICK;
1304 else
1305 return META_BUTTON_FUNCTION_LAST;
1306}
1307
1308static MetaButtonFunction
1309meta_button_opposite_function (MetaButtonFunction ofwhat)
1310{
1311 switch (ofwhat)
1312 {
1313 case META_BUTTON_FUNCTION_SHADE:
1314 return META_BUTTON_FUNCTION_UNSHADE;
1315 case META_BUTTON_FUNCTION_UNSHADE:
1316 return META_BUTTON_FUNCTION_SHADE;
1317
1318 case META_BUTTON_FUNCTION_ABOVE:
1319 return META_BUTTON_FUNCTION_UNABOVE;
1320 case META_BUTTON_FUNCTION_UNABOVE:
1321 return META_BUTTON_FUNCTION_ABOVE;
1322
1323 case META_BUTTON_FUNCTION_STICK:
1324 return META_BUTTON_FUNCTION_UNSTICK;
1325 case META_BUTTON_FUNCTION_UNSTICK:
1326 return META_BUTTON_FUNCTION_STICK;
1327
1328 default:
1329 return META_BUTTON_FUNCTION_LAST;
1330 }
1331}
1332
1333static void
1334meta_initialize_button_layout (MetaButtonLayout *layout)
1335{
1336 int i;
1337
1338 for (i = 0; i < MAX_BUTTONS_PER_CORNER; ++i)
1339 {
1340 layout->left_buttons[i] = META_BUTTON_FUNCTION_LAST;
1341 layout->right_buttons[i] = META_BUTTON_FUNCTION_LAST;
1342 layout->left_buttons_has_spacer[i] = FALSE;
1343 layout->right_buttons_has_spacer[i] = FALSE;
1344 }
1345}
1346
1347void
1348meta_update_button_layout (const char *value)
1349{
1350 MetaButtonLayout new_layout;
1351 MetaButtonFunction f;
1352 char **sides;
1353 int i;
1354
1355 meta_initialize_button_layout (&new_layout);
1356
1357 sides = g_strsplit (value, ":", 2);
1358
1359 if (sides[0] != NULL)
1360 {
1361 char **buttons;
1362 int b;
1363 gboolean used[META_BUTTON_FUNCTION_LAST];
1364
1365 for (i = 0; i < META_BUTTON_FUNCTION_LAST; ++i)
1366 used[i] = FALSE;
1367
1368 buttons = g_strsplit (sides[0], ",", -1);
1369
1370 i = b = 0;
1371 while (buttons[b] != NULL)
1372 {
1373 f = meta_button_function_from_string (buttons[b]);
1374 if (i > 0 && strcmp ("spacer", buttons[b]) == 0)
1375 {
1376 new_layout.left_buttons_has_spacer[i - 1] = TRUE;
1377 f = meta_button_opposite_function (f);
1378
1379 if (f != META_BUTTON_FUNCTION_LAST)
1380 new_layout.left_buttons_has_spacer[i - 2] = TRUE;
1381 }
1382 else
1383 {
1384 if (f != META_BUTTON_FUNCTION_LAST && !used[f])
1385 {
1386 used[f] = TRUE;
1387 new_layout.left_buttons[i++] = f;
1388
1389 f = meta_button_opposite_function (f);
1390
1391 if (f != META_BUTTON_FUNCTION_LAST)
1392 new_layout.left_buttons[i++] = f;
1393
1394 }
1395 else
1396 {
1397 fprintf (stderr, "%s: Ignoring unknown or already-used "
1398 "button name \"%s\"\n", program_name, buttons[b]);
1399 }
1400 }
1401 ++b;
1402 }
1403
1404 new_layout.left_buttons[i] = META_BUTTON_FUNCTION_LAST;
1405
1406 g_strfreev (buttons);
1407
1408 if (sides[1] != NULL)
1409 {
1410 for (i = 0; i < META_BUTTON_FUNCTION_LAST; ++i)
1411 used[i] = FALSE;
1412
1413 buttons = g_strsplit (sides[1], ",", -1);
1414
1415 i = b = 0;
1416 while (buttons[b] != NULL)
1417 {
1418 f = meta_button_function_from_string (buttons[b]);
1419 if (i > 0 && strcmp ("spacer", buttons[b]) == 0)
1420 {
1421 new_layout.right_buttons_has_spacer[i - 1] = TRUE;
1422 f = meta_button_opposite_function (f);
1423 if (f != META_BUTTON_FUNCTION_LAST)
1424 new_layout.right_buttons_has_spacer[i - 2] = TRUE;
1425 }
1426 else
1427 {
1428 if (f != META_BUTTON_FUNCTION_LAST && !used[f])
1429 {
1430 used[f] = TRUE;
1431 new_layout.right_buttons[i++] = f;
1432
1433 f = meta_button_opposite_function (f);
1434
1435 if (f != META_BUTTON_FUNCTION_LAST)
1436 new_layout.right_buttons[i++] = f;
1437 }
1438 else
1439 {
1440 fprintf (stderr, "%s: Ignoring unknown or "
1441 "already-used button name \"%s\"\n",
1442 program_name, buttons[b]);
1443 }
1444 }
1445 ++b;
1446 }
1447
1448 new_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST;
1449
1450 g_strfreev (buttons);
1451 }
1452 }
1453
1454 g_strfreev (sides);
1455
1456 /* Invert the button layout for RTL languages */
1457 if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
1458 {
1459 MetaButtonLayout rtl_layout;
1460 int j;
1461
1462 meta_initialize_button_layout (&rtl_layout);
1463
1464 i = 0;
1465 while (new_layout.left_buttons[i] != META_BUTTON_FUNCTION_LAST)
1466 ++i;
1467
1468 for (j = 0; j < i; ++j)
1469 {
1470 rtl_layout.right_buttons[j] = new_layout.left_buttons[i - j - 1];
1471 if (j == 0)
1472 rtl_layout.right_buttons_has_spacer[i - 1] = new_layout.left_buttons_has_spacer[i - j - 1];
1473 else
1474 rtl_layout.right_buttons_has_spacer[j - 1] = new_layout.left_buttons_has_spacer[i - j - 1];
1475 }
1476
1477 i = 0;
1478 while (new_layout.right_buttons[i] != META_BUTTON_FUNCTION_LAST)
1479 ++i;
1480
1481 for (j = 0; j < i; ++j)
1482 {
1483 rtl_layout.left_buttons[j] = new_layout.right_buttons[i - j - 1];
1484 if (j == 0)
1485 rtl_layout.left_buttons_has_spacer[i - 1] = new_layout.right_buttons_has_spacer[i - j - 1];
1486 else
1487 rtl_layout.left_buttons_has_spacer[j - 1] = new_layout.right_buttons_has_spacer[i - j - 1];
1488 }
1489
1490 new_layout = rtl_layout;
1491 }
1492
1493 meta_button_layout = new_layout;
1494}
1495
1496void
1497meta_update_border_extents (decor_frame_t *frame)
1498{
1499 MetaTheme *theme;
1500 GdkScreen *screen;
1501 MetaStyleInfo *style_info;
1502 MetaFrameBorders borders;
1503 MetaFrameType frame_type;
1504 gint top_height;
1505 gint bottom_height;
1506 gint left_width;
1507 gint right_width;
1508
1509 gwd_decor_frame_ref (frame);
1510
1511 frame_type = meta_frame_type_from_string (frame->type);
1512 if (!(frame_type < META_FRAME_TYPE_LAST))
1513 frame_type = META_FRAME_TYPE_NORMAL;
1514
1515 theme = meta_theme_get_current ();
1516
1517 screen = gtk_widget_get_screen (frame->style_window_rgba);
1518 style_info = meta_theme_create_style_info (screen, NULL);
1519
1520 meta_theme_get_frame_borders (theme, style_info, frame_type, frame->text_height,
1521 0, &borders);
1522
1523 top_height = borders.visible.top;
1524 bottom_height = borders.visible.bottom;
1525 left_width = borders.visible.left;
1526 right_width = borders.visible.right;
1527
1528 frame->win_extents.top = frame->win_extents.top;
1529 frame->win_extents.bottom = bottom_height;
1530 frame->win_extents.left = left_width;
1531 frame->win_extents.right = right_width;
1532
1533 frame->titlebar_height = top_height - frame->win_extents.top;
1534
1535 meta_theme_get_frame_borders (theme, style_info, frame_type, frame->text_height,
1536 META_FRAME_MAXIMIZED, &borders);
1537
1538 top_height = borders.visible.top;
1539 bottom_height = borders.visible.bottom;
1540 left_width = borders.visible.left;
1541 right_width = borders.visible.right;
1542
1543 frame->max_win_extents.top = frame->win_extents.top;
1544 frame->max_win_extents.bottom = bottom_height;
1545 frame->max_win_extents.left = left_width;
1546 frame->max_win_extents.right = right_width;
1547
1548 frame->max_titlebar_height = top_height - frame->max_win_extents.top;
1549
1550 meta_style_info_unref (style_info);
1551
1552 gwd_decor_frame_unref (frame);
1553}
1554
1555#endif
01556
=== modified file 'plugins/grid/src/grid.cpp'
=== modified file 'plugins/opengl/src/paint.cpp'

Subscribers

People subscribed via source and target branches

to all changes: