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