diff options
author | Charles Bos | 2015-06-09 12:47:28 +0100 |
---|---|---|
committer | Charles Bos | 2015-06-09 12:47:28 +0100 |
commit | a0427ba34d116c66325a5b45f2f1e16401282773 (patch) | |
tree | d622f837bb4c316cf65bd809819ef630a5913b0e | |
download | aur-a0427ba34d116c66325a5b45f2f1e16401282773.tar.gz |
Initial commit
-rw-r--r-- | .SRCINFO | 49 | ||||
-rw-r--r-- | PKGBUILD | 102 | ||||
-rw-r--r-- | compiz.install | 35 | ||||
-rw-r--r-- | focus-prevention-disable.patch | 12 | ||||
-rw-r--r-- | metacity-3_16.patch | 6172 | ||||
-rw-r--r-- | set-gwd-default.patch | 12 |
6 files changed, 6382 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO new file mode 100644 index 000000000000..3f44b7a919ec --- /dev/null +++ b/.SRCINFO @@ -0,0 +1,49 @@ +# Generated by makepkg 4.2.1 +# Sat Apr 11 15:05:49 UTC 2015 +pkgbase = compiz + pkgdesc = Composite manager for Aiglx and Xgl, with plugins and CCSM (release version) + pkgver = 0.9.12.1 + pkgrel = 4 + url = https://launchpad.net/compiz + install = compiz.install + arch = i686 + arch = x86_64 + license = GPL + license = LGPL + license = MIT + makedepends = cmake + makedepends = intltool + depends = boost + depends = xorg-server + depends = libxcomposite + depends = startup-notification + depends = librsvg + depends = dbus + depends = mesa + depends = libxslt + depends = fuse + depends = glibmm + depends = libxrender + depends = libwnck3 + depends = pygtk + depends = desktop-file-utils + depends = pyrex + depends = protobuf + depends = metacity>=3.16.0 + depends = glu + depends = libsm + depends = dconf + optdepends = xorg-xprop: grab various window properties for use in window matching rules + conflicts = compiz-core + replaces = compiz-core-devel + source = https://launchpad.net/compiz/0.9.12/0.9.12.1/+download/compiz-0.9.12.1.tar.bz2 + source = set-gwd-default.patch + source = focus-prevention-disable.patch + source = metacity-3_16.patch + sha256sums = 8b9d6a72c581c96b820dff182669864aeb8fd1989e95ff56a73203fc478d854e + sha256sums = 3aa6cb70f357b3d34d51735f4b5bcb0479086d7c7336de4bd8157569d6c52c08 + sha256sums = f4897590b0f677ba34767a29822f8f922a750daf66e8adf47be89f7c2550cf4b + sha256sums = 27e7c516c22947a28bb1f34ecc63142fc1a6b8178439a04660f7ae0968bdc57c + +pkgname = compiz + diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 000000000000..c14a233b7eea --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,102 @@ +# Maintainer: Charles Bos <charlesbos1 AT gmail> +# Contributor: Rob McCathie <archaur at rmcc dot com dot au +# Contributor: /dev/rs0 <rs0@secretco.de.com> +# Contributor: Iven Hsu <ivenvd AT gmail> +# Contributor: Nathan Hulse <nat.hulse@gmail.com> + +pkgname=compiz +pkgver=0.9.12.1 +_pkgseries=0.9.12 +pkgrel=4 +pkgdesc="Composite manager for Aiglx and Xgl, with plugins and CCSM (release version)" +arch=('i686' 'x86_64') +url="https://launchpad.net/compiz" +license=('GPL' 'LGPL' 'MIT') +depends=('boost' 'xorg-server' 'libxcomposite' 'startup-notification' 'librsvg' 'dbus' 'mesa' 'libxslt' 'fuse' 'glibmm' 'libxrender' 'libwnck3' 'pygtk' 'desktop-file-utils' 'pyrex' 'protobuf' 'metacity>=3.16.0' 'glu' 'libsm' 'dconf') +makedepends=('cmake' 'intltool') +optdepends=( + 'xorg-xprop: grab various window properties for use in window matching rules' +) +conflicts=('compiz-core') +replaces=('compiz-core-devel') +source=("https://launchpad.net/compiz/${_pkgseries}/${pkgver}/+download/compiz-${pkgver}.tar.bz2" + "set-gwd-default.patch" + "focus-prevention-disable.patch" + "metacity-3_16.patch") +sha256sums=('8b9d6a72c581c96b820dff182669864aeb8fd1989e95ff56a73203fc478d854e' + '3aa6cb70f357b3d34d51735f4b5bcb0479086d7c7336de4bd8157569d6c52c08' + 'f4897590b0f677ba34767a29822f8f922a750daf66e8adf47be89f7c2550cf4b' + '27e7c516c22947a28bb1f34ecc63142fc1a6b8178439a04660f7ae0968bdc57c') +install='compiz.install' + +prepare() { + cd "compiz-${pkgver}" + + # Set gtk-window-decorator as default in the Window Decoration plugin + patch -Np1 -i "${srcdir}/set-gwd-default.patch" + + # Set focus prevention level to off which means that new windows will always get focus + patch -Np1 -i "${srcdir}/focus-prevention-disable.patch" + + find -type f \( -name 'CMakeLists.txt' -or -name '*.cmake' \) -exec sed -e 's/COMMAND python/COMMAND python2/g' -i {} \; + find compizconfig/ccsm -type f -exec sed -e 's|^#!.*python|#!/usr/bin/env python2|g' -i {} \; + + # Fix Python build directory with CMake 3.2 + sed -i 's/${PY_BUILD_DIR}/lib/g' compizconfig/ccsm/CMakeLists.txt + + # Metacity 3.16 compatibility + patch -Np1 -i "${srcdir}/metacity-3_16.patch" +} + +build() { + cd "compiz-${pkgver}" + + export PYTHON="/usr/bin/python2" + + mkdir build; cd build + + cmake .. \ + -DCMAKE_BUILD_TYPE="Release" \ + -DCMAKE_INSTALL_PREFIX="/usr" \ + -DCMAKE_INSTALL_LIBDIR="/usr/lib" \ + -DPYTHON_INCLUDE_DIR=/usr/include/python2.7 \ + -DPYTHON_LIBRARY=/usr/lib/libpython2.7.so \ + -DQT_QMAKE_EXECUTABLE=qmake-qt4 \ + -DCOMPIZ_DISABLE_SCHEMAS_INSTALL=On \ + -DCOMPIZ_BUILD_WITH_RPATH=Off \ + -DCOMPIZ_PACKAGING_ENABLED=On \ + -DBUILD_GTK=On \ + -DBUILD_METACITY=On \ + -DBUILD_KDE4=Off \ + -DUSE_GCONF=Off \ + -DUSE_GSETTINGS=On \ + -DCOMPIZ_BUILD_TESTING=Off \ + -DCOMPIZ_WERROR=Off \ + -DCOMPIZ_DEFAULT_PLUGINS="composite,opengl,decor,resize,place,move,ccp" + + make +} + +package() { + cd "compiz-${pkgver}/build" + make DESTDIR="${pkgdir}" install + + # findcompiz_install needs COMPIZ_DESTDIR and install needs DESTDIR + # make findcompiz_install + CMAKE_DIR=$(cmake --system-information | grep '^CMAKE_ROOT' | awk -F\" '{print $2}') + install -dm755 "${pkgdir}${CMAKE_DIR}/Modules/" + install -m644 ../cmake/FindCompiz.cmake "${pkgdir}${CMAKE_DIR}/Modules/" + + # Add documentation + install -dm755 "${pkgdir}/usr/share/doc/compiz/" + install ../{AUTHORS,NEWS,README} "${pkgdir}/usr/share/doc/compiz/" + + # Add the gsettings schema files + if ls generated/glib-2.0/schemas/ | grep -qm1 .gschema.xml; then + install -dm755 "${pkgdir}/usr/share/glib-2.0/schemas/" + install -m644 generated/glib-2.0/schemas/*.gschema.xml "${pkgdir}/usr/share/glib-2.0/schemas/" + fi + + # Remove GConf schemas + rm -rv "${pkgdir}/usr/share/gconf/" +} diff --git a/compiz.install b/compiz.install new file mode 100644 index 000000000000..4c346d149f62 --- /dev/null +++ b/compiz.install @@ -0,0 +1,35 @@ +post_install() { + echo " -> Updating icon cache..." + gtk-update-icon-cache -q -f -t /usr/share/icons/hicolor + echo " -> Updating XDG menu database..." + update-desktop-database -q + + ls /usr/share/glib-2.0/schemas 2>/dev/null | grep -qm1 org.compiz + if [ $? -eq 0 ]; then + echo " -> Recompiling the GSettings database... " + glib-compile-schemas /usr/share/glib-2.0/schemas + fi +} + +pre_upgrade() { + if [ -f /usr/share/gconf/schemas/compiz.schemas ]; then + echo " -> Uninstalling GConf schemas... " + gconfpkg --uninstall compiz + fi +} + +post_upgrade() { + post_install $1 +} + +post_remove() { + echo " -> Updating icon cache..." + gtk-update-icon-cache -q -f -t /usr/share/icons/hicolor + echo " -> Updating XDG menu database..." + update-desktop-database -q + + if [ -d /usr/share/glib-2.0/schemas ]; then + echo " -> Recompiling the GSettings database... " + glib-compile-schemas /usr/share/glib-2.0/schemas + fi +} diff --git a/focus-prevention-disable.patch b/focus-prevention-disable.patch new file mode 100644 index 000000000000..df2fcef106db --- /dev/null +++ b/focus-prevention-disable.patch @@ -0,0 +1,12 @@ +diff -Naur original/metadata/core.xml.in modified/metadata/core.xml.in +--- original/metadata/core.xml.in 2013-07-23 20:58:03.000000000 +0100 ++++ modified/metadata/core.xml.in 2014-06-11 09:06:53.839302487 +0100 +@@ -114,7 +114,7 @@ + <_long>Level of focus stealing prevention</_long> + <min>0</min> + <max>4</max> +- <default>1</default> ++ <default>0</default> + <desc> + <value>0</value> + <_name>Off</_name> diff --git a/metacity-3_16.patch b/metacity-3_16.patch new file mode 100644 index 000000000000..150a7362e239 --- /dev/null +++ b/metacity-3_16.patch @@ -0,0 +1,6172 @@ +diff -Nur original/gtk/CMakeLists.txt modified/gtk/CMakeLists.txt +--- original/gtk/CMakeLists.txt 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/CMakeLists.txt 2015-04-11 14:34:11.000000000 +0100 +@@ -28,6 +28,7 @@ + pkg_check_modules (METACITY libmetacity-private>=3.12.0) + if (METACITY_FOUND) + compiz_pkg_check_modules (HAVE_METACITY_3_14_0 libmetacity-private>=3.14.0) ++ compiz_pkg_check_modules (HAVE_METACITY_3_16_0 libmetacity-private>=3.16.0) + else (METACITY_FOUND) + compiz_set (USE_METACITY 0) + endif (METACITY_FOUND) +diff -Nur original/gtk/config.h.gtk.in modified/gtk/config.h.gtk.in +--- original/gtk/config.h.gtk.in 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/config.h.gtk.in 2015-04-11 14:34:11.000000000 +0100 +@@ -4,4 +4,7 @@ + /* Define to 1 if metacity version >= 3.14.0 */ + #cmakedefine HAVE_METACITY_3_14_0 1 + ++/* Define to 1 if metacity version >= 3.16.0 */ ++#cmakedefine HAVE_METACITY_3_16_0 1 ++ + #define GETTEXT_PACKAGE "${GETTEXT_PACKAGE}" +diff -Nur original/gtk/window-decorator/cairo.c modified/gtk/window-decorator/cairo.c +--- original/gtk/window-decorator/cairo.c 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/cairo.c 2015-04-11 14:34:11.000000000 +0100 +@@ -26,6 +26,8 @@ + #include "gtk-window-decorator.h" + #include "gwd-cairo-window-decoration-util.h" + ++#define STROKE_ALPHA 0.6f ++ + void + rounded_rectangle (cairo_t *cr, + double x, +diff -Nur original/gtk/window-decorator/CMakeLists.txt modified/gtk/window-decorator/CMakeLists.txt +--- original/gtk/window-decorator/CMakeLists.txt 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/CMakeLists.txt 2015-04-11 14:34:11.000000000 +0100 +@@ -99,6 +99,7 @@ + gdk.c + switcher.c + metacity.c ++ metacity-3-16.c + events.c + forcequit.c + tooltip.c +@@ -138,6 +139,3 @@ + endif (COMPIZ_BUILD_TESTING) + + endif (USE_GTK) +- +- +- +diff -Nur original/gtk/window-decorator/decorator.c modified/gtk/window-decorator/decorator.c +--- original/gtk/window-decorator/decorator.c 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/decorator.c 2015-04-11 14:34:11.000000000 +0100 +@@ -25,83 +25,12 @@ + + #include "gtk-window-decorator.h" + +-decor_frame_t * +-create_normal_frame (const gchar *type) +-{ +- decor_frame_t *frame = decor_frame_new (type); +- +- decor_context_t _window_context = { +- { 0, 0, 0, 0 }, +- 6, 6, 4, 6, +- 0, 0, 0, 0 +- }; +- +- decor_context_t _max_window_context = { +- { 0, 0, 0, 0 }, +- 6, 6, 4, 6, +- 0, 0, 0, 0 +- }; +- +- decor_context_t _window_context_no_shadow = { +- { 0, 0, 0, 0 }, +- 6, 6, 4, 6, +- 0, 0, 0, 0 +- }; +- +- decor_context_t _max_window_context_no_shadow = { +- { 0, 0, 0, 0 }, +- 6, 6, 4, 6, +- 0, 0, 0, 0 +- }; +- +- decor_extents_t _win_extents = { 6, 6, 6, 6 }; +- decor_extents_t _max_win_extents = { 6, 6, 4, 6 }; +- +- frame->win_extents = _win_extents; +- frame->max_win_extents = _max_win_extents; +- frame->update_shadow = decor_frame_update_shadow; +- frame->window_context_active = _window_context; +- frame->window_context_inactive = _window_context; +- frame->window_context_no_shadow = _window_context_no_shadow; +- frame->max_window_context_active = _max_window_context; +- frame->max_window_context_inactive = _max_window_context; +- frame->max_window_context_no_shadow = _max_window_context_no_shadow; +- +- return frame; +-} +- + void + destroy_normal_frame (decor_frame_t *frame) + { + decor_frame_destroy (frame); + } + +-decor_frame_t * +-create_bare_frame (const gchar *type) +-{ +- decor_frame_t *frame = decor_frame_new (type); +- decor_context_t _shadow_context = { +- { 0, 0, 0, 0 }, +- 0, 0, 0, 0, +- 0, 0, 0, 0, +- }; +- +- decor_extents_t _shadow_extents = { 0, 0, 0, 0 }; +- +- frame->win_extents = _shadow_extents; +- frame->max_win_extents = _shadow_extents; +- frame->win_extents = _shadow_extents; +- frame->window_context_active = _shadow_context; +- frame->window_context_inactive = _shadow_context; +- frame->window_context_no_shadow = _shadow_context; +- frame->max_window_context_active = _shadow_context; +- frame->max_window_context_inactive = _shadow_context; +- frame->max_window_context_no_shadow = _shadow_context; +- frame->update_shadow = bare_frame_update_shadow; +- +- return frame; +-} +- + void + destroy_bare_frame (decor_frame_t *frame) + { +@@ -411,7 +340,7 @@ + * the window name using pango (with 6px padding) + * Returns zero if window has no name. + */ +-gint ++static gint + max_window_name_width (WnckWindow *win) + { + decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); +@@ -453,7 +382,7 @@ + * wnck. Also checks to see if the name has a length (slight optimization) + * and re-creates the pango context to re-render the name + */ +-void ++static void + update_window_decoration_name (WnckWindow *win) + { + decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); +@@ -823,7 +752,7 @@ + * + * We do something similar for the maximimzed mode as well + */ +-void ++static void + bare_frame_update_shadow (Display *xdisplay, + Screen *screen, + decor_frame_t *frame, +@@ -894,7 +823,7 @@ + NULL); + } + +-void ++static void + decor_frame_update_shadow (Display *xdisplay, + Screen *screen, + decor_frame_t *frame, +@@ -1507,3 +1436,74 @@ + cairo_set_source_surface (d->cr, d->buffer_surface, 0, 0); + cairo_paint (d->cr); + } ++ ++decor_frame_t * ++create_bare_frame (const gchar *type) ++{ ++ decor_frame_t *frame = decor_frame_new (type); ++ decor_context_t _shadow_context = { ++ { 0, 0, 0, 0 }, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ }; ++ ++ decor_extents_t _shadow_extents = { 0, 0, 0, 0 }; ++ ++ frame->win_extents = _shadow_extents; ++ frame->max_win_extents = _shadow_extents; ++ frame->win_extents = _shadow_extents; ++ frame->window_context_active = _shadow_context; ++ frame->window_context_inactive = _shadow_context; ++ frame->window_context_no_shadow = _shadow_context; ++ frame->max_window_context_active = _shadow_context; ++ frame->max_window_context_inactive = _shadow_context; ++ frame->max_window_context_no_shadow = _shadow_context; ++ frame->update_shadow = bare_frame_update_shadow; ++ ++ return frame; ++} ++ ++decor_frame_t * ++create_normal_frame (const gchar *type) ++{ ++ decor_frame_t *frame = decor_frame_new (type); ++ ++ decor_context_t _window_context = { ++ { 0, 0, 0, 0 }, ++ 6, 6, 4, 6, ++ 0, 0, 0, 0 ++ }; ++ ++ decor_context_t _max_window_context = { ++ { 0, 0, 0, 0 }, ++ 6, 6, 4, 6, ++ 0, 0, 0, 0 ++ }; ++ ++ decor_context_t _window_context_no_shadow = { ++ { 0, 0, 0, 0 }, ++ 6, 6, 4, 6, ++ 0, 0, 0, 0 ++ }; ++ ++ decor_context_t _max_window_context_no_shadow = { ++ { 0, 0, 0, 0 }, ++ 6, 6, 4, 6, ++ 0, 0, 0, 0 ++ }; ++ ++ decor_extents_t _win_extents = { 6, 6, 6, 6 }; ++ decor_extents_t _max_win_extents = { 6, 6, 4, 6 }; ++ ++ frame->win_extents = _win_extents; ++ frame->max_win_extents = _max_win_extents; ++ frame->update_shadow = decor_frame_update_shadow; ++ frame->window_context_active = _window_context; ++ frame->window_context_inactive = _window_context; ++ frame->window_context_no_shadow = _window_context_no_shadow; ++ frame->max_window_context_active = _max_window_context; ++ frame->max_window_context_inactive = _max_window_context; ++ frame->max_window_context_no_shadow = _max_window_context_no_shadow; ++ ++ return frame; ++} +diff -Nur original/gtk/window-decorator/events.c modified/gtk/window-decorator/events.c +--- original/gtk/window-decorator/events.c 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/events.c 2015-04-11 14:34:11.000000000 +0100 +@@ -26,7 +26,34 @@ + #include "gtk-window-decorator.h" + #include "gwd-settings-interface.h" + +-void ++#define DOUBLE_CLICK_DISTANCE 8.0f ++ ++#define WM_MOVERESIZE_SIZE_TOPLEFT 0 ++#define WM_MOVERESIZE_SIZE_TOP 1 ++#define WM_MOVERESIZE_SIZE_TOPRIGHT 2 ++#define WM_MOVERESIZE_SIZE_RIGHT 3 ++#define WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4 ++#define WM_MOVERESIZE_SIZE_BOTTOM 5 ++#define WM_MOVERESIZE_SIZE_BOTTOMLEFT 6 ++#define WM_MOVERESIZE_SIZE_LEFT 7 ++#define WM_MOVERESIZE_MOVE 8 ++#define WM_MOVERESIZE_SIZE_KEYBOARD 9 ++#define WM_MOVERESIZE_MOVE_KEYBOARD 10 ++ ++static double ++square (double x) ++{ ++ return x * x; ++} ++ ++static double ++dist (double x1, double y1, ++ double x2, double y2) ++{ ++ return sqrt (square (x1 - x2) + square (y1 - y2)); ++} ++ ++static void + move_resize_window (WnckWindow *win, + int direction, + decor_event *gtkwd_event) +@@ -74,7 +101,7 @@ + XSync (xdisplay, FALSE); + } + +-void ++static void + common_button_event (WnckWindow *win, + decor_event *gtkwd_event, + decor_event_type gtkwd_type, +@@ -392,7 +419,7 @@ + } + } + +-void ++static void + handle_title_button_event (WnckWindow *win, + int action, + decor_event *gtkwd_event) +@@ -426,7 +453,7 @@ + } + } + +-void ++static void + handle_mouse_wheel_title_event (WnckWindow *win, + unsigned int button) + { +@@ -526,7 +553,7 @@ + } + } + +-void ++static void + frame_common_event (WnckWindow *win, + int direction, + decor_event *gtkwd_event, +@@ -684,7 +711,7 @@ + } + } + +-event_callback ++static event_callback + find_event_callback_for_point (decor_t *d, + int x, + int y, +@@ -739,7 +766,7 @@ + return NULL; + } + +-event_callback ++static event_callback + find_leave_event_callback (decor_t *d) + { + int i, j; +diff -Nur original/gtk/window-decorator/frames.c modified/gtk/window-decorator/frames.c +--- original/gtk/window-decorator/frames.c 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/frames.c 2015-04-11 14:34:11.000000000 +0100 +@@ -31,6 +31,192 @@ + GHashTable *frame_info_table; + GHashTable *frames_table; + ++/* from clearlooks theme */ ++static void ++rgb_to_hls (gdouble *r, ++ gdouble *g, ++ gdouble *b) ++{ ++ gdouble min; ++ gdouble max; ++ gdouble red; ++ gdouble green; ++ gdouble blue; ++ gdouble h, l, s; ++ gdouble delta; ++ ++ red = *r; ++ green = *g; ++ blue = *b; ++ ++ if (red > green) ++ { ++ if (red > blue) ++ max = red; ++ else ++ max = blue; ++ ++ if (green < blue) ++ min = green; ++ else ++ min = blue; ++ } ++ else ++ { ++ if (green > blue) ++ max = green; ++ else ++ max = blue; ++ ++ if (red < blue) ++ min = red; ++ else ++ min = blue; ++ } ++ ++ l = (max + min) / 2; ++ s = 0; ++ h = 0; ++ ++ if (max != min) ++ { ++ if (l <= 0.5) ++ s = (max - min) / (max + min); ++ else ++ s = (max - min) / (2 - max - min); ++ ++ delta = max -min; ++ if (red == max) ++ h = (green - blue) / delta; ++ else if (green == max) ++ h = 2 + (blue - red) / delta; ++ else if (blue == max) ++ h = 4 + (red - green) / delta; ++ ++ h *= 60; ++ if (h < 0.0) ++ h += 360; ++ } ++ ++ *r = h; ++ *g = l; ++ *b = s; ++} ++ ++static void ++hls_to_rgb (gdouble *h, ++ gdouble *l, ++ gdouble *s) ++{ ++ gdouble hue; ++ gdouble lightness; ++ gdouble saturation; ++ gdouble m1, m2; ++ gdouble r, g, b; ++ ++ lightness = *l; ++ saturation = *s; ++ ++ if (lightness <= 0.5) ++ m2 = lightness * (1 + saturation); ++ else ++ m2 = lightness + saturation - lightness * saturation; ++ ++ m1 = 2 * lightness - m2; ++ ++ if (saturation == 0) ++ { ++ *h = lightness; ++ *l = lightness; ++ *s = lightness; ++ } ++ else ++ { ++ hue = *h + 120; ++ while (hue > 360) ++ hue -= 360; ++ while (hue < 0) ++ hue += 360; ++ ++ if (hue < 60) ++ r = m1 + (m2 - m1) * hue / 60; ++ else if (hue < 180) ++ r = m2; ++ else if (hue < 240) ++ r = m1 + (m2 - m1) * (240 - hue) / 60; ++ else ++ r = m1; ++ ++ hue = *h; ++ while (hue > 360) ++ hue -= 360; ++ while (hue < 0) ++ hue += 360; ++ ++ if (hue < 60) ++ g = m1 + (m2 - m1) * hue / 60; ++ else if (hue < 180) ++ g = m2; ++ else if (hue < 240) ++ g = m1 + (m2 - m1) * (240 - hue) / 60; ++ else ++ g = m1; ++ ++ hue = *h - 120; ++ while (hue > 360) ++ hue -= 360; ++ while (hue < 0) ++ hue += 360; ++ ++ if (hue < 60) ++ b = m1 + (m2 - m1) * hue / 60; ++ else if (hue < 180) ++ b = m2; ++ else if (hue < 240) ++ b = m1 + (m2 - m1) * (240 - hue) / 60; ++ else ++ b = m1; ++ ++ *h = r; ++ *l = g; ++ *s = b; ++ } ++} ++ ++static void ++shade (const decor_color_t *a, ++ decor_color_t *b, ++ float k) ++{ ++ double red; ++ double green; ++ double blue; ++ ++ red = a->r; ++ green = a->g; ++ blue = a->b; ++ ++ rgb_to_hls (&red, &green, &blue); ++ ++ green *= k; ++ if (green > 1.0) ++ green = 1.0; ++ else if (green < 0.0) ++ green = 0.0; ++ ++ blue *= k; ++ if (blue > 1.0) ++ blue = 1.0; ++ else if (blue < 0.0) ++ blue = 0.0; ++ ++ hls_to_rgb (&red, &green, &blue); ++ ++ b->r = red; ++ b->g = green; ++ b->b = blue; ++} ++ + static void + update_style (GtkWidget *widget) + { +diff -Nur original/gtk/window-decorator/gtk-window-decorator.c modified/gtk/window-decorator/gtk-window-decorator.c +--- original/gtk/window-decorator/gtk-window-decorator.c 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/gtk-window-decorator.c 2015-04-11 14:34:11.000000000 +0100 +@@ -36,29 +36,13 @@ + + gdouble decoration_alpha = 0.5; + #ifdef USE_METACITY +-MetaButtonLayout meta_button_layout; + gboolean meta_button_layout_set = FALSE; + #endif + + gboolean minimal = FALSE; + +-#define SWITCHER_SPACE 40 +- +-const float STROKE_ALPHA = 0.6f; +- + const unsigned short ICON_SPACE = 20; + +-const float DOUBLE_CLICK_DISTANCE = 8.0f; +- +-const float SHADOW_RADIUS = 8.0f; +-const float SHADOW_OPACITY = 0.5f; +-const unsigned short SHADOW_OFFSET_X = 1; +-const unsigned short SHADOW_OFFSET_Y = 1; +- +-const float META_OPACITY = 0.75f; +- +-const float META_ACTIVE_OPACITY = 1.0f; +- + guint cmdline_options = 0; + + Atom frame_input_window_atom; +diff -Nur original/gtk/window-decorator/gtk-window-decorator.h modified/gtk/window-decorator/gtk-window-decorator.h +--- original/gtk/window-decorator/gtk-window-decorator.h 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/gtk-window-decorator.h 2015-04-11 14:34:11.000000000 +0100 +@@ -78,52 +78,11 @@ + + #include <gwd-fwd.h> + +-#define DBUS_DEST "org.freedesktop.compiz" +-#define DBUS_PATH "/org/freedesktop/compiz/decor/screen0" +-#define DBUS_INTERFACE "org.freedesktop.compiz" +-#define DBUS_METHOD_GET "get" +- +-extern const float STROKE_ALPHA; +- + extern const unsigned short ICON_SPACE; + +-extern const float DOUBLE_CLICK_DISTANCE; +- +-#define WM_MOVERESIZE_SIZE_TOPLEFT 0 +-#define WM_MOVERESIZE_SIZE_TOP 1 +-#define WM_MOVERESIZE_SIZE_TOPRIGHT 2 +-#define WM_MOVERESIZE_SIZE_RIGHT 3 +-#define WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4 +-#define WM_MOVERESIZE_SIZE_BOTTOM 5 +-#define WM_MOVERESIZE_SIZE_BOTTOMLEFT 6 +-#define WM_MOVERESIZE_SIZE_LEFT 7 +-#define WM_MOVERESIZE_MOVE 8 +-#define WM_MOVERESIZE_SIZE_KEYBOARD 9 +-#define WM_MOVERESIZE_MOVE_KEYBOARD 10 +- +-extern const float SHADOW_RADIUS; +-extern const float SHADOW_OPACITY; +-extern const unsigned short SHADOW_OFFSET_X; +-extern const unsigned short SHADOW_OFFSET_Y; +-#define SHADOW_COLOR_RED 0x0000 +-#define SHADOW_COLOR_GREEN 0x0000 +-#define SHADOW_COLOR_BLUE 0x0000 +- +-extern const float META_OPACITY; +-#define META_SHADE_OPACITY TRUE; +-extern const float META_ACTIVE_OPACITY; +-#define META_ACTIVE_SHADE_OPACITY TRUE; +- + #define META_MAXIMIZED (WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY | \ + WNCK_WINDOW_STATE_MAXIMIZED_VERTICALLY) + +-#define CMDLINE_OPACITY (1 << 0) +-#define CMDLINE_OPACITY_SHADE (1 << 1) +-#define CMDLINE_ACTIVE_OPACITY (1 << 2) +-#define CMDLINE_ACTIVE_OPACITY_SHADE (1 << 3) +-#define CMDLINE_BLUR (1 << 4) +-#define CMDLINE_THEME (1 << 5) +- + #define MWM_HINTS_DECORATIONS (1L << 1) + + #define MWM_DECOR_ALL (1L << 0) +@@ -144,16 +103,13 @@ + + extern gboolean minimal; + +-#define SWITCHER_SPACE 40 +- + extern GWDSettingsNotified *notified; +-extern GWDSettings *settings; ++extern GWDSettings *settings; + extern GWDSettingsWritable *writable; + + extern gdouble decoration_alpha; + #ifdef USE_METACITY +-extern MetaButtonLayout meta_button_layout; +-extern gboolean meta_button_layout_set; ++extern gboolean meta_button_layout_set; + #endif + + extern Atom frame_input_window_atom; +@@ -406,22 +362,11 @@ + extern XRenderPictFormat *xformat_rgba; + extern XRenderPictFormat *xformat_rgb; + +-/* gtk-window-decorator.c */ +- +-double +-dist (double x1, double y1, +- double x2, double y2); +- + /* frames.c */ + + void + initialize_decorations (); + +-void +-update_frames_border_extents (gpointer key, +- gpointer value, +- gpointer user_data); +- + decor_frame_t * + gwd_get_decor_frame (const gchar *); + +@@ -458,30 +403,6 @@ + void + frame_update_titlebar_font (decor_frame_t *frame); + +-void +-bare_frame_update_shadow (Display *xdisplay, +- Screen *screen, +- decor_frame_t *frame, +- decor_shadow_t **shadow_normal, +- decor_context_t *context_normal, +- decor_shadow_t **shadow_max, +- decor_context_t *context_max, +- decor_shadow_info_t *info, +- decor_shadow_options_t *opt_shadow, +- decor_shadow_options_t *opt_no_shadow); +- +-void +-decor_frame_update_shadow (Display *xdisplay, +- Screen *screen, +- decor_frame_t *frame, +- decor_shadow_t **shadow_normal, +- decor_context_t *context_normal, +- decor_shadow_t **shadow_max, +- decor_context_t *context_max, +- decor_shadow_info_t *info, +- decor_shadow_options_t *opt_shadow, +- decor_shadow_options_t *opt_no_shadow); +- + decor_frame_t * + create_normal_frame (const gchar *type); + +@@ -501,12 +422,6 @@ + gboolean + request_update_window_decoration_size (WnckWindow *win); + +-void +-update_window_decoration_name (WnckWindow *win); +- +-gint +-max_window_name_width (WnckWindow *win); +- + unsigned int + populate_frame_type (decor_t *d); + +@@ -538,9 +453,6 @@ + update_titlebar_font (); + + void +-update_window_decoration_name (WnckWindow *win); +- +-void + update_window_decoration (WnckWindow *win); + + void +@@ -561,10 +473,6 @@ + connect_screen (WnckScreen *screen); + + void +-window_opened (WnckScreen *screen, +- WnckWindow *window); +- +-void + window_closed (WnckScreen *screen, + WnckWindow *window); + +@@ -580,10 +488,6 @@ + restack_window (WnckWindow *win, + int stack_mode); + +-void +-connect_window (WnckWindow *win); +- +- + /* blur.c */ + + void +@@ -711,6 +615,7 @@ + surface_new_from_pixbuf (GdkPixbuf *pixbuf, GtkWidget *parent); + + /* metacity.c */ ++ + #ifdef USE_METACITY + + MetaFrameType +@@ -719,18 +624,6 @@ + void + meta_draw_window_decoration (decor_t *d); + +-void +-meta_get_decoration_geometry (decor_t *d, +- MetaTheme *theme, +- MetaFrameFlags *flags, +- MetaFrameGeometry *fgeom, +- MetaButtonLayout *button_layout, +- MetaFrameType frame_type, +- GdkRectangle *clip); +- +-void +-meta_calc_button_size (decor_t *d); +- + gboolean + meta_calc_decoration_size (decor_t *d, + gint w, +@@ -749,10 +642,6 @@ + gint *w, + gint *h); + +-gboolean +-meta_button_present (MetaButtonLayout *button_layout, +- MetaButtonFunction function); +- + void + meta_get_event_window_position (decor_t *d, + gint i, +@@ -777,6 +666,7 @@ + meta_get_shadow (decor_frame_t *, decor_shadow_options_t *opts, gboolean active); + + #endif ++ + /* switcher.c */ + + #define SWITCHER_ALPHA 0xa0a0 +@@ -799,35 +689,13 @@ + void + destroy_switcher_frame (); + +-void +-draw_switcher_decoration (decor_t *d); +- + gboolean + update_switcher_window (Window popup, + Window selected); + +-decor_t * +-switcher_window_opened (Window popup, Window selected); +- +-void +-switcher_window_closed (); +- + /* events.c */ + + void +-move_resize_window (WnckWindow *win, +- int direction, +- decor_event *gtkwd_event); +- +-void +-common_button_event (WnckWindow *win, +- decor_event *gtkwd_event, +- decor_event_type gtkwd_type, +- int button, +- int max, +- char *tooltip); +- +-void + close_button_event (WnckWindow *win, + decor_event *gtkwd_event, + decor_event_type gtkwd_type); +@@ -877,26 +745,11 @@ + decor_event_type gtkwd_type); + + void +-handle_title_button_event (WnckWindow *win, +- int action, +- decor_event *gtkwd_event); +- +-void +-handle_mouse_wheel_title_event (WnckWindow *win, +- unsigned int button); +- +-void + title_event (WnckWindow *win, + decor_event *gtkwd_event, + decor_event_type gtkwd_type); + + void +-frame_common_event (WnckWindow *win, +- int direction, +- decor_event *gtkwd_event, +- decor_event_type gtkwd_type); +- +-void + top_left_event (WnckWindow *win, + decor_event *gtkwd_event, + decor_event_type gtkwd_type); +@@ -938,17 +791,6 @@ + frame_window_realized (GtkWidget *widget, + gpointer data); + +-event_callback +-find_event_callback_for_point (decor_t *d, +- int x, +- int y, +- Bool *enter, +- Bool *leave, +- BoxPtr *entered_box); +- +-event_callback +-find_leave_event_callback (decor_t *d); +- + void + frame_handle_button_press (GtkWidget *widget, + GdkEventButton *event, +@@ -1004,18 +846,6 @@ + + /* util.c */ + +-double +-square (double x); +- +-double +-dist (double x1, double y1, +- double x2, double y2); +- +-void +-shade (const decor_color_t *a, +- decor_color_t *b, +- float k); +- + gboolean + get_window_prop (Window xwindow, + Atom atom, +diff -Nur original/gtk/window-decorator/gwd-settings.c modified/gtk/window-decorator/gwd-settings.c +--- original/gtk/window-decorator/gwd-settings.c 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/gwd-settings.c 2015-04-11 14:34:11.000000000 +0100 +@@ -61,21 +61,20 @@ + GWD_SETTINGS_IMPL_PROPERTY_INACTIVE_SHADOW = 2, + GWD_SETTINGS_IMPL_PROPERTY_USE_TOOLTIPS = 3, + GWD_SETTINGS_IMPL_PROPERTY_DRAGGABLE_BORDER_WIDTH = 4, +- GWD_SETTINGS_IMPL_PROPERTY_ATTACH_MODAL_DIALOGS = 5, +- GWD_SETTINGS_IMPL_PROPERTY_BLUR_CHANGED = 6, +- GWD_SETTINGS_IMPL_PROPERTY_METACITY_THEME = 7, +- GWD_SETTINGS_IMPL_PROPERTY_ACTIVE_OPACITY = 8, +- GWD_SETTINGS_IMPL_PROPERTY_INACTIVE_OPACITY = 9, +- GWD_SETTINGS_IMPL_PROPERTY_ACTIVE_SHADE_OPACITY = 10, +- GWD_SETTINGS_IMPL_PROPERTY_INACTIVE_SHADE_OPACITY = 11, +- GWD_SETTINGS_IMPL_PROPERTY_BUTTON_LAYOUT = 12, +- GWD_SETTINGS_IMPL_PROPERTY_TITLEBAR_ACTION_DOUBLE_CLICK = 13, +- GWD_SETTINGS_IMPL_PROPERTY_TITLEBAR_ACTION_MIDDLE_CLICK = 14, +- GWD_SETTINGS_IMPL_PROPERTY_TITLEBAR_ACTION_RIGHT_CLICK = 15, +- GWD_SETTINGS_IMPL_PROPERTY_MOUSE_WHEEL_ACTION = 16, +- GWD_SETTINGS_IMPL_PROPERTY_TITLEBAR_FONT = 17, +- GWD_SETTINGS_IMPL_PROPERTY_CMDLINE_OPTIONS = 18, +- GWD_SETTINGS_IMPL_PROPERTY_SETTINGS_NOTIFIED = 19 ++ GWD_SETTINGS_IMPL_PROPERTY_BLUR_CHANGED = 5, ++ GWD_SETTINGS_IMPL_PROPERTY_METACITY_THEME = 6, ++ GWD_SETTINGS_IMPL_PROPERTY_ACTIVE_OPACITY = 7, ++ GWD_SETTINGS_IMPL_PROPERTY_INACTIVE_OPACITY = 8, ++ GWD_SETTINGS_IMPL_PROPERTY_ACTIVE_SHADE_OPACITY = 9, ++ GWD_SETTINGS_IMPL_PROPERTY_INACTIVE_SHADE_OPACITY = 10, ++ GWD_SETTINGS_IMPL_PROPERTY_BUTTON_LAYOUT = 11, ++ GWD_SETTINGS_IMPL_PROPERTY_TITLEBAR_ACTION_DOUBLE_CLICK = 12, ++ GWD_SETTINGS_IMPL_PROPERTY_TITLEBAR_ACTION_MIDDLE_CLICK = 13, ++ GWD_SETTINGS_IMPL_PROPERTY_TITLEBAR_ACTION_RIGHT_CLICK = 14, ++ GWD_SETTINGS_IMPL_PROPERTY_MOUSE_WHEEL_ACTION = 15, ++ GWD_SETTINGS_IMPL_PROPERTY_TITLEBAR_FONT = 16, ++ GWD_SETTINGS_IMPL_PROPERTY_CMDLINE_OPTIONS = 17, ++ GWD_SETTINGS_IMPL_PROPERTY_SETTINGS_NOTIFIED = 18 + }; + + enum +@@ -92,7 +91,6 @@ + decor_shadow_options_t inactive_shadow; + gboolean use_tooltips; + gint draggable_border_width; +- gboolean attach_modal_dialogs; + gint blur_type; + gchar *metacity_theme; + gdouble metacity_active_opacity; +@@ -261,24 +259,6 @@ + } + + static gboolean +-gwd_settings_attach_modal_dialogs_changed (GWDSettingsWritable *settings, +- gboolean attach_modal_dialogs) +-{ +- GWDSettingsImpl *settings_impl = GWD_SETTINGS_IMPL (settings); +- GWDSettingsImplPrivate *priv = GET_PRIVATE (settings_impl); +- +- if (priv->attach_modal_dialogs != attach_modal_dialogs) +- { +- priv->attach_modal_dialogs = attach_modal_dialogs; +- append_to_notify_funcs (settings_impl, gwd_settings_notified_update_decorations); +- release_notify_funcs (settings_impl); +- return TRUE; +- } +- else +- return FALSE; +-} +- +-static gboolean + gwd_settings_blur_changed (GWDSettingsWritable *settings, + const gchar *type) + +@@ -554,7 +534,6 @@ + interface->shadow_property_changed = gwd_settings_shadow_property_changed; + interface->use_tooltips_changed = gwd_settings_use_tooltips_changed; + interface->draggable_border_width_changed = gwd_settings_draggable_border_width_changed; +- interface->attach_modal_dialogs_changed = gwd_settings_attach_modal_dialogs_changed; + interface->blur_changed = gwd_settings_blur_changed; + interface->metacity_theme_changed = gwd_settings_metacity_theme_changed; + interface->opacity_changed = gwd_settings_opacity_changed; +@@ -659,9 +638,6 @@ + case GWD_SETTINGS_IMPL_PROPERTY_DRAGGABLE_BORDER_WIDTH: + g_value_set_int (value, priv->draggable_border_width); + break; +- case GWD_SETTINGS_IMPL_PROPERTY_ATTACH_MODAL_DIALOGS: +- g_value_set_boolean (value, priv->attach_modal_dialogs); +- break; + case GWD_SETTINGS_IMPL_PROPERTY_BLUR_CHANGED: + g_value_set_int (value, priv->blur_type); + break; +@@ -729,9 +705,6 @@ + GWD_SETTINGS_IMPL_PROPERTY_DRAGGABLE_BORDER_WIDTH, + "draggable-border-width"); + g_object_class_override_property (object_class, +- GWD_SETTINGS_IMPL_PROPERTY_ATTACH_MODAL_DIALOGS, +- "attach-modal-dialogs"); +- g_object_class_override_property (object_class, + GWD_SETTINGS_IMPL_PROPERTY_BLUR_CHANGED, + "blur"); + g_object_class_override_property (object_class, +@@ -807,7 +780,6 @@ + priv->inactive_shadow.shadow_color[1] = 0; + priv->inactive_shadow.shadow_color[2] = 0; + priv->draggable_border_width = DRAGGABLE_BORDER_WIDTH_DEFAULT; +- priv->attach_modal_dialogs = ATTACH_MODAL_DIALOGS_DEFAULT; + priv->blur_type = BLUR_TYPE_DEFAULT; + priv->metacity_theme = g_strdup (METACITY_THEME_DEFAULT); + priv->metacity_active_opacity = METACITY_ACTIVE_OPACITY_DEFAULT; +diff -Nur original/gtk/window-decorator/gwd-settings-interface.c modified/gtk/window-decorator/gwd-settings-interface.c +--- original/gtk/window-decorator/gwd-settings-interface.c 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/gwd-settings-interface.c 2015-04-11 14:34:11.000000000 +0100 +@@ -34,7 +34,6 @@ + const gchar *INACTIVE_SHADOW_COLOR_DEFAULT = "#00000000"; + + const guint DRAGGABLE_BORDER_WIDTH_DEFAULT = 7; +-const gboolean ATTACH_MODAL_DIALOGS_DEFAULT = FALSE; + const gint BLUR_TYPE_DEFAULT = BLUR_TYPE_NONE; + + const gchar *METACITY_THEME_DEFAULT = "Adwaita"; +@@ -83,12 +82,6 @@ + DRAGGABLE_BORDER_WIDTH_DEFAULT, + G_PARAM_READABLE)); + g_object_interface_install_property (settings_interface, +- g_param_spec_boolean ("attach-modal-dialogs", +- "Attach modal dialogs", +- "Attach modal dialogs setting", +- ATTACH_MODAL_DIALOGS_DEFAULT, +- G_PARAM_READABLE)); +- g_object_interface_install_property (settings_interface, + g_param_spec_int ("blur", + "Blur Type", + "Blur type property", +diff -Nur original/gtk/window-decorator/gwd-settings-notified.c modified/gtk/window-decorator/gwd-settings-notified.c +--- original/gtk/window-decorator/gwd-settings-notified.c 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/gwd-settings-notified.c 2015-04-11 14:34:11.000000000 +0100 +@@ -200,17 +200,6 @@ + interface->update_metacity_theme = gwd_settings_notified_impl_update_metacity_theme; + } + +-static void gwd_settings_notified_impl_dispose (GObject *object) +-{ +- GWDSettingsNotifiedImplPrivate *priv = GET_PRIVATE (object); +- +- if (priv->screen) +- { +- g_object_unref (priv->screen); +- priv->screen = NULL; +- } +-} +- + static void gwd_settings_notified_impl_finalize (GObject *object) + { + G_OBJECT_CLASS (gwd_settings_notified_impl_parent_class)->finalize (object); +@@ -240,7 +229,6 @@ + + g_type_class_add_private (klass, sizeof (GWDSettingsNotifiedImplPrivate)); + +- object_class->dispose = gwd_settings_notified_impl_dispose; + object_class->finalize = gwd_settings_notified_impl_finalize; + object_class->set_property = gwd_settings_notified_impl_set_property; + +diff -Nur original/gtk/window-decorator/gwd-settings-storage-gsettings.c modified/gtk/window-decorator/gwd-settings-storage-gsettings.c +--- original/gtk/window-decorator/gwd-settings-storage-gsettings.c 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/gwd-settings-storage-gsettings.c 2015-04-11 14:34:11.000000000 +0100 +@@ -17,6 +17,9 @@ + * + * Authored By: Sam Spilsbury <sam.spilsbury@canonical.com> + */ ++#ifdef HAVE_CONFIG_H ++#include <config.h> ++#endif + #include <glib-object.h> + + #include <gio/gio.h> +@@ -28,6 +31,7 @@ + #include "gwd-settings-storage-gsettings.h" + + const gchar * ORG_COMPIZ_GWD = "org.compiz.gwd"; ++const gchar * ORG_GNOME_METACITY = "org.gnome.metacity"; + const gchar * ORG_GNOME_MUTTER = "org.gnome.mutter"; + const gchar * ORG_GNOME_DESKTOP_WM_PREFERENCES = "org.gnome.desktop.wm.preferences"; + +@@ -39,6 +43,8 @@ + const gchar * ORG_COMPIZ_GWD_KEY_METACITY_THEME_INACTIVE_SHADE_OPACITY = "metacity-theme-inactive-shade-opacity"; + const gchar * ORG_COMPIZ_GWD_KEY_USE_METACITY_THEME = "use-metacity-theme"; + const gchar * ORG_COMPIZ_GWD_KEY_MOUSE_WHEEL_ACTION = "mouse-wheel-action"; ++const gchar * ORG_GNOME_METACITY_THEME = "theme"; ++const gchar * ORG_GNOME_MUTTER_DRAGGABLE_BORDER_WIDTH = "draggable-border-width"; + const gchar * ORG_GNOME_DESKTOP_WM_PREFERENCES_ACTION_DOUBLE_CLICK_TITLEBAR = "action-double-click-titlebar"; + const gchar * ORG_GNOME_DESKTOP_WM_PREFERENCES_ACTION_MIDDLE_CLICK_TITLEBAR = "action-middle-click-titlebar"; + const gchar * ORG_GNOME_DESKTOP_WM_PREFERENCES_ACTION_RIGHT_CLICK_TITLEBAR = "action-right-click-titlebar"; +@@ -46,8 +52,6 @@ + const gchar * ORG_GNOME_DESKTOP_WM_PREFERENCES_TITLEBAR_USES_SYSTEM_FONT = "titlebar-uses-system-font"; + const gchar * ORG_GNOME_DESKTOP_WM_PREFERENCES_TITLEBAR_FONT = "titlebar-font"; + const gchar * ORG_GNOME_DESKTOP_WM_PREFERENCES_BUTTON_LAYOUT = "button-layout"; +-const gchar * ORG_GNOME_MUTTER_ATTACH_MODAL_DIALOGS = "attach-modal-dialogs"; +-const gchar * ORG_GNOME_MUTTER_DRAGGABLE_BORDER_WIDTH = "draggable-border-width"; + + #define GWD_SETTINGS_STORAGE_GSETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GWD_TYPE_SETTINGS_STORAGE_GSETTINGS, GWDSettingsStorageGSettings)); + #define GWD_SETTINGS_STORAGE_GSETTINGS_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GWD_TYPE_SETTINGS_STORAGE_GSETTINGS, GWDSettingsStorageGSettingsClass)); +@@ -75,10 +79,11 @@ + + enum + { +- GWD_SETTINGS_STORAGE_GSETTINGS_PROPERTY_DESKTOP_GSETTINGS = 1, +- GWD_SETTINGS_STORAGE_GSETTINGS_PROPERTY_MUTTER_GSETTINGS = 2, +- GWD_SETTINGS_STORAGE_GSETTINGS_PROPERTY_GWD_GSETTINGS = 3, +- GWD_SETTINGS_STORAGE_GSETTINGS_PROPERTY_WRITABLE_SETTINGS = 4 ++ GWD_SETTINGS_STORAGE_GSETTINGS_PROPERTY_DESKTOP_GSETTINGS = 1, ++ GWD_SETTINGS_STORAGE_GSETTINGS_PROPERTY_METACITY_GSETTINGS = 2, ++ GWD_SETTINGS_STORAGE_GSETTINGS_PROPERTY_MUTTER_GSETTINGS = 3, ++ GWD_SETTINGS_STORAGE_GSETTINGS_PROPERTY_GWD_GSETTINGS = 4, ++ GWD_SETTINGS_STORAGE_GSETTINGS_PROPERTY_WRITABLE_SETTINGS = 5 + }; + + const guint GWD_SETTINGS_STORAGE_GSETTINGS_N_CONSTRUCTION_PARAMS = 4; +@@ -86,6 +91,7 @@ + typedef struct _GWDSettingsStorageGSettingsPrivate + { + GSettings *desktop; ++ GSettings *metacity; + GSettings *mutter; + GSettings *gwd; + GWDSettingsWritable *writable; +@@ -120,20 +126,6 @@ + } + + static gboolean +-gwd_settings_storage_gsettings_update_attach_modal_dialogs (GWDSettingsStorage *settings) +-{ +- GWDSettingsStorageGSettings *storage = GWD_SETTINGS_STORAGE_GSETTINGS (settings); +- GWDSettingsStorageGSettingsPrivate *priv = GET_PRIVATE (storage); +- +- if (!priv->mutter) +- return FALSE; +- +- return gwd_settings_writable_attach_modal_dialogs_changed (priv->writable, +- g_settings_get_boolean (priv->mutter, +- ORG_GNOME_MUTTER_ATTACH_MODAL_DIALOGS)); +-} +- +-static gboolean + gwd_settings_storage_gsettings_update_blur (GWDSettingsStorage *settings) + { + GWDSettingsStorageGSettings *storage = GWD_SETTINGS_STORAGE_GSETTINGS (settings); +@@ -150,20 +142,34 @@ + static gboolean + gwd_settings_storage_gsettings_update_metacity_theme (GWDSettingsStorage *settings) + { +- GWDSettingsStorageGSettings *storage = GWD_SETTINGS_STORAGE_GSETTINGS (settings); +- GWDSettingsStorageGSettingsPrivate *priv = GET_PRIVATE (storage); ++ GWDSettingsStorageGSettings *storage; ++ GWDSettingsStorageGSettingsPrivate *priv; ++ gboolean use_metacity_theme; ++ gchar *theme; ++ ++ storage = GWD_SETTINGS_STORAGE_GSETTINGS (settings); ++ priv = GET_PRIVATE (storage); + + if (!priv->gwd) +- return FALSE; ++ return FALSE; + ++ use_metacity_theme = g_settings_get_boolean (priv->gwd, ORG_COMPIZ_GWD_KEY_USE_METACITY_THEME); ++ ++#ifdef HAVE_METACITY_3_16_0 ++ if (!priv->metacity) ++ return FALSE; ++ ++ theme = g_settings_get_string (priv->metacity, ORG_GNOME_METACITY_THEME); ++#else + if (!priv->desktop) +- return FALSE; ++ return FALSE; ++ ++ theme = g_settings_get_string (priv->desktop, ORG_GNOME_DESKTOP_WM_PREFERENCES_THEME); ++#endif + + return gwd_settings_writable_metacity_theme_changed (priv->writable, +- g_settings_get_boolean (priv->gwd, +- ORG_COMPIZ_GWD_KEY_USE_METACITY_THEME), +- g_settings_get_string (priv->desktop, +- ORG_GNOME_DESKTOP_WM_PREFERENCES_THEME)); ++ use_metacity_theme, ++ theme); + } + + static gboolean +@@ -275,7 +281,6 @@ + { + interface->update_use_tooltips = gwd_settings_storage_gsettings_update_use_tooltips; + interface->update_draggable_border_width = gwd_settings_storage_gsettings_update_draggable_border_width; +- interface->update_attach_modal_dialogs = gwd_settings_storage_gsettings_update_attach_modal_dialogs; + interface->update_blur = gwd_settings_storage_gsettings_update_blur; + interface->update_metacity_theme = gwd_settings_storage_gsettings_update_metacity_theme; + interface->update_opacity = gwd_settings_storage_gsettings_update_opacity; +@@ -300,6 +305,12 @@ + + priv->desktop = g_value_dup_object (value); + break; ++ case GWD_SETTINGS_STORAGE_GSETTINGS_PROPERTY_METACITY_GSETTINGS: ++ if (priv->metacity) ++ g_object_unref (priv->metacity); ++ ++ priv->metacity = g_value_dup_object (value); ++ break; + case GWD_SETTINGS_STORAGE_GSETTINGS_PROPERTY_MUTTER_GSETTINGS: + if (priv->mutter) + g_object_unref (priv->mutter); +@@ -330,6 +341,9 @@ + if (priv->desktop) + g_object_unref (priv->desktop); + ++ if (priv->metacity) ++ g_object_unref (priv->metacity); ++ + if (priv->mutter) + g_object_unref (priv->mutter); + +@@ -355,6 +369,11 @@ + "GSettings Object for org.gnome.desktop.wm.preferences", + G_TYPE_SETTINGS, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY), ++ g_param_spec_object ("metacity-gsettings", ++ ORG_GNOME_METACITY, ++ "GSettings Object for org.gnome.metacity", ++ G_TYPE_SETTINGS, ++ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY), + g_param_spec_object ("mutter-gsettings", + ORG_GNOME_MUTTER, + "GSettings Object for org.gnome.mutter", +@@ -388,14 +407,16 @@ + + GWDSettingsStorage * + gwd_settings_storage_gsettings_new (GSettings *desktop, ++ GSettings *metacity, + GSettings *mutter, + GSettings *gwd, + GWDSettingsWritable *writable) + { +- static const guint gwd_settings_storage_gsettings_n_construction_params = 4; ++ static const guint gwd_settings_storage_gsettings_n_construction_params = 5; + GParameter param[gwd_settings_storage_gsettings_n_construction_params]; + + GValue desktop_value = G_VALUE_INIT; ++ GValue metacity_value = G_VALUE_INIT; + GValue mutter_value = G_VALUE_INIT; + GValue gwd_value = G_VALUE_INIT; + GValue writable_value = G_VALUE_INIT; +@@ -405,29 +426,34 @@ + g_return_val_if_fail (writable != NULL, NULL); + + g_value_init (&desktop_value, G_TYPE_OBJECT); ++ g_value_init (&metacity_value, G_TYPE_OBJECT); + g_value_init (&mutter_value, G_TYPE_OBJECT); + g_value_init (&gwd_value, G_TYPE_OBJECT); + g_value_init (&writable_value, G_TYPE_POINTER); + + g_value_take_object (&desktop_value, desktop); ++ g_value_take_object (&metacity_value, metacity); + g_value_take_object (&mutter_value, mutter); + g_value_take_object (&gwd_value, gwd); + g_value_set_pointer (&writable_value, writable); + + param[0].name = "desktop-gsettings"; + param[0].value = desktop_value; +- param[1].name = "mutter-gsettings"; +- param[1].value = mutter_value; +- param[2].name = "gwd-gsettings"; +- param[2].value = gwd_value; +- param[3].name = "writable-settings"; +- param[3].value = writable_value; ++ param[1].name = "metacity-gsettings"; ++ param[1].value = metacity_value; ++ param[2].name = "mutter-gsettings"; ++ param[2].value = mutter_value; ++ param[3].name = "gwd-gsettings"; ++ param[3].value = gwd_value; ++ param[4].name = "writable-settings"; ++ param[4].value = writable_value; + + storage = GWD_SETTINGS_STORAGE_INTERFACE (g_object_newv (GWD_TYPE_SETTINGS_STORAGE_GSETTINGS, + gwd_settings_storage_gsettings_n_construction_params, + param)); + + g_value_unset (&desktop_value); ++ g_value_unset (&metacity_value); + g_value_unset (&mutter_value); + g_value_unset (&gwd_value); + g_value_unset (&writable_value); +@@ -488,6 +514,35 @@ + } + + static void ++org_gnome_metacity_settings_changed (GSettings *settings, ++ const gchar *key, ++ gpointer user_data) ++{ ++ GWDSettingsStorage *storage; ++ ++ storage = GWD_SETTINGS_STORAGE_INTERFACE (user_data); ++ ++ if (strcmp (key, ORG_GNOME_METACITY_THEME) == 0) ++ gwd_settings_storage_update_metacity_theme (storage); ++} ++ ++void ++gwd_connect_org_gnome_metacity_settings (GSettings *settings, ++ GWDSettingsStorage *storage) ++{ ++ if (!settings) ++ return; ++ ++ g_signal_connect (settings, "changed", (GCallback) org_gnome_metacity_settings_changed, storage); ++} ++ ++GSettings * ++gwd_get_org_gnome_metacity_settings () ++{ ++ return get_settings_no_abort (ORG_GNOME_METACITY); ++} ++ ++static void + org_gnome_mutter_settings_changed (GSettings *settings, + const gchar *key, + gpointer user_data) +@@ -496,8 +551,6 @@ + + if (strcmp (key, ORG_GNOME_MUTTER_DRAGGABLE_BORDER_WIDTH) == 0) + gwd_settings_storage_update_draggable_border_width (storage); +- else if (strcmp (key, ORG_GNOME_MUTTER_ATTACH_MODAL_DIALOGS) == 0) +- gwd_settings_storage_update_attach_modal_dialogs (storage); + } + + void +diff -Nur original/gtk/window-decorator/gwd-settings-storage-gsettings.h modified/gtk/window-decorator/gwd-settings-storage-gsettings.h +--- original/gtk/window-decorator/gwd-settings-storage-gsettings.h 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/gwd-settings-storage-gsettings.h 2015-04-11 14:34:11.000000000 +0100 +@@ -30,6 +30,7 @@ + + GWDSettingsStorage * + gwd_settings_storage_gsettings_new (GSettings *orgGNOMEDesktopSettings, ++ GSettings *metacitySettings, + GSettings *mutterSettings, + GSettings *gwdSettings, + GWDSettingsWritable *writableSettings); +@@ -42,6 +43,13 @@ + gwd_get_org_compiz_gwd_settings (); + + void ++gwd_connect_org_gnome_metacity_settings (GSettings *settings, ++ GWDSettingsStorage *storage); ++ ++GSettings * ++gwd_get_org_gnome_metacity_settings (); ++ ++void + gwd_connect_org_gnome_mutter_settings (GSettings *settings, + GWDSettingsStorage *storage); + +@@ -56,6 +64,7 @@ + gwd_get_org_gnome_desktop_wm_preferences_settings (); + + extern const gchar * ORG_COMPIZ_GWD; ++extern const gchar * ORG_GNOME_METACITY; + extern const gchar * ORG_GNOME_MUTTER; + extern const gchar * ORG_GNOME_DESKTOP_WM_PREFERENCES; + +@@ -67,6 +76,8 @@ + extern const gchar * ORG_COMPIZ_GWD_KEY_METACITY_THEME_INACTIVE_SHADE_OPACITY; + extern const gchar * ORG_COMPIZ_GWD_KEY_USE_METACITY_THEME; + extern const gchar * ORG_COMPIZ_GWD_KEY_MOUSE_WHEEL_ACTION; ++extern const gchar * ORG_GNOME_METACITY_THEME; ++extern const gchar * ORG_GNOME_MUTTER_DRAGGABLE_BORDER_WIDTH; + extern const gchar * ORG_GNOME_DESKTOP_WM_PREFERENCES_ACTION_DOUBLE_CLICK_TITLEBAR; + extern const gchar * ORG_GNOME_DESKTOP_WM_PREFERENCES_ACTION_MIDDLE_CLICK_TITLEBAR; + extern const gchar * ORG_GNOME_DESKTOP_WM_PREFERENCES_ACTION_RIGHT_CLICK_TITLEBAR; +@@ -74,8 +85,6 @@ + extern const gchar * ORG_GNOME_DESKTOP_WM_PREFERENCES_TITLEBAR_USES_SYSTEM_FONT; + extern const gchar * ORG_GNOME_DESKTOP_WM_PREFERENCES_TITLEBAR_FONT; + extern const gchar * ORG_GNOME_DESKTOP_WM_PREFERENCES_BUTTON_LAYOUT; +-extern const gchar * ORG_GNOME_MUTTER_ATTACH_MODAL_DIALOGS; +-extern const gchar * ORG_GNOME_MUTTER_DRAGGABLE_BORDER_WIDTH; + + G_END_DECLS + +diff -Nur original/gtk/window-decorator/gwd-settings-storage-interface.c modified/gtk/window-decorator/gwd-settings-storage-interface.c +--- original/gtk/window-decorator/gwd-settings-storage-interface.c 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/gwd-settings-storage-interface.c 2015-04-11 14:34:11.000000000 +0100 +@@ -39,12 +39,6 @@ + return (*interface->update_draggable_border_width) (settings); + } + +-gboolean gwd_settings_storage_update_attach_modal_dialogs (GWDSettingsStorage *settings) +-{ +- GWDSettingsStorageInterface *interface = GWD_SETTINGS_STORAGE_GET_INTERFACE (settings); +- return (*interface->update_attach_modal_dialogs) (settings); +-} +- + gboolean gwd_settings_storage_update_blur (GWDSettingsStorage *settings) + { + GWDSettingsStorageInterface *interface = GWD_SETTINGS_STORAGE_GET_INTERFACE (settings); +diff -Nur original/gtk/window-decorator/gwd-settings-storage-interface.h modified/gtk/window-decorator/gwd-settings-storage-interface.h +--- original/gtk/window-decorator/gwd-settings-storage-interface.h 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/gwd-settings-storage-interface.h 2015-04-11 14:34:11.000000000 +0100 +@@ -41,7 +41,6 @@ + + gboolean (*update_use_tooltips) (GWDSettingsStorage *settings); + gboolean (*update_draggable_border_width) (GWDSettingsStorage *settings); +- gboolean (*update_attach_modal_dialogs) (GWDSettingsStorage *settings); + gboolean (*update_blur) (GWDSettingsStorage *settings); + gboolean (*update_metacity_theme) (GWDSettingsStorage *settings); + gboolean (*update_opacity) (GWDSettingsStorage *settings); +@@ -52,7 +51,6 @@ + + gboolean gwd_settings_storage_update_use_tooltips (GWDSettingsStorage *settings); + gboolean gwd_settings_storage_update_draggable_border_width (GWDSettingsStorage *settings); +-gboolean gwd_settings_storage_update_attach_modal_dialogs (GWDSettingsStorage *settings); + gboolean gwd_settings_storage_update_blur (GWDSettingsStorage *settings); + gboolean gwd_settings_storage_update_metacity_theme (GWDSettingsStorage *settings); + gboolean gwd_settings_storage_update_opacity (GWDSettingsStorage *settings); +diff -Nur original/gtk/window-decorator/gwd-settings-writable-interface.c modified/gtk/window-decorator/gwd-settings-writable-interface.c +--- original/gtk/window-decorator/gwd-settings-writable-interface.c 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/gwd-settings-writable-interface.c 2015-04-11 14:34:11.000000000 +0100 +@@ -85,14 +85,6 @@ + } + + gboolean +-gwd_settings_writable_attach_modal_dialogs_changed (GWDSettingsWritable *settings, +- gboolean attach_modal_dialogs) +-{ +- GWDSettingsWritableInterface *iface = GWD_SETTINGS_WRITABLE_GET_INTERFACE (settings); +- return (*iface->attach_modal_dialogs_changed) (settings, attach_modal_dialogs); +-} +- +-gboolean + gwd_settings_writable_blur_changed (GWDSettingsWritable *settings, + const gchar *blur_type) + { +diff -Nur original/gtk/window-decorator/gwd-settings-writable-interface.h modified/gtk/window-decorator/gwd-settings-writable-interface.h +--- original/gtk/window-decorator/gwd-settings-writable-interface.h 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/gwd-settings-writable-interface.h 2015-04-11 14:34:11.000000000 +0100 +@@ -56,8 +56,6 @@ + gboolean new_value); + gboolean (*draggable_border_width_changed) (GWDSettingsWritable *settings, + gint new_value); +- gboolean (*attach_modal_dialogs_changed) (GWDSettingsWritable *settings, +- gboolean new_value); + gboolean (*blur_changed) (GWDSettingsWritable *settings, + const gchar *type); + gboolean (*metacity_theme_changed) (GWDSettingsWritable *settings, +@@ -108,10 +106,6 @@ + gint draggable_border_width); + + gboolean +-gwd_settings_writable_attach_modal_dialogs_changed (GWDSettingsWritable *settings, +- gboolean attach_modal_dialogs); +- +-gboolean + gwd_settings_writable_blur_changed (GWDSettingsWritable *settings, + const gchar *blur_type); + +diff -Nur original/gtk/window-decorator/metacity-3-16.c modified/gtk/window-decorator/metacity-3-16.c +--- original/gtk/window-decorator/metacity-3-16.c 1970-01-01 01:00:00.000000000 +0100 ++++ modified/gtk/window-decorator/metacity-3-16.c 2015-04-11 14:34:11.000000000 +0100 +@@ -0,0 +1,1555 @@ ++/* ++ * Copyright © 2006 Novell, Inc. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the ++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ * Boston, MA 02111-1307, USA. ++ * ++ * Author: David Reveman <davidr@novell.com> ++ * ++ * 2D Mode: Copyright © 2010 Sam Spilsbury <smspillaz@gmail.com> ++ * Frames Management: Copright © 2011 Canonical Ltd. ++ * Authored By: Sam Spilsbury <sam.spilsbury@canonical.com> ++ */ ++ ++#include "gtk-window-decorator.h" ++ ++#ifdef USE_METACITY ++#ifdef HAVE_METACITY_3_16_0 ++ ++MetaButtonLayout meta_button_layout; ++ ++static gboolean ++meta_button_present (MetaButtonLayout *button_layout, ++ MetaButtonFunction function) ++{ ++ int i; ++ ++ for (i = 0; i < MAX_BUTTONS_PER_CORNER; ++i) ++ if (button_layout->left_buttons[i] == function) ++ return TRUE; ++ ++ for (i = 0; i < MAX_BUTTONS_PER_CORNER; ++i) ++ if (button_layout->right_buttons[i] == function) ++ return TRUE; ++ ++ return FALSE; ++} ++ ++static void ++decor_update_meta_window_property (decor_t *d, ++ MetaTheme *theme, ++ MetaFrameFlags flags, ++ MetaFrameType type, ++ Region top, ++ Region bottom, ++ Region left, ++ Region right) ++{ ++ long *data; ++ GdkDisplay *display; ++ Display *xdisplay; ++ gint nQuad; ++ decor_extents_t win_extents; ++ decor_extents_t frame_win_extents; ++ decor_extents_t max_win_extents; ++ decor_extents_t frame_max_win_extents; ++ decor_quad_t quads[N_QUADS_MAX]; ++ unsigned int nOffset; ++ unsigned int frame_type; ++ unsigned int frame_state; ++ unsigned int frame_actions; ++ gint w; ++ gint lh; ++ gint rh; ++ gint top_stretch_offset; ++ gint bottom_stretch_offset; ++ gint left_stretch_offset; ++ gint right_stretch_offset; ++ ++ display = gdk_display_get_default (); ++ xdisplay = gdk_x11_display_get_xdisplay (display); ++ ++ nOffset = 1; ++ ++ frame_type = populate_frame_type (d); ++ frame_state = populate_frame_state (d); ++ frame_actions = populate_frame_actions (d); ++ ++ win_extents = frame_win_extents = d->frame->win_extents; ++ max_win_extents = frame_max_win_extents = d->frame->max_win_extents; ++ ++ /* Add the invisible grab area padding, but only for ++ * pixmap type decorations */ ++ if (!d->frame_window) ++ { ++ GdkScreen *screen; ++ MetaStyleInfo *style_info; ++ MetaFrameBorders borders; ++ ++ screen = gtk_widget_get_screen (d->frame->style_window_rgba); ++ style_info = meta_theme_create_style_info (screen, NULL); ++ ++ meta_theme_get_frame_borders (theme, style_info, type, ++ d->frame->text_height, ++ flags, &borders); ++ ++ if (flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE) ++ { ++ frame_win_extents.left += borders.invisible.left; ++ frame_win_extents.right += borders.invisible.right; ++ frame_max_win_extents.left += borders.invisible.left; ++ frame_max_win_extents.right += borders.invisible.right; ++ } ++ ++ if (flags & META_FRAME_ALLOWS_VERTICAL_RESIZE) ++ { ++ frame_win_extents.bottom += borders.invisible.bottom; ++ frame_win_extents.top += borders.invisible.top; ++ frame_max_win_extents.bottom += borders.invisible.bottom; ++ frame_max_win_extents.top += borders.invisible.top; ++ } ++ ++ meta_style_info_unref (style_info); ++ } ++ ++ w = d->border_layout.top.x2 - d->border_layout.top.x1 - ++ d->context->left_space - d->context->right_space; ++ ++ if (d->border_layout.rotation) ++ lh = d->border_layout.left.x2 - d->border_layout.left.x1; ++ else ++ lh = d->border_layout.left.y2 - d->border_layout.left.y1; ++ ++ if (d->border_layout.rotation) ++ rh = d->border_layout.right.x2 - d->border_layout.right.x1; ++ else ++ rh = d->border_layout.right.y2 - d->border_layout.right.y1; ++ ++ left_stretch_offset = lh / 2; ++ right_stretch_offset = rh / 2; ++ top_stretch_offset = w - d->button_width - 1; ++ bottom_stretch_offset = (d->border_layout.bottom.x2 - d->border_layout.bottom.x1 - ++ d->context->left_space - d->context->right_space) / 2; ++ ++ nQuad = decor_set_lXrXtXbX_window_quads (quads, d->context, &d->border_layout, ++ left_stretch_offset, right_stretch_offset, ++ top_stretch_offset, bottom_stretch_offset); ++ ++ win_extents.top += d->frame->titlebar_height; ++ frame_win_extents.top += d->frame->titlebar_height; ++ max_win_extents.top += d->frame->max_titlebar_height; ++ frame_max_win_extents.top += d->frame->max_titlebar_height; ++ ++ if (d->frame_window) ++ { ++ data = decor_alloc_property (nOffset, WINDOW_DECORATION_TYPE_WINDOW); ++ decor_gen_window_property (data, nOffset - 1, &win_extents, &max_win_extents, ++ 20, 20, frame_type, frame_state, frame_actions); ++ } ++ else ++ { ++ data = decor_alloc_property (nOffset, WINDOW_DECORATION_TYPE_PIXMAP); ++ decor_quads_to_property (data, nOffset - 1, cairo_xlib_surface_get_drawable (d->surface), ++ &frame_win_extents, &win_extents, ++ &frame_max_win_extents, &max_win_extents, ++ ICON_SPACE + d->button_width, ++ 0, quads, nQuad, frame_type, frame_state, frame_actions); ++ } ++ ++ gdk_error_trap_push (); ++ ++ XChangeProperty (xdisplay, d->prop_xid, win_decor_atom, XA_INTEGER, ++ 32, PropModeReplace, (guchar *) data, ++ PROP_HEADER_SIZE + BASE_PROP_SIZE + QUAD_PROP_SIZE * N_QUADS_MAX); ++ gdk_display_sync (display); ++ ++ gdk_error_trap_pop_ignored (); ++ ++ free (data); ++ ++ decor_update_blur_property (d, w, lh, ++ top, top_stretch_offset, ++ bottom, bottom_stretch_offset, ++ left, left_stretch_offset, ++ right, right_stretch_offset); ++} ++ ++static void ++meta_get_corner_radius (const MetaFrameGeometry *fgeom, ++ int *top_left_radius, ++ int *top_right_radius, ++ int *bottom_left_radius, ++ int *bottom_right_radius) ++{ ++ *top_left_radius = fgeom->top_left_corner_rounded_radius; ++ *top_right_radius = fgeom->top_right_corner_rounded_radius; ++ *bottom_left_radius = fgeom->bottom_left_corner_rounded_radius; ++ *bottom_right_radius = fgeom->bottom_right_corner_rounded_radius; ++} ++ ++static int ++radius_to_width (int radius, ++ int i) ++{ ++ float r1 = sqrt (radius) + radius; ++ float r2 = r1 * r1 - (r1 - (i + 0.5)) * (r1 - (i + 0.5)); ++ ++ return floor (0.5f + r1 - sqrt (r2)); ++} ++ ++static Region ++meta_get_top_border_region (const MetaFrameGeometry *fgeom, ++ int width) ++{ ++ Region corners_xregion; ++ Region border_xregion; ++ XRectangle xrect; ++ int top_left_radius; ++ int top_right_radius; ++ int bottom_left_radius; ++ int bottom_right_radius; ++ int w; ++ int i; ++ int height; ++ ++ corners_xregion = XCreateRegion (); ++ ++ meta_get_corner_radius (fgeom, &top_left_radius, &top_right_radius, ++ &bottom_left_radius, &bottom_right_radius); ++ ++ width = width - fgeom->borders.invisible.left - fgeom->borders.invisible.right; ++ height = fgeom->borders.visible.top; ++ ++ if (top_left_radius) ++ { ++ for (i = 0; i < top_left_radius; ++i) ++ { ++ w = radius_to_width (top_left_radius, i); ++ ++ xrect.x = 0; ++ xrect.y = i; ++ xrect.width = w; ++ xrect.height = 1; ++ ++ XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); ++ } ++ } ++ ++ if (top_right_radius) ++ { ++ for (i = 0; i < top_right_radius; ++i) ++ { ++ w = radius_to_width (top_right_radius, i); ++ ++ xrect.x = width - w; ++ xrect.y = i; ++ xrect.width = w; ++ xrect.height = 1; ++ ++ XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); ++ } ++ } ++ ++ border_xregion = XCreateRegion (); ++ ++ xrect.x = 0; ++ xrect.y = 0; ++ xrect.width = width; ++ xrect.height = height; ++ ++ XUnionRectWithRegion (&xrect, border_xregion, border_xregion); ++ ++ XSubtractRegion (border_xregion, corners_xregion, border_xregion); ++ ++ XDestroyRegion (corners_xregion); ++ ++ return border_xregion; ++} ++ ++static Region ++meta_get_bottom_border_region (const MetaFrameGeometry *fgeom, ++ int width) ++{ ++ Region corners_xregion; ++ Region border_xregion; ++ XRectangle xrect; ++ int top_left_radius; ++ int top_right_radius; ++ int bottom_left_radius; ++ int bottom_right_radius; ++ int w; ++ int i; ++ int height; ++ ++ corners_xregion = XCreateRegion (); ++ ++ meta_get_corner_radius (fgeom, &top_left_radius, &top_right_radius, ++ &bottom_left_radius, &bottom_right_radius); ++ ++ width = width - fgeom->borders.invisible.left - fgeom->borders.invisible.right; ++ height = fgeom->borders.visible.bottom; ++ ++ if (bottom_left_radius) ++ { ++ for (i = 0; i < bottom_left_radius; ++i) ++ { ++ w = radius_to_width (bottom_left_radius, i); ++ ++ xrect.x = 0; ++ xrect.y = height - i - 1; ++ xrect.width = w; ++ xrect.height = 1; ++ ++ XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); ++ } ++ } ++ ++ if (bottom_right_radius) ++ { ++ for (i = 0; i < bottom_right_radius; ++i) ++ { ++ w = radius_to_width (bottom_right_radius, i); ++ ++ xrect.x = width - w; ++ xrect.y = height - i - 1; ++ xrect.width = w; ++ xrect.height = 1; ++ ++ XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); ++ } ++ } ++ ++ border_xregion = XCreateRegion (); ++ ++ xrect.x = 0; ++ xrect.y = 0; ++ xrect.width = width; ++ xrect.height = height; ++ ++ XUnionRectWithRegion (&xrect, border_xregion, border_xregion); ++ ++ XSubtractRegion (border_xregion, corners_xregion, border_xregion); ++ ++ XDestroyRegion (corners_xregion); ++ ++ return border_xregion; ++} ++ ++static Region ++meta_get_left_border_region (const MetaFrameGeometry *fgeom, ++ int height) ++{ ++ Region border_xregion; ++ XRectangle xrect; ++ ++ border_xregion = XCreateRegion (); ++ ++ xrect.x = 0; ++ xrect.y = 0; ++ xrect.width = fgeom->borders.visible.left; ++ xrect.height = height - fgeom->borders.total.top - fgeom->borders.total.bottom; ++ ++ XUnionRectWithRegion (&xrect, border_xregion, border_xregion); ++ ++ return border_xregion; ++} ++ ++static Region ++meta_get_right_border_region (const MetaFrameGeometry *fgeom, ++ int height) ++{ ++ Region border_xregion; ++ XRectangle xrect; ++ ++ border_xregion = XCreateRegion (); ++ ++ xrect.x = 0; ++ xrect.y = 0; ++ xrect.width = fgeom->borders.visible.right; ++ xrect.height = height - fgeom->borders.total.top - fgeom->borders.total.bottom; ++ ++ XUnionRectWithRegion (&xrect, border_xregion, border_xregion); ++ ++ return border_xregion; ++} ++ ++static MetaButtonState ++meta_button_state (int state) ++{ ++ if (state & IN_EVENT_WINDOW) ++ { ++ if (state & PRESSED_EVENT_WINDOW) ++ return META_BUTTON_STATE_PRESSED; ++ ++ return META_BUTTON_STATE_PRELIGHT; ++ } ++ ++ return META_BUTTON_STATE_NORMAL; ++} ++ ++static MetaButtonType ++meta_function_to_type (MetaButtonFunction function) ++{ ++ switch (function) ++ { ++ case META_BUTTON_FUNCTION_MENU: ++ return META_BUTTON_TYPE_MENU; ++ case META_BUTTON_FUNCTION_MINIMIZE: ++ return META_BUTTON_TYPE_MINIMIZE; ++ case META_BUTTON_FUNCTION_MAXIMIZE: ++ return META_BUTTON_TYPE_MAXIMIZE; ++ case META_BUTTON_FUNCTION_CLOSE: ++ return META_BUTTON_TYPE_CLOSE; ++ case META_BUTTON_FUNCTION_SHADE: ++ return META_BUTTON_TYPE_SHADE; ++ case META_BUTTON_FUNCTION_ABOVE: ++ return META_BUTTON_TYPE_ABOVE; ++ case META_BUTTON_FUNCTION_STICK: ++ return META_BUTTON_TYPE_STICK; ++ case META_BUTTON_FUNCTION_UNSHADE: ++ return META_BUTTON_TYPE_UNSHADE; ++ case META_BUTTON_FUNCTION_UNABOVE: ++ return META_BUTTON_TYPE_UNABOVE; ++ case META_BUTTON_FUNCTION_UNSTICK: ++ return META_BUTTON_TYPE_UNSTICK; ++ default: ++ break; ++ } ++ ++ return META_BUTTON_TYPE_LAST; ++} ++ ++static MetaButtonState ++meta_button_state_for_button_type (decor_t *d, ++ MetaButtonType type) ++{ ++ switch (type) ++ { ++ case META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND: ++ type = meta_function_to_type (meta_button_layout.left_buttons[0]); ++ break; ++ case META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND: ++ type = meta_function_to_type (meta_button_layout.left_buttons[1]); ++ break; ++ case META_BUTTON_TYPE_LEFT_RIGHT_BACKGROUND: ++ type = meta_function_to_type (meta_button_layout.left_buttons[2]); ++ break; ++ case META_BUTTON_TYPE_RIGHT_LEFT_BACKGROUND: ++ type = meta_function_to_type (meta_button_layout.right_buttons[0]); ++ break; ++ case META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND: ++ type = meta_function_to_type (meta_button_layout.right_buttons[1]); ++ break; ++ case META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND: ++ type = meta_function_to_type (meta_button_layout.right_buttons[2]); ++ default: ++ break; ++ } ++ ++ switch (type) ++ { ++ case META_BUTTON_TYPE_CLOSE: ++ return meta_button_state (d->button_states[BUTTON_CLOSE]); ++ case META_BUTTON_TYPE_MAXIMIZE: ++ return meta_button_state (d->button_states[BUTTON_MAX]); ++ case META_BUTTON_TYPE_MINIMIZE: ++ return meta_button_state (d->button_states[BUTTON_MIN]); ++ case META_BUTTON_TYPE_MENU: ++ return meta_button_state (d->button_states[BUTTON_MENU]); ++ case META_BUTTON_TYPE_SHADE: ++ return meta_button_state (d->button_states[BUTTON_SHADE]); ++ case META_BUTTON_TYPE_ABOVE: ++ return meta_button_state (d->button_states[BUTTON_ABOVE]); ++ case META_BUTTON_TYPE_STICK: ++ return meta_button_state (d->button_states[BUTTON_STICK]); ++ case META_BUTTON_TYPE_UNSHADE: ++ return meta_button_state (d->button_states[BUTTON_UNSHADE]); ++ case META_BUTTON_TYPE_UNABOVE: ++ return meta_button_state (d->button_states[BUTTON_UNABOVE]); ++ case META_BUTTON_TYPE_UNSTICK: ++ return meta_button_state (d->button_states[BUTTON_UNSTICK]); ++ default: ++ break; ++ } ++ ++ return META_BUTTON_STATE_NORMAL; ++} ++ ++static void ++meta_get_decoration_geometry (decor_t *d, ++ MetaTheme *theme, ++ MetaFrameFlags *flags, ++ MetaFrameGeometry *fgeom, ++ MetaButtonLayout *button_layout, ++ MetaFrameType frame_type) ++{ ++ GdkScreen *screen; ++ MetaStyleInfo *style_info; ++ gint client_width; ++ gint client_height; ++ ++ if (!(frame_type < META_FRAME_TYPE_LAST)) ++ frame_type = META_FRAME_TYPE_NORMAL; ++ ++ if (meta_button_layout_set) ++ { ++ *button_layout = meta_button_layout; ++ } ++ else ++ { ++ gint i; ++ ++ button_layout->left_buttons[0] = META_BUTTON_FUNCTION_MENU; ++ ++ for (i = 1; i < MAX_BUTTONS_PER_CORNER; ++i) ++ button_layout->left_buttons[i] = META_BUTTON_FUNCTION_LAST; ++ ++ button_layout->right_buttons[0] = META_BUTTON_FUNCTION_MINIMIZE; ++ button_layout->right_buttons[1] = META_BUTTON_FUNCTION_MAXIMIZE; ++ button_layout->right_buttons[2] = META_BUTTON_FUNCTION_CLOSE; ++ ++ for (i = 3; i < MAX_BUTTONS_PER_CORNER; ++i) ++ button_layout->right_buttons[i] = META_BUTTON_FUNCTION_LAST; ++ } ++ ++ *flags = 0; ++ ++ if (d->actions & WNCK_WINDOW_ACTION_CLOSE) ++ *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_DELETE; ++ ++ if (d->actions & WNCK_WINDOW_ACTION_MINIMIZE) ++ *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_MINIMIZE; ++ ++ if (d->actions & WNCK_WINDOW_ACTION_MAXIMIZE) ++ *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_MAXIMIZE; ++ ++ *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_MENU; ++ ++ if (d->actions & WNCK_WINDOW_ACTION_RESIZE) ++ { ++ if (!(d->state & WNCK_WINDOW_STATE_MAXIMIZED_VERTICALLY)) ++ *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_VERTICAL_RESIZE; ++ if (!(d->state & WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY)) ++ *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_HORIZONTAL_RESIZE; ++ } ++ ++ if (d->actions & WNCK_WINDOW_ACTION_MOVE) ++ *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_MOVE; ++ ++ if (d->actions & WNCK_WINDOW_ACTION_MAXIMIZE) ++ *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_MAXIMIZE; ++ ++ if (d->actions & WNCK_WINDOW_ACTION_SHADE) ++ *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_SHADE; ++ ++ if (d->active) ++ *flags |= (MetaFrameFlags ) META_FRAME_HAS_FOCUS; ++ ++ if ((d->state & META_MAXIMIZED) == META_MAXIMIZED) ++ *flags |= (MetaFrameFlags ) META_FRAME_MAXIMIZED; ++ ++ if (d->state & WNCK_WINDOW_STATE_STICKY) ++ *flags |= (MetaFrameFlags ) META_FRAME_STUCK; ++ ++ if (d->state & WNCK_WINDOW_STATE_FULLSCREEN) ++ *flags |= (MetaFrameFlags ) META_FRAME_FULLSCREEN; ++ ++ if (d->state & WNCK_WINDOW_STATE_SHADED) ++ *flags |= (MetaFrameFlags ) META_FRAME_SHADED; ++ ++ if (d->state & WNCK_WINDOW_STATE_ABOVE) ++ *flags |= (MetaFrameFlags ) META_FRAME_ABOVE; ++ ++ client_width = d->border_layout.top.x2 - d->border_layout.top.x1; ++ client_width -= d->context->right_space + d->context->left_space; ++ ++ if (d->border_layout.rotation) ++ client_height = d->border_layout.left.x2 - d->border_layout.left.x1; ++ else ++ client_height = d->border_layout.left.y2 - d->border_layout.left.y1; ++ ++ screen = gtk_widget_get_screen (d->frame->style_window_rgba); ++ style_info = meta_theme_create_style_info (screen, NULL); ++ ++ meta_theme_calc_geometry (theme, style_info, frame_type, d->frame->text_height, ++ *flags, client_width, client_height, ++ button_layout, fgeom); ++ ++ meta_style_info_unref (style_info); ++} ++ ++void ++meta_draw_window_decoration (decor_t *d) ++{ ++ GdkDisplay *display; ++ GdkScreen *screen; ++ Display *xdisplay; ++ cairo_surface_t *surface; ++ Picture src; ++ MetaButtonState button_states [META_BUTTON_TYPE_LAST]; ++ MetaButtonLayout button_layout; ++ MetaFrameGeometry fgeom; ++ MetaFrameFlags flags; ++ MetaFrameType frame_type; ++ MetaTheme *theme; ++ MetaStyleInfo *style_info; ++ GtkStyleContext *context; ++ cairo_t *cr; ++ gint i; ++ Region top_region; ++ Region bottom_region; ++ Region left_region; ++ Region right_region; ++ gdouble meta_active_opacity; ++ gdouble meta_inactive_opacity; ++ gboolean meta_active_shade_opacity; ++ gboolean meta_inactive_shade_opacity; ++ double alpha; ++ gboolean shade_alpha; ++ MetaFrameStyle *frame_style; ++ GtkWidget *style_window; ++ GdkRGBA bg_rgba; ++ ++ if (!d->surface || !d->picture) ++ return; ++ ++ display = gdk_display_get_default (); ++ xdisplay = gdk_x11_display_get_xdisplay (display); ++ ++ top_region = NULL; ++ bottom_region = NULL; ++ left_region = NULL; ++ right_region = NULL; ++ ++ g_object_get (settings, "metacity-active-opacity", &meta_active_opacity, NULL); ++ g_object_get (settings, "metacity-inactive-opacity", &meta_inactive_opacity, NULL); ++ g_object_get (settings, "metacity-active-shade-opacity", &meta_active_shade_opacity, NULL); ++ g_object_get (settings, "metacity-inactive-shade-opacity", &meta_inactive_shade_opacity, NULL); ++ ++ alpha = (d->active) ? meta_active_opacity : meta_inactive_opacity; ++ shade_alpha = (d->active) ? meta_active_shade_opacity : meta_inactive_shade_opacity; ++ ++ if (decoration_alpha == 1.0) ++ alpha = 1.0; ++ ++ if (cairo_xlib_surface_get_depth (d->surface) == 32) ++ style_window = d->frame->style_window_rgba; ++ else ++ style_window = d->frame->style_window_rgb; ++ ++ context = gtk_widget_get_style_context (style_window); ++ ++ cr = cairo_create (d->buffer_surface ? d->buffer_surface : d->surface); ++ ++ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); ++ ++ theme = meta_theme_get_current (); ++ ++ frame_type = meta_frame_type_from_string (d->frame->type); ++ ++ if (frame_type == META_FRAME_TYPE_LAST) ++ frame_type = META_FRAME_TYPE_NORMAL; ++ ++ meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout, ++ frame_type); ++ ++ if ((d->prop_xid || !d->buffer_surface) && !d->frame_window) ++ draw_shadow_background (d, cr, d->shadow, d->context); ++ ++ for (i = 0; i < META_BUTTON_TYPE_LAST; ++i) ++ button_states[i] = meta_button_state_for_button_type (d, i); ++ ++ frame_style = meta_theme_get_frame_style (theme, frame_type, flags); ++ ++ gtk_style_context_get_background_color (context, GTK_STATE_FLAG_NORMAL, &bg_rgba); ++ bg_rgba.alpha = 1.0; ++ ++ if (frame_style->window_background_color) ++ { ++ meta_color_spec_render (frame_style->window_background_color, ++ context, &bg_rgba); ++ ++ bg_rgba.alpha = frame_style->window_background_alpha / 255.0; ++ } ++ ++ /* Draw something that will be almost invisible to user. This is hacky way ++ * to fix invisible decorations. */ ++ cairo_set_source_rgba (cr, 0, 0, 0, 0.01); ++ cairo_rectangle (cr, 0, 0, 1, 1); ++ cairo_fill (cr); ++ /* ------------ */ ++ ++ cairo_destroy (cr); ++ ++ if (d->frame_window) ++ surface = create_surface (fgeom.width, fgeom.height, d->frame->style_window_rgb); ++ else ++ surface = create_surface (fgeom.width, fgeom.height, d->frame->style_window_rgba); ++ ++ cr = cairo_create (surface); ++ gdk_cairo_set_source_rgba (cr, &bg_rgba); ++ cairo_set_operator (cr, CAIRO_OPERATOR_OVER); ++ ++ src = XRenderCreatePicture (xdisplay, cairo_xlib_surface_get_drawable (surface), ++ get_format_for_surface (d, surface), 0, NULL); ++ ++ screen = gtk_widget_get_screen (d->frame->style_window_rgba); ++ style_info = meta_theme_create_style_info (screen, NULL); ++ ++ cairo_paint (cr); ++ meta_theme_draw_frame (theme, style_info, cr, frame_type, flags, ++ fgeom.width - fgeom.borders.total.left - fgeom.borders.total.right, ++ fgeom.height - fgeom.borders.total.top - fgeom.borders.total.bottom, ++ d->layout, d->frame->text_height, &button_layout, ++ button_states, d->icon_pixbuf, NULL); ++ ++ meta_style_info_unref (style_info); ++ ++ if (fgeom.borders.visible.top) ++ { ++ top_region = meta_get_top_border_region (&fgeom, fgeom.width); ++ ++ decor_blend_border_picture (xdisplay, d->context, src, ++ fgeom.borders.invisible.left, ++ fgeom.borders.invisible.top, ++ d->picture, &d->border_layout, ++ BORDER_TOP, top_region, ++ alpha * 0xffff, shade_alpha, 0); ++ } ++ ++ if (fgeom.borders.visible.bottom) ++ { ++ bottom_region = meta_get_bottom_border_region (&fgeom, fgeom.width); ++ ++ decor_blend_border_picture (xdisplay, d->context, src, ++ fgeom.borders.invisible.left, ++ fgeom.height - fgeom.borders.total.bottom, ++ d->picture, &d->border_layout, ++ BORDER_BOTTOM, bottom_region, ++ alpha * 0xffff, shade_alpha, 0); ++ } ++ ++ if (fgeom.borders.visible.left) ++ { ++ left_region = meta_get_left_border_region (&fgeom, fgeom.height); ++ ++ decor_blend_border_picture (xdisplay, d->context, src, ++ fgeom.borders.invisible.left, ++ fgeom.borders.total.top, ++ d->picture, &d->border_layout, ++ BORDER_LEFT, left_region, ++ alpha * 0xffff, shade_alpha, 0); ++ } ++ ++ if (fgeom.borders.visible.right) ++ { ++ right_region = meta_get_right_border_region (&fgeom, fgeom.height); ++ ++ decor_blend_border_picture (xdisplay, d->context, src, ++ fgeom.width - fgeom.borders.total.right, ++ fgeom.borders.total.top, ++ d->picture, &d->border_layout, ++ BORDER_RIGHT, right_region, ++ alpha * 0xffff, shade_alpha, 0); ++ } ++ ++ cairo_destroy (cr); ++ cairo_surface_destroy (surface); ++ XRenderFreePicture (xdisplay, src); ++ ++ copy_to_front_buffer (d); ++ ++ if (d->frame_window) ++ { ++ GdkWindow *gdk_frame_window; ++ GdkPixbuf *pixbuf; ++ ++ gdk_frame_window = gtk_widget_get_window (d->decor_window); ++ ++ pixbuf = gdk_pixbuf_get_from_surface (d->surface, 0, 0, d->width, d->height); ++ gtk_image_set_from_pixbuf (GTK_IMAGE (d->decor_image), pixbuf); ++ g_object_unref (pixbuf); ++ ++ gdk_window_move_resize (gdk_frame_window, ++ d->context->left_corner_space - 1, ++ d->context->top_corner_space - 1, ++ d->width, ++ d->height); ++ ++ gdk_window_lower (gdk_frame_window); ++ } ++ ++ if (d->prop_xid) ++ { ++ /* translate from frame to client window space */ ++ if (top_region) ++ XOffsetRegion (top_region, -fgeom.borders.total.left, -fgeom.borders.total.top); ++ if (bottom_region) ++ XOffsetRegion (bottom_region, -fgeom.borders.total.left, 0); ++ if (left_region) ++ XOffsetRegion (left_region, -fgeom.borders.total.left, 0); ++ ++ decor_update_meta_window_property (d, theme, flags, frame_type, ++ top_region, bottom_region, ++ left_region, right_region); ++ ++ d->prop_xid = 0; ++ } ++ ++ if (top_region) ++ XDestroyRegion (top_region); ++ if (bottom_region) ++ XDestroyRegion (bottom_region); ++ if (left_region) ++ XDestroyRegion (left_region); ++ if (right_region) ++ XDestroyRegion (right_region); ++} ++ ++static void ++meta_calc_button_size (decor_t *d) ++{ ++ MetaTheme *theme; ++ MetaFrameType frame_type; ++ MetaFrameFlags flags; ++ MetaFrameGeometry fgeom; ++ MetaButtonLayout button_layout; ++ gint i, min_x, x, y, w, h, width; ++ ++ if (!d->context) ++ { ++ d->button_width = 0; ++ return; ++ } ++ ++ theme = meta_theme_get_current (); ++ ++ frame_type = meta_frame_type_from_string (d->frame->type); ++ if (!(frame_type < META_FRAME_TYPE_LAST)) ++ frame_type = META_FRAME_TYPE_NORMAL; ++ ++ meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout, ++ frame_type); ++ ++ width = d->border_layout.top.x2 - d->border_layout.top.x1 - ++ d->context->left_space - d->context->right_space + ++ fgeom.borders.total.left + fgeom.borders.total.right; ++ ++ min_x = width; ++ ++ for (i = 0; i < 3; ++i) ++ { ++ static guint button_actions[3] = { ++ WNCK_WINDOW_ACTION_CLOSE, ++ WNCK_WINDOW_ACTION_MAXIMIZE, ++ WNCK_WINDOW_ACTION_MINIMIZE ++ }; ++ ++ if (d->actions & button_actions[i]) ++ { ++ if (meta_get_button_position (d, i, width, 256, &x, &y, &w, &h)) ++ { ++ if (x > width / 2 && x < min_x) ++ min_x = x; ++ } ++ } ++ } ++ ++ d->button_width = width - min_x; ++} ++ ++static MetaButtonFunction ++button_to_meta_button_function (gint i) ++{ ++ switch (i) ++ { ++ case BUTTON_MENU: ++ return META_BUTTON_FUNCTION_MENU; ++ case BUTTON_MIN: ++ return META_BUTTON_FUNCTION_MINIMIZE; ++ case BUTTON_MAX: ++ return META_BUTTON_FUNCTION_MAXIMIZE; ++ case BUTTON_CLOSE: ++ return META_BUTTON_FUNCTION_CLOSE; ++ case BUTTON_SHADE: ++ return META_BUTTON_FUNCTION_SHADE; ++ case BUTTON_ABOVE: ++ return META_BUTTON_FUNCTION_ABOVE; ++ case BUTTON_STICK: ++ return META_BUTTON_FUNCTION_STICK; ++ case BUTTON_UNSHADE: ++ return META_BUTTON_FUNCTION_UNSHADE; ++ case BUTTON_UNABOVE: ++ return META_BUTTON_FUNCTION_UNABOVE; ++ case BUTTON_UNSTICK: ++ return META_BUTTON_FUNCTION_UNSTICK; ++ default: ++ break; ++ } ++ ++ return META_BUTTON_FUNCTION_LAST; ++} ++ ++gboolean ++meta_get_button_position (decor_t *d, ++ gint i, ++ gint width, ++ gint height, ++ gint *x, ++ gint *y, ++ gint *w, ++ gint *h) ++{ ++ MetaButtonLayout button_layout; ++ MetaFrameGeometry fgeom; ++ MetaFrameType frame_type; ++ MetaFrameFlags flags; ++ MetaTheme *theme; ++ MetaButtonFunction button_function; ++ MetaButtonSpace *space; ++ ++ if (!d->context) ++ { ++ /* undecorated windows implicitly have no buttons */ ++ return FALSE; ++ } ++ ++ theme = meta_theme_get_current (); ++ ++ frame_type = meta_frame_type_from_string (d->frame->type); ++ if (!(frame_type < META_FRAME_TYPE_LAST)) ++ frame_type = META_FRAME_TYPE_NORMAL; ++ ++ meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout, ++ frame_type); ++ ++ button_function = button_to_meta_button_function (i); ++ if (!meta_button_present (&button_layout, button_function)) ++ return FALSE; ++ ++ switch (i) ++ { ++ case BUTTON_MENU: ++ space = &fgeom.menu_rect; ++ break; ++ case BUTTON_MIN: ++ space = &fgeom.min_rect; ++ break; ++ case BUTTON_MAX: ++ space = &fgeom.max_rect; ++ break; ++ case BUTTON_CLOSE: ++ space = &fgeom.close_rect; ++ break; ++ case BUTTON_SHADE: ++ space = &fgeom.shade_rect; ++ break; ++ case BUTTON_ABOVE: ++ space = &fgeom.above_rect; ++ break; ++ case BUTTON_STICK: ++ space = &fgeom.stick_rect; ++ break; ++ case BUTTON_UNSHADE: ++ space = &fgeom.unshade_rect; ++ break; ++ case BUTTON_UNABOVE: ++ space = &fgeom.unabove_rect; ++ break; ++ case BUTTON_UNSTICK: ++ space = &fgeom.unstick_rect; ++ break; ++ default: ++ return FALSE; ++ } ++ ++ if (!space->clickable.width && !space->clickable.height) ++ return FALSE; ++ ++ *x = space->clickable.x; ++ *y = space->clickable.y; ++ *w = space->clickable.width; ++ *h = space->clickable.height; ++ ++ if (d->frame_window) ++ { ++ *x += d->frame->win_extents.left + 4; ++ *y += d->frame->win_extents.top + 2; ++ } ++ ++ return TRUE; ++} ++ ++gfloat ++meta_get_title_scale (decor_frame_t *frame) ++{ ++ MetaTheme *theme; ++ MetaFrameType type; ++ MetaFrameFlags flags; ++ ++ theme = meta_theme_get_current (); ++ type = meta_frame_type_from_string (frame->type); ++ flags = 0xc33; /* fixme */ ++ ++ if (type == META_FRAME_TYPE_LAST) ++ return 1.0f; ++ ++ gfloat scale = meta_theme_get_title_scale (theme, type, flags); ++ ++ return scale; ++} ++ ++gboolean ++meta_calc_decoration_size (decor_t *d, ++ gint w, ++ gint h, ++ gint name_width, ++ gint *width, ++ gint *height) ++{ ++ decor_layout_t layout; ++ decor_context_t *context; ++ decor_shadow_t *shadow; ++ ++ if (!d->decorated) ++ return FALSE; ++ ++ if ((d->state & META_MAXIMIZED) == META_MAXIMIZED) ++ { ++ if (!d->frame_window) ++ { ++ if (d->active) ++ { ++ context = &d->frame->max_window_context_active; ++ shadow = d->frame->max_border_shadow_active; ++ } ++ else ++ { ++ context = &d->frame->max_window_context_inactive; ++ shadow = d->frame->max_border_shadow_inactive; ++ } ++ } ++ else ++ { ++ context = &d->frame->max_window_context_no_shadow; ++ shadow = d->frame->max_border_no_shadow; ++ } ++ } ++ else ++ { ++ if (!d->frame_window) ++ { ++ if (d->active) ++ { ++ context = &d->frame->window_context_active; ++ shadow = d->frame->border_shadow_active; ++ } ++ else ++ { ++ context = &d->frame->window_context_inactive; ++ shadow = d->frame->border_shadow_inactive; ++ } ++ } ++ else ++ { ++ context = &d->frame->window_context_no_shadow; ++ shadow = d->frame->border_no_shadow; ++ } ++ } ++ ++ if (!d->frame_window) ++ { ++ decor_get_best_layout (context, w, h, &layout); ++ ++ if (context != d->context || memcmp (&layout, &d->border_layout, sizeof (layout))) ++ { ++ *width = layout.width; ++ *height = layout.height; ++ ++ d->border_layout = layout; ++ d->context = context; ++ d->shadow = shadow; ++ ++ meta_calc_button_size (d); ++ ++ return TRUE; ++ } ++ } ++ else ++ { ++ if ((d->state & META_MAXIMIZED) == META_MAXIMIZED) ++ decor_get_default_layout (context, d->client_width, ++ d->client_height - d->frame->titlebar_height, ++ &layout); ++ else ++ decor_get_default_layout (context, d->client_width, ++ d->client_height, &layout); ++ ++ *width = layout.width; ++ *height = layout.height; ++ ++ d->border_layout = layout; ++ d->shadow = shadow; ++ d->context = context; ++ ++ meta_calc_button_size (d); ++ ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++#define TOP_RESIZE_HEIGHT 2 ++#define RESIZE_EXTENDS 15 ++ ++void ++meta_get_event_window_position (decor_t *d, ++ gint i, ++ gint j, ++ gint width, ++ gint height, ++ gint *x, ++ gint *y, ++ gint *w, ++ gint *h) ++{ ++ MetaButtonLayout button_layout; ++ MetaFrameGeometry fgeom; ++ MetaFrameFlags flags; ++ MetaTheme *theme; ++ ++ theme = meta_theme_get_current (); ++ ++ meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout, ++ meta_frame_type_from_string (d->frame->type)); ++ ++ width += fgeom.borders.total.right + fgeom.borders.total.left; ++ height += fgeom.borders.total.top + fgeom.borders.total.bottom; ++ ++ switch (i) ++ { ++ case 2: /* bottom */ ++ switch (j) ++ { ++ case 2: /* bottom right */ ++ *x = width - fgeom.borders.total.right - RESIZE_EXTENDS; ++ *y = height - fgeom.borders.total.bottom - RESIZE_EXTENDS; ++ ++ if (d->frame_window) ++ { ++ *x += d->frame->win_extents.left + 2; ++ *y += d->frame->win_extents.top + 2; ++ } ++ ++ *w = fgeom.borders.total.right + RESIZE_EXTENDS; ++ *h = fgeom.borders.total.bottom + RESIZE_EXTENDS; ++ break; ++ case 1: /* bottom */ ++ *x = fgeom.borders.total.left + RESIZE_EXTENDS; ++ *y = height - fgeom.borders.total.bottom; ++ ++ if (d->frame_window) ++ *y += d->frame->win_extents.top + 2; ++ ++ *w = width - fgeom.borders.total.left - fgeom.borders.total.right - (2 * RESIZE_EXTENDS); ++ *h = fgeom.borders.total.bottom; ++ break; ++ case 0: /* bottom left */ ++ default: ++ *x = 0; ++ *y = height - fgeom.borders.total.bottom - RESIZE_EXTENDS; ++ ++ if (d->frame_window) ++ { ++ *x += d->frame->win_extents.left + 4; ++ *y += d->frame->win_extents.bottom + 2; ++ } ++ ++ *w = fgeom.borders.total.left + RESIZE_EXTENDS; ++ *h = fgeom.borders.total.bottom + RESIZE_EXTENDS; ++ break; ++ } ++ break; ++ case 1: /* middle */ ++ switch (j) ++ { ++ case 2: /* right */ ++ *x = width - fgeom.borders.total.right; ++ *y = fgeom.borders.total.top + RESIZE_EXTENDS; ++ ++ if (d->frame_window) ++ *x += d->frame->win_extents.left + 2; ++ ++ *w = fgeom.borders.total.right; ++ *h = height - fgeom.borders.total.top - fgeom.borders.total.bottom - (2 * RESIZE_EXTENDS); ++ break; ++ case 1: /* middle */ ++ *x = fgeom.borders.total.left; ++ *y = fgeom.title_rect.y + TOP_RESIZE_HEIGHT; ++ *w = width - fgeom.borders.total.left - fgeom.borders.total.right; ++ *h = height - fgeom.top_titlebar_edge - fgeom.borders.total.bottom; ++ break; ++ case 0: /* left */ ++ default: ++ *x = 0; ++ *y = fgeom.borders.total.top + RESIZE_EXTENDS; ++ ++ if (d->frame_window) ++ *x += d->frame->win_extents.left + 4; ++ ++ *w = fgeom.borders.total.left; ++ *h = height - fgeom.borders.total.top - fgeom.borders.total.bottom - (2 * RESIZE_EXTENDS); ++ break; ++ } ++ break; ++ case 0: /* top */ ++ default: ++ switch (j) ++ { ++ case 2: /* top right */ ++ *x = width - fgeom.borders.total.right - RESIZE_EXTENDS; ++ *y = 0; ++ ++ if (d->frame_window) ++ { ++ *x += d->frame->win_extents.left + 2; ++ *y += d->frame->win_extents.top + 2 - fgeom.title_rect.height; ++ } ++ ++ *w = fgeom.borders.total.right + RESIZE_EXTENDS; ++ *h = fgeom.borders.total.top + RESIZE_EXTENDS; ++ break; ++ case 1: /* top */ ++ *x = fgeom.borders.total.left + RESIZE_EXTENDS; ++ *y = 0; ++ ++ if (d->frame_window) ++ *y += d->frame->win_extents.top + 2; ++ ++ *w = width - fgeom.borders.total.left - fgeom.borders.total.right - (2 * RESIZE_EXTENDS); ++ *h = fgeom.borders.total.top - fgeom.title_rect.height; ++ break; ++ case 0: /* top left */ ++ default: ++ *x = 0; ++ *y = 0; ++ ++ if (d->frame_window) ++ { ++ *x += d->frame->win_extents.left + 4; ++ *y += d->frame->win_extents.top + 2 - fgeom.title_rect.height; ++ } ++ ++ *w = fgeom.borders.total.left + RESIZE_EXTENDS; ++ *h = fgeom.borders.total.top + RESIZE_EXTENDS; ++ break; ++ } ++ break; ++ } ++ ++ if (!(flags & META_FRAME_ALLOWS_VERTICAL_RESIZE)) ++ { ++ /* turn off top and bottom event windows */ ++ if (i == 0 || i == 2) ++ *w = *h = 0; ++ } ++ ++ if (!(flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE)) ++ { ++ /* turn off left and right event windows */ ++ if (j == 0 || j == 2) ++ *w = *h = 0; ++ } ++} ++ ++static MetaButtonFunction ++meta_button_function_from_string (const char *str) ++{ ++ if (strcmp (str, "menu") == 0) ++ return META_BUTTON_FUNCTION_MENU; ++ else if (strcmp (str, "appmenu") == 0) ++ return META_BUTTON_FUNCTION_APPMENU; ++ else if (strcmp (str, "minimize") == 0) ++ return META_BUTTON_FUNCTION_MINIMIZE; ++ else if (strcmp (str, "maximize") == 0) ++ return META_BUTTON_FUNCTION_MAXIMIZE; ++ else if (strcmp (str, "close") == 0) ++ return META_BUTTON_FUNCTION_CLOSE; ++ else if (strcmp (str, "shade") == 0) ++ return META_BUTTON_FUNCTION_SHADE; ++ else if (strcmp (str, "above") == 0) ++ return META_BUTTON_FUNCTION_ABOVE; ++ else if (strcmp (str, "stick") == 0) ++ return META_BUTTON_FUNCTION_STICK; ++ else if (strcmp (str, "unshade") == 0) ++ return META_BUTTON_FUNCTION_UNSHADE; ++ else if (strcmp (str, "unabove") == 0) ++ return META_BUTTON_FUNCTION_UNABOVE; ++ else if (strcmp (str, "unstick") == 0) ++ return META_BUTTON_FUNCTION_UNSTICK; ++ else ++ return META_BUTTON_FUNCTION_LAST; ++} ++ ++static MetaButtonFunction ++meta_button_opposite_function (MetaButtonFunction ofwhat) ++{ ++ switch (ofwhat) ++ { ++ case META_BUTTON_FUNCTION_SHADE: ++ return META_BUTTON_FUNCTION_UNSHADE; ++ case META_BUTTON_FUNCTION_UNSHADE: ++ return META_BUTTON_FUNCTION_SHADE; ++ ++ case META_BUTTON_FUNCTION_ABOVE: ++ return META_BUTTON_FUNCTION_UNABOVE; ++ case META_BUTTON_FUNCTION_UNABOVE: ++ return META_BUTTON_FUNCTION_ABOVE; ++ ++ case META_BUTTON_FUNCTION_STICK: ++ return META_BUTTON_FUNCTION_UNSTICK; ++ case META_BUTTON_FUNCTION_UNSTICK: ++ return META_BUTTON_FUNCTION_STICK; ++ ++ default: ++ return META_BUTTON_FUNCTION_LAST; ++ } ++} ++ ++static void ++meta_initialize_button_layout (MetaButtonLayout *layout) ++{ ++ int i; ++ ++ for (i = 0; i < MAX_BUTTONS_PER_CORNER; ++i) ++ { ++ layout->left_buttons[i] = META_BUTTON_FUNCTION_LAST; ++ layout->right_buttons[i] = META_BUTTON_FUNCTION_LAST; ++ layout->left_buttons_has_spacer[i] = FALSE; ++ layout->right_buttons_has_spacer[i] = FALSE; ++ } ++} ++ ++void ++meta_update_button_layout (const char *value) ++{ ++ MetaButtonLayout new_layout; ++ MetaButtonFunction f; ++ char **sides; ++ int i; ++ ++ meta_initialize_button_layout (&new_layout); ++ ++ sides = g_strsplit (value, ":", 2); ++ ++ if (sides[0] != NULL) ++ { ++ char **buttons; ++ int b; ++ gboolean used[META_BUTTON_FUNCTION_LAST]; ++ ++ for (i = 0; i < META_BUTTON_FUNCTION_LAST; ++i) ++ used[i] = FALSE; ++ ++ buttons = g_strsplit (sides[0], ",", -1); ++ ++ i = b = 0; ++ while (buttons[b] != NULL) ++ { ++ f = meta_button_function_from_string (buttons[b]); ++ if (i > 0 && strcmp ("spacer", buttons[b]) == 0) ++ { ++ new_layout.left_buttons_has_spacer[i - 1] = TRUE; ++ f = meta_button_opposite_function (f); ++ ++ if (f != META_BUTTON_FUNCTION_LAST) ++ new_layout.left_buttons_has_spacer[i - 2] = TRUE; ++ } ++ else ++ { ++ if (f != META_BUTTON_FUNCTION_LAST && !used[f]) ++ { ++ used[f] = TRUE; ++ new_layout.left_buttons[i++] = f; ++ ++ f = meta_button_opposite_function (f); ++ ++ if (f != META_BUTTON_FUNCTION_LAST) ++ new_layout.left_buttons[i++] = f; ++ ++ } ++ else ++ { ++ fprintf (stderr, "%s: Ignoring unknown or already-used " ++ "button name \"%s\"\n", program_name, buttons[b]); ++ } ++ } ++ ++b; ++ } ++ ++ new_layout.left_buttons[i] = META_BUTTON_FUNCTION_LAST; ++ ++ g_strfreev (buttons); ++ ++ if (sides[1] != NULL) ++ { ++ for (i = 0; i < META_BUTTON_FUNCTION_LAST; ++i) ++ used[i] = FALSE; ++ ++ buttons = g_strsplit (sides[1], ",", -1); ++ ++ i = b = 0; ++ while (buttons[b] != NULL) ++ { ++ f = meta_button_function_from_string (buttons[b]); ++ if (i > 0 && strcmp ("spacer", buttons[b]) == 0) ++ { ++ new_layout.right_buttons_has_spacer[i - 1] = TRUE; ++ f = meta_button_opposite_function (f); ++ if (f != META_BUTTON_FUNCTION_LAST) ++ new_layout.right_buttons_has_spacer[i - 2] = TRUE; ++ } ++ else ++ { ++ if (f != META_BUTTON_FUNCTION_LAST && !used[f]) ++ { ++ used[f] = TRUE; ++ new_layout.right_buttons[i++] = f; ++ ++ f = meta_button_opposite_function (f); ++ ++ if (f != META_BUTTON_FUNCTION_LAST) ++ new_layout.right_buttons[i++] = f; ++ } ++ else ++ { ++ fprintf (stderr, "%s: Ignoring unknown or " ++ "already-used button name \"%s\"\n", ++ program_name, buttons[b]); ++ } ++ } ++ ++b; ++ } ++ ++ new_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST; ++ ++ g_strfreev (buttons); ++ } ++ } ++ ++ g_strfreev (sides); ++ ++ /* Invert the button layout for RTL languages */ ++ if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL) ++ { ++ MetaButtonLayout rtl_layout; ++ int j; ++ ++ meta_initialize_button_layout (&rtl_layout); ++ ++ i = 0; ++ while (new_layout.left_buttons[i] != META_BUTTON_FUNCTION_LAST) ++ ++i; ++ ++ for (j = 0; j < i; ++j) ++ { ++ rtl_layout.right_buttons[j] = new_layout.left_buttons[i - j - 1]; ++ if (j == 0) ++ rtl_layout.right_buttons_has_spacer[i - 1] = new_layout.left_buttons_has_spacer[i - j - 1]; ++ else ++ rtl_layout.right_buttons_has_spacer[j - 1] = new_layout.left_buttons_has_spacer[i - j - 1]; ++ } ++ ++ i = 0; ++ while (new_layout.right_buttons[i] != META_BUTTON_FUNCTION_LAST) ++ ++i; ++ ++ for (j = 0; j < i; ++j) ++ { ++ rtl_layout.left_buttons[j] = new_layout.right_buttons[i - j - 1]; ++ if (j == 0) ++ rtl_layout.left_buttons_has_spacer[i - 1] = new_layout.right_buttons_has_spacer[i - j - 1]; ++ else ++ rtl_layout.left_buttons_has_spacer[j - 1] = new_layout.right_buttons_has_spacer[i - j - 1]; ++ } ++ ++ new_layout = rtl_layout; ++ } ++ ++ meta_button_layout = new_layout; ++} ++ ++void ++meta_update_border_extents (decor_frame_t *frame) ++{ ++ MetaTheme *theme; ++ GdkScreen *screen; ++ MetaStyleInfo *style_info; ++ MetaFrameBorders borders; ++ MetaFrameType frame_type; ++ gint top_height; ++ gint bottom_height; ++ gint left_width; ++ gint right_width; ++ ++ gwd_decor_frame_ref (frame); ++ ++ frame_type = meta_frame_type_from_string (frame->type); ++ if (!(frame_type < META_FRAME_TYPE_LAST)) ++ frame_type = META_FRAME_TYPE_NORMAL; ++ ++ theme = meta_theme_get_current (); ++ ++ screen = gtk_widget_get_screen (frame->style_window_rgba); ++ style_info = meta_theme_create_style_info (screen, NULL); ++ ++ meta_theme_get_frame_borders (theme, style_info, frame_type, frame->text_height, ++ 0, &borders); ++ ++ top_height = borders.visible.top; ++ bottom_height = borders.visible.bottom; ++ left_width = borders.visible.left; ++ right_width = borders.visible.right; ++ ++ frame->win_extents.top = frame->win_extents.top; ++ frame->win_extents.bottom = bottom_height; ++ frame->win_extents.left = left_width; ++ frame->win_extents.right = right_width; ++ ++ frame->titlebar_height = top_height - frame->win_extents.top; ++ ++ meta_theme_get_frame_borders (theme, style_info, frame_type, frame->text_height, ++ META_FRAME_MAXIMIZED, &borders); ++ ++ top_height = borders.visible.top; ++ bottom_height = borders.visible.bottom; ++ left_width = borders.visible.left; ++ right_width = borders.visible.right; ++ ++ frame->max_win_extents.top = frame->win_extents.top; ++ frame->max_win_extents.bottom = bottom_height; ++ frame->max_win_extents.left = left_width; ++ frame->max_win_extents.right = right_width; ++ ++ frame->max_titlebar_height = top_height - frame->max_win_extents.top; ++ ++ meta_style_info_unref (style_info); ++ ++ gwd_decor_frame_unref (frame); ++} ++ ++#endif /* HAVE_METACITY_3_16_0 */ ++#endif /* USE_METACITY */ +diff -Nur original/gtk/window-decorator/metacity.c modified/gtk/window-decorator/metacity.c +--- original/gtk/window-decorator/metacity.c 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/metacity.c 2015-04-11 14:34:11.000000000 +0100 +@@ -26,87 +26,118 @@ + #include "gtk-window-decorator.h" + + #ifdef USE_METACITY ++#ifndef HAVE_METACITY_3_16_0 ++ ++MetaButtonLayout meta_button_layout; ++ ++static gboolean ++meta_button_present (MetaButtonLayout *button_layout, ++ MetaButtonFunction function) ++{ ++ int i; ++ ++ for (i = 0; i < MAX_BUTTONS_PER_CORNER; ++i) ++ if (button_layout->left_buttons[i] == function) ++ return TRUE; ++ ++ for (i = 0; i < MAX_BUTTONS_PER_CORNER; ++i) ++ if (button_layout->right_buttons[i] == function) ++ return TRUE; ++ ++ return FALSE; ++} + + static void +-decor_update_meta_window_property (decor_t *d, +- MetaTheme *theme, +- MetaFrameFlags flags, +- Region top, +- Region bottom, +- Region left, +- Region right) +-{ +- long *data; +- Display *xdisplay = +- GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); +- gint nQuad; +- decor_extents_t win_extents, frame_win_extents; +- decor_extents_t max_win_extents, frame_max_win_extents; +- decor_quad_t quads[N_QUADS_MAX]; +- unsigned int nOffset = 1; +- unsigned int frame_type = populate_frame_type (d); +- unsigned int frame_state = populate_frame_state (d); +- unsigned int frame_actions = populate_frame_actions (d); +- gint w, lh, rh; +- gint top_stretch_offset; +- gint bottom_stretch_offset; +- gint left_stretch_offset; +- gint right_stretch_offset; +- gint mutter_draggable_border_width = 0; ++decor_update_meta_window_property (decor_t *d, ++ MetaTheme *theme, ++ MetaFrameFlags flags, ++ Region top, ++ Region bottom, ++ Region left, ++ Region right) ++{ ++ long *data; ++ GdkDisplay *display; ++ Display *xdisplay; ++ gint nQuad; ++ decor_extents_t win_extents; ++ decor_extents_t frame_win_extents; ++ decor_extents_t max_win_extents; ++ decor_extents_t frame_max_win_extents; ++ decor_quad_t quads[N_QUADS_MAX]; ++ unsigned int nOffset; ++ unsigned int frame_type; ++ unsigned int frame_state; ++ unsigned int frame_actions; ++ gint w; ++ gint lh; ++ gint rh; ++ gint top_stretch_offset; ++ gint bottom_stretch_offset; ++ gint left_stretch_offset; ++ gint right_stretch_offset; ++ gint mutter_draggable_border_width; ++ ++ display = gdk_display_get_default (); ++ xdisplay = gdk_x11_display_get_xdisplay (display); ++ ++ nOffset = 1; ++ ++ frame_type = populate_frame_type (d); ++ frame_state = populate_frame_state (d); ++ frame_actions = populate_frame_actions (d); + + win_extents = frame_win_extents = d->frame->win_extents; + max_win_extents = frame_max_win_extents = d->frame->max_win_extents; + +- g_object_get (settings, "draggable-border-width", &mutter_draggable_border_width, NULL); ++ mutter_draggable_border_width = 0; ++ ++ g_object_get (settings, "draggable-border-width", ++ &mutter_draggable_border_width, NULL); + + /* Add the invisible grab area padding, but only for + * pixmap type decorations */ + if (!d->frame_window) + { +- if (flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE) +- { +- frame_win_extents.left += mutter_draggable_border_width; +- frame_win_extents.right += mutter_draggable_border_width; +- frame_max_win_extents.left += mutter_draggable_border_width; +- frame_max_win_extents.right += mutter_draggable_border_width; +- } +- +- if (flags & META_FRAME_ALLOWS_VERTICAL_RESIZE) +- { +- frame_win_extents.bottom += mutter_draggable_border_width; +- frame_win_extents.top += mutter_draggable_border_width; +- frame_max_win_extents.bottom += mutter_draggable_border_width; +- frame_max_win_extents.top += mutter_draggable_border_width; +- } ++ if (flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE) ++ { ++ frame_win_extents.left += mutter_draggable_border_width; ++ frame_win_extents.right += mutter_draggable_border_width; ++ frame_max_win_extents.left += mutter_draggable_border_width; ++ frame_max_win_extents.right += mutter_draggable_border_width; ++ } ++ ++ if (flags & META_FRAME_ALLOWS_VERTICAL_RESIZE) ++ { ++ frame_win_extents.bottom += mutter_draggable_border_width; ++ frame_win_extents.top += mutter_draggable_border_width; ++ frame_max_win_extents.bottom += mutter_draggable_border_width; ++ frame_max_win_extents.top += mutter_draggable_border_width; ++ } + } + + w = d->border_layout.top.x2 - d->border_layout.top.x1 - +- d->context->left_space - d->context->right_space; ++ d->context->left_space - d->context->right_space; + + if (d->border_layout.rotation) +- lh = d->border_layout.left.x2 - d->border_layout.left.x1; ++ lh = d->border_layout.left.x2 - d->border_layout.left.x1; + else +- lh = d->border_layout.left.y2 - d->border_layout.left.y1; ++ lh = d->border_layout.left.y2 - d->border_layout.left.y1; + + if (d->border_layout.rotation) +- rh = d->border_layout.right.x2 - d->border_layout.right.x1; ++ rh = d->border_layout.right.x2 - d->border_layout.right.x1; + else +- rh = d->border_layout.right.y2 - d->border_layout.right.y1; ++ rh = d->border_layout.right.y2 - d->border_layout.right.y1; + +- left_stretch_offset = lh / 2; +- right_stretch_offset = rh / 2; +- top_stretch_offset = w - d->button_width - 1; +- bottom_stretch_offset = (d->border_layout.bottom.x2 - +- d->border_layout.bottom.x1 - +- d->context->left_space - +- d->context->right_space) / 2; +- +- nQuad = decor_set_lXrXtXbX_window_quads (quads, d->context, +- &d->border_layout, +- left_stretch_offset, +- right_stretch_offset, +- top_stretch_offset, +- bottom_stretch_offset); ++ left_stretch_offset = lh / 2; ++ right_stretch_offset = rh / 2; ++ top_stretch_offset = w - d->button_width - 1; ++ bottom_stretch_offset = (d->border_layout.bottom.x2 - d->border_layout.bottom.x1 - ++ d->context->left_space - d->context->right_space) / 2; ++ ++ nQuad = decor_set_lXrXtXbX_window_quads (quads, d->context, &d->border_layout, ++ left_stretch_offset, right_stretch_offset, ++ top_stretch_offset, bottom_stretch_offset); + + win_extents.top += d->frame->titlebar_height; + frame_win_extents.top += d->frame->titlebar_height; +@@ -115,47 +146,44 @@ + + if (d->frame_window) + { +- data = decor_alloc_property (nOffset, WINDOW_DECORATION_TYPE_WINDOW); +- decor_gen_window_property (data, nOffset - 1, &win_extents, &max_win_extents, 20, 20, +- frame_type, frame_state, frame_actions); ++ data = decor_alloc_property (nOffset, WINDOW_DECORATION_TYPE_WINDOW); ++ decor_gen_window_property (data, nOffset - 1, &win_extents, &max_win_extents, ++ 20, 20, frame_type, frame_state, frame_actions); + } + else + { +- data = decor_alloc_property (nOffset, WINDOW_DECORATION_TYPE_PIXMAP); +- decor_quads_to_property (data, nOffset - 1, cairo_xlib_surface_get_drawable (d->surface), +- &frame_win_extents, &win_extents, +- &frame_max_win_extents, &max_win_extents, +- ICON_SPACE + d->button_width, +- 0, +- quads, nQuad, frame_type, frame_state, frame_actions); ++ data = decor_alloc_property (nOffset, WINDOW_DECORATION_TYPE_PIXMAP); ++ decor_quads_to_property (data, nOffset - 1, cairo_xlib_surface_get_drawable (d->surface), ++ &frame_win_extents, &win_extents, ++ &frame_max_win_extents, &max_win_extents, ++ ICON_SPACE + d->button_width, ++ 0, quads, nQuad, frame_type, frame_state, frame_actions); + } + + gdk_error_trap_push (); + +- XChangeProperty (xdisplay, d->prop_xid, +- win_decor_atom, +- XA_INTEGER, +- 32, PropModeReplace, (guchar *) data, +- PROP_HEADER_SIZE + BASE_PROP_SIZE + QUAD_PROP_SIZE * N_QUADS_MAX); +- gdk_display_sync (gdk_display_get_default ()); ++ XChangeProperty (xdisplay, d->prop_xid, win_decor_atom, XA_INTEGER, ++ 32, PropModeReplace, (guchar *) data, ++ PROP_HEADER_SIZE + BASE_PROP_SIZE + QUAD_PROP_SIZE * N_QUADS_MAX); ++ gdk_display_sync (display); ++ + gdk_error_trap_pop_ignored (); + + free (data); + +- decor_update_blur_property (d, +- w, lh, +- top, top_stretch_offset, +- bottom, bottom_stretch_offset, +- left, left_stretch_offset, +- right, right_stretch_offset); ++ decor_update_blur_property (d, w, lh, ++ top, top_stretch_offset, ++ bottom, bottom_stretch_offset, ++ left, left_stretch_offset, ++ right, right_stretch_offset); + } + + static void + meta_get_corner_radius (const MetaFrameGeometry *fgeom, +- int *top_left_radius, +- int *top_right_radius, +- int *bottom_left_radius, +- int *bottom_right_radius) ++ int *top_left_radius, ++ int *top_right_radius, ++ int *bottom_left_radius, ++ int *bottom_right_radius) + { + *top_left_radius = fgeom->top_left_corner_rounded_radius; + *top_right_radius = fgeom->top_right_corner_rounded_radius; +@@ -165,7 +193,7 @@ + + static int + radius_to_width (int radius, +- int i) ++ int i) + { + float r1 = sqrt (radius) + radius; + float r2 = r1 * r1 - (r1 - (i + 0.5)) * (r1 - (i + 0.5)); +@@ -175,52 +203,51 @@ + + static Region + meta_get_top_border_region (const MetaFrameGeometry *fgeom, +- int width) ++ int width) + { +- Region corners_xregion, border_xregion; ++ Region corners_xregion; ++ Region border_xregion; + XRectangle xrect; +- int top_left_radius; +- int top_right_radius; +- int bottom_left_radius; +- int bottom_right_radius; +- int w, i; ++ int top_left_radius; ++ int top_right_radius; ++ int bottom_left_radius; ++ int bottom_right_radius; ++ int w; ++ int i; + + corners_xregion = XCreateRegion (); + +- meta_get_corner_radius (fgeom, +- &top_left_radius, +- &top_right_radius, +- &bottom_left_radius, +- &bottom_right_radius); ++ meta_get_corner_radius (fgeom, &top_left_radius, &top_right_radius, ++ &bottom_left_radius, &bottom_right_radius); + + if (top_left_radius) + { +- for (i = 0; i < top_left_radius; ++i) +- { +- w = radius_to_width (top_left_radius, i); +- +- xrect.x = 0; +- xrect.y = i; +- xrect.width = w; +- xrect.height = 1; ++ for (i = 0; i < top_left_radius; ++i) ++ { ++ w = radius_to_width (top_left_radius, i); ++ ++ xrect.x = 0; ++ xrect.y = i; ++ xrect.width = w; ++ xrect.height = 1; + +- XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); +- } ++ XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); ++ } + } + + if (top_right_radius) + { +- for (i = 0; i < top_right_radius; ++i) +- { +- w = radius_to_width (top_right_radius, i); +- +- xrect.x = width - w; +- xrect.y = i; +- xrect.width = w; +- xrect.height = 1; ++ for (i = 0; i < top_right_radius; ++i) ++ { ++ w = radius_to_width (top_right_radius, i); ++ ++ xrect.x = width - w; ++ xrect.y = i; ++ xrect.width = w; ++ xrect.height = 1; + +- XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); +- } ++ XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); ++ } + } + + border_xregion = XCreateRegion (); +@@ -241,52 +268,51 @@ + + static Region + meta_get_bottom_border_region (const MetaFrameGeometry *fgeom, +- int width) ++ int width) + { +- Region corners_xregion, border_xregion; ++ Region corners_xregion; ++ Region border_xregion; + XRectangle xrect; +- int top_left_radius; +- int top_right_radius; +- int bottom_left_radius; +- int bottom_right_radius; +- int w, i; ++ int top_left_radius; ++ int top_right_radius; ++ int bottom_left_radius; ++ int bottom_right_radius; ++ int w; ++ int i; + + corners_xregion = XCreateRegion (); + +- meta_get_corner_radius (fgeom, +- &top_left_radius, +- &top_right_radius, +- &bottom_left_radius, +- &bottom_right_radius); ++ meta_get_corner_radius (fgeom, &top_left_radius, &top_right_radius, ++ &bottom_left_radius, &bottom_right_radius); + + if (bottom_left_radius) + { +- for (i = 0; i < bottom_left_radius; ++i) +- { +- w = radius_to_width (bottom_left_radius, i); +- +- xrect.x = 0; +- xrect.y = fgeom->bottom_height - i - 1; +- xrect.width = w; +- xrect.height = 1; ++ for (i = 0; i < bottom_left_radius; ++i) ++ { ++ w = radius_to_width (bottom_left_radius, i); ++ ++ xrect.x = 0; ++ xrect.y = fgeom->bottom_height - i - 1; ++ xrect.width = w; ++ xrect.height = 1; + +- XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); +- } ++ XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); ++ } + } + + if (bottom_right_radius) + { +- for (i = 0; i < bottom_right_radius; ++i) +- { +- w = radius_to_width (bottom_right_radius, i); +- +- xrect.x = width - w; +- xrect.y = fgeom->bottom_height - i - 1; +- xrect.width = w; +- xrect.height = 1; ++ for (i = 0; i < bottom_right_radius; ++i) ++ { ++ w = radius_to_width (bottom_right_radius, i); ++ ++ xrect.x = width - w; ++ xrect.y = fgeom->bottom_height - i - 1; ++ xrect.width = w; ++ xrect.height = 1; + +- XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); +- } ++ XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); ++ } + } + + border_xregion = XCreateRegion (); +@@ -307,16 +333,16 @@ + + static Region + meta_get_left_border_region (const MetaFrameGeometry *fgeom, +- int height) ++ int height) + { +- Region border_xregion; ++ Region border_xregion; + XRectangle xrect; + + border_xregion = XCreateRegion (); + +- xrect.x = 0; +- xrect.y = 0; +- xrect.width = fgeom->left_width; ++ xrect.x = 0; ++ xrect.y = 0; ++ xrect.width = fgeom->left_width; + xrect.height = height - fgeom->top_height - fgeom->bottom_height; + + XUnionRectWithRegion (&xrect, border_xregion, border_xregion); +@@ -326,16 +352,16 @@ + + static Region + meta_get_right_border_region (const MetaFrameGeometry *fgeom, +- int height) ++ int height) + { +- Region border_xregion; ++ Region border_xregion; + XRectangle xrect; + + border_xregion = XCreateRegion (); + +- xrect.x = 0; +- xrect.y = 0; +- xrect.width = fgeom->right_width; ++ xrect.x = 0; ++ xrect.y = 0; ++ xrect.width = fgeom->right_width; + xrect.height = height - fgeom->top_height - fgeom->bottom_height; + + XUnionRectWithRegion (&xrect, border_xregion, border_xregion); +@@ -348,10 +374,10 @@ + { + if (state & IN_EVENT_WINDOW) + { +- if (state & PRESSED_EVENT_WINDOW) +- return META_BUTTON_STATE_PRESSED; ++ if (state & PRESSED_EVENT_WINDOW) ++ return META_BUTTON_STATE_PRESSED; + +- return META_BUTTON_STATE_PRELIGHT; ++ return META_BUTTON_STATE_PRELIGHT; + } + + return META_BUTTON_STATE_NORMAL; +@@ -360,271 +386,245 @@ + static MetaButtonType + meta_function_to_type (MetaButtonFunction function) + { +- switch (function) { ++ switch (function) ++ { + case META_BUTTON_FUNCTION_MENU: +- return META_BUTTON_TYPE_MENU; ++ return META_BUTTON_TYPE_MENU; + case META_BUTTON_FUNCTION_MINIMIZE: +- return META_BUTTON_TYPE_MINIMIZE; ++ return META_BUTTON_TYPE_MINIMIZE; + case META_BUTTON_FUNCTION_MAXIMIZE: +- return META_BUTTON_TYPE_MAXIMIZE; ++ return META_BUTTON_TYPE_MAXIMIZE; + case META_BUTTON_FUNCTION_CLOSE: +- return META_BUTTON_TYPE_CLOSE; ++ return META_BUTTON_TYPE_CLOSE; + case META_BUTTON_FUNCTION_SHADE: +- return META_BUTTON_TYPE_SHADE; ++ return META_BUTTON_TYPE_SHADE; + case META_BUTTON_FUNCTION_ABOVE: +- return META_BUTTON_TYPE_ABOVE; ++ return META_BUTTON_TYPE_ABOVE; + case META_BUTTON_FUNCTION_STICK: +- return META_BUTTON_TYPE_STICK; ++ return META_BUTTON_TYPE_STICK; + case META_BUTTON_FUNCTION_UNSHADE: +- return META_BUTTON_TYPE_UNSHADE; ++ return META_BUTTON_TYPE_UNSHADE; + case META_BUTTON_FUNCTION_UNABOVE: +- return META_BUTTON_TYPE_UNABOVE; ++ return META_BUTTON_TYPE_UNABOVE; + case META_BUTTON_FUNCTION_UNSTICK: +- return META_BUTTON_TYPE_UNSTICK; ++ return META_BUTTON_TYPE_UNSTICK; + default: +- break; ++ break; + } + + return META_BUTTON_TYPE_LAST; + } + + static MetaButtonState +-meta_button_state_for_button_type (decor_t *d, +- MetaButtonType type) ++meta_button_state_for_button_type (decor_t *d, ++ MetaButtonType type) + { +- switch (type) { ++ switch (type) ++ { + case META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND: +- type = meta_function_to_type (meta_button_layout.left_buttons[0]); +- break; ++ type = meta_function_to_type (meta_button_layout.left_buttons[0]); ++ break; + case META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND: +- type = meta_function_to_type (meta_button_layout.left_buttons[1]); +- break; ++ type = meta_function_to_type (meta_button_layout.left_buttons[1]); ++ break; + case META_BUTTON_TYPE_LEFT_RIGHT_BACKGROUND: +- type = meta_function_to_type (meta_button_layout.left_buttons[2]); +- break; ++ type = meta_function_to_type (meta_button_layout.left_buttons[2]); ++ break; + case META_BUTTON_TYPE_RIGHT_LEFT_BACKGROUND: +- type = meta_function_to_type (meta_button_layout.right_buttons[0]); +- break; ++ type = meta_function_to_type (meta_button_layout.right_buttons[0]); ++ break; + case META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND: +- type = meta_function_to_type (meta_button_layout.right_buttons[1]); +- break; ++ type = meta_function_to_type (meta_button_layout.right_buttons[1]); ++ break; + case META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND: +- type = meta_function_to_type (meta_button_layout.right_buttons[2]); ++ type = meta_function_to_type (meta_button_layout.right_buttons[2]); + default: +- break; ++ break; + } + +- switch (type) { ++ switch (type) ++ { + case META_BUTTON_TYPE_CLOSE: +- return meta_button_state (d->button_states[BUTTON_CLOSE]); ++ return meta_button_state (d->button_states[BUTTON_CLOSE]); + case META_BUTTON_TYPE_MAXIMIZE: +- return meta_button_state (d->button_states[BUTTON_MAX]); ++ return meta_button_state (d->button_states[BUTTON_MAX]); + case META_BUTTON_TYPE_MINIMIZE: +- return meta_button_state (d->button_states[BUTTON_MIN]); ++ return meta_button_state (d->button_states[BUTTON_MIN]); + case META_BUTTON_TYPE_MENU: +- return meta_button_state (d->button_states[BUTTON_MENU]); ++ return meta_button_state (d->button_states[BUTTON_MENU]); + case META_BUTTON_TYPE_SHADE: +- return meta_button_state (d->button_states[BUTTON_SHADE]); ++ return meta_button_state (d->button_states[BUTTON_SHADE]); + case META_BUTTON_TYPE_ABOVE: +- return meta_button_state (d->button_states[BUTTON_ABOVE]); ++ return meta_button_state (d->button_states[BUTTON_ABOVE]); + case META_BUTTON_TYPE_STICK: +- return meta_button_state (d->button_states[BUTTON_STICK]); ++ return meta_button_state (d->button_states[BUTTON_STICK]); + case META_BUTTON_TYPE_UNSHADE: +- return meta_button_state (d->button_states[BUTTON_UNSHADE]); ++ return meta_button_state (d->button_states[BUTTON_UNSHADE]); + case META_BUTTON_TYPE_UNABOVE: +- return meta_button_state (d->button_states[BUTTON_UNABOVE]); ++ return meta_button_state (d->button_states[BUTTON_UNABOVE]); + case META_BUTTON_TYPE_UNSTICK: +- return meta_button_state (d->button_states[BUTTON_UNSTICK]); ++ return meta_button_state (d->button_states[BUTTON_UNSTICK]); + default: +- break; ++ break; + } + + return META_BUTTON_STATE_NORMAL; + } + +-void +-meta_get_decoration_geometry (decor_t *d, +- MetaTheme *theme, +- MetaFrameFlags *flags, +- MetaFrameGeometry *fgeom, +- MetaButtonLayout *button_layout, +- MetaFrameType frame_type, +- GdkRectangle *clip) ++static void ++meta_get_decoration_geometry (decor_t *d, ++ MetaTheme *theme, ++ MetaFrameFlags *flags, ++ MetaFrameGeometry *fgeom, ++ MetaButtonLayout *button_layout, ++ MetaFrameType frame_type) + { +-#ifdef HAVE_METACITY_3_14_0 +- MetaFrameBorders borders; +-#endif +- gint left_width, right_width, top_height, bottom_height; ++ gint client_width; ++ gint client_height; + + if (!(frame_type < META_FRAME_TYPE_LAST)) +- frame_type = META_FRAME_TYPE_NORMAL; ++ frame_type = META_FRAME_TYPE_NORMAL; + + if (meta_button_layout_set) + { +- *button_layout = meta_button_layout; ++ *button_layout = meta_button_layout; + } + else + { +- gint i; ++ gint i; + +- button_layout->left_buttons[0] = META_BUTTON_FUNCTION_MENU; ++ button_layout->left_buttons[0] = META_BUTTON_FUNCTION_MENU; + +- for (i = 1; i < MAX_BUTTONS_PER_CORNER; ++i) +- button_layout->left_buttons[i] = META_BUTTON_FUNCTION_LAST; ++ for (i = 1; i < MAX_BUTTONS_PER_CORNER; ++i) ++ button_layout->left_buttons[i] = META_BUTTON_FUNCTION_LAST; + +- button_layout->right_buttons[0] = META_BUTTON_FUNCTION_MINIMIZE; +- button_layout->right_buttons[1] = META_BUTTON_FUNCTION_MAXIMIZE; +- button_layout->right_buttons[2] = META_BUTTON_FUNCTION_CLOSE; ++ button_layout->right_buttons[0] = META_BUTTON_FUNCTION_MINIMIZE; ++ button_layout->right_buttons[1] = META_BUTTON_FUNCTION_MAXIMIZE; ++ button_layout->right_buttons[2] = META_BUTTON_FUNCTION_CLOSE; + +- for (i = 3; i < MAX_BUTTONS_PER_CORNER; ++i) +- button_layout->right_buttons[i] = META_BUTTON_FUNCTION_LAST; ++ for (i = 3; i < MAX_BUTTONS_PER_CORNER; ++i) ++ button_layout->right_buttons[i] = META_BUTTON_FUNCTION_LAST; + } + + *flags = 0; + + if (d->actions & WNCK_WINDOW_ACTION_CLOSE) +- *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_DELETE; ++ *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_DELETE; + + if (d->actions & WNCK_WINDOW_ACTION_MINIMIZE) +- *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_MINIMIZE; ++ *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_MINIMIZE; + + if (d->actions & WNCK_WINDOW_ACTION_MAXIMIZE) +- *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_MAXIMIZE; ++ *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_MAXIMIZE; + + *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_MENU; + + if (d->actions & WNCK_WINDOW_ACTION_RESIZE) + { +- if (!(d->state & WNCK_WINDOW_STATE_MAXIMIZED_VERTICALLY)) +- *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_VERTICAL_RESIZE; +- if (!(d->state & WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY)) +- *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_HORIZONTAL_RESIZE; ++ if (!(d->state & WNCK_WINDOW_STATE_MAXIMIZED_VERTICALLY)) ++ *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_VERTICAL_RESIZE; ++ if (!(d->state & WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY)) ++ *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_HORIZONTAL_RESIZE; + } + + if (d->actions & WNCK_WINDOW_ACTION_MOVE) +- *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_MOVE; ++ *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_MOVE; + + if (d->actions & WNCK_WINDOW_ACTION_MAXIMIZE) +- *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_MAXIMIZE; ++ *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_MAXIMIZE; + + if (d->actions & WNCK_WINDOW_ACTION_SHADE) +- *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_SHADE; ++ *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_SHADE; + + if (d->active) +- *flags |= (MetaFrameFlags ) META_FRAME_HAS_FOCUS; ++ *flags |= (MetaFrameFlags ) META_FRAME_HAS_FOCUS; + + if ((d->state & META_MAXIMIZED) == META_MAXIMIZED) +- *flags |= (MetaFrameFlags ) META_FRAME_MAXIMIZED; ++ *flags |= (MetaFrameFlags ) META_FRAME_MAXIMIZED; + + if (d->state & WNCK_WINDOW_STATE_STICKY) +- *flags |= (MetaFrameFlags ) META_FRAME_STUCK; ++ *flags |= (MetaFrameFlags ) META_FRAME_STUCK; + + if (d->state & WNCK_WINDOW_STATE_FULLSCREEN) +- *flags |= (MetaFrameFlags ) META_FRAME_FULLSCREEN; ++ *flags |= (MetaFrameFlags ) META_FRAME_FULLSCREEN; + + if (d->state & WNCK_WINDOW_STATE_SHADED) +- *flags |= (MetaFrameFlags ) META_FRAME_SHADED; ++ *flags |= (MetaFrameFlags ) META_FRAME_SHADED; + + if (d->state & WNCK_WINDOW_STATE_ABOVE) +- *flags |= (MetaFrameFlags ) META_FRAME_ABOVE; +- +-#ifdef HAVE_METACITY_3_14_0 +- meta_theme_get_frame_borders (theme, +- frame_type, +- d->frame->text_height, +- *flags, +- &borders); +- top_height = borders.visible.top; +- bottom_height = borders.visible.bottom; +- left_width = borders.visible.left; +- right_width = borders.visible.right; +-#else +- meta_theme_get_frame_borders (theme, +- frame_type, +- d->frame->text_height, +- *flags, +- &top_height, +- &bottom_height, +- &left_width, +- &right_width); +-#endif ++ *flags |= (MetaFrameFlags ) META_FRAME_ABOVE; + +- clip->x = d->context->left_space - left_width; +- clip->y = d->context->top_space - top_height; +- +- clip->width = d->border_layout.top.x2 - d->border_layout.top.x1; +- clip->width -= d->context->right_space + d->context->left_space; ++ client_width = d->border_layout.top.x2 - d->border_layout.top.x1; ++ client_width -= d->context->right_space + d->context->left_space; + + if (d->border_layout.rotation) +- clip->height = d->border_layout.left.x2 - d->border_layout.left.x1; ++ client_height = d->border_layout.left.x2 - d->border_layout.left.x1; + else +- clip->height = d->border_layout.left.y2 - d->border_layout.left.y1; +- +- meta_theme_calc_geometry (theme, +- frame_type, +- d->frame->text_height, +- *flags, +- clip->width, +- clip->height, +- button_layout, +- fgeom); ++ client_height = d->border_layout.left.y2 - d->border_layout.left.y1; + +- clip->width += left_width + right_width; +- clip->height += top_height + bottom_height; ++ meta_theme_calc_geometry (theme, frame_type, d->frame->text_height, ++ *flags, client_width, client_height, ++ button_layout, fgeom); + } + + void + meta_draw_window_decoration (decor_t *d) + { +- Display *xdisplay = +- GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); ++ GdkDisplay *display; ++ Display *xdisplay; + cairo_surface_t *surface; +- Picture src; +- MetaButtonState button_states [META_BUTTON_TYPE_LAST]; +- MetaButtonLayout button_layout; ++ Picture src; ++ MetaButtonState button_states [META_BUTTON_TYPE_LAST]; ++ MetaButtonLayout button_layout; + MetaFrameGeometry fgeom; +- MetaFrameFlags flags; +- MetaFrameType frame_type; +- MetaTheme *theme; ++ MetaFrameFlags flags; ++ MetaFrameType frame_type; ++ MetaTheme *theme; + GtkStyleContext *context; +- cairo_t *cr; +- gint i; +- GdkRectangle clip; +- Region top_region = NULL; +- Region bottom_region = NULL; +- Region left_region = NULL; +- Region right_region = NULL; +- gdouble meta_active_opacity, meta_inactive_opacity; +- gboolean meta_active_shade_opacity, meta_inactive_shade_opacity; ++ cairo_t *cr; ++ gint i; ++ Region top_region; ++ Region bottom_region; ++ Region left_region; ++ Region right_region; ++ gdouble meta_active_opacity; ++ gdouble meta_inactive_opacity; ++ gboolean meta_active_shade_opacity; ++ gboolean meta_inactive_shade_opacity; ++ double alpha; ++ gboolean shade_alpha; ++ MetaFrameStyle *frame_style; ++ GtkWidget *style_window; ++ GdkRGBA bg_rgba; ++ ++ if (!d->surface || !d->picture) ++ return; ++ ++ display = gdk_display_get_default (); ++ xdisplay = gdk_x11_display_get_xdisplay (display); ++ ++ top_region = NULL; ++ bottom_region = NULL; ++ left_region = NULL; ++ right_region = NULL; + + g_object_get (settings, "metacity-active-opacity", &meta_active_opacity, NULL); + g_object_get (settings, "metacity-inactive-opacity", &meta_inactive_opacity, NULL); + g_object_get (settings, "metacity-active-shade-opacity", &meta_active_shade_opacity, NULL); + g_object_get (settings, "metacity-inactive-shade-opacity", &meta_inactive_shade_opacity, NULL); + +- double alpha = (d->active) ? meta_active_opacity : meta_inactive_opacity; +- gboolean shade_alpha = (d->active) ? meta_active_shade_opacity : +- meta_inactive_shade_opacity; +- MetaFrameStyle *frame_style; +- GtkWidget *style_window; +- GdkRGBA bg_rgba; +- +- if (!d->surface || !d->picture) +- return; ++ alpha = (d->active) ? meta_active_opacity : meta_inactive_opacity; ++ shade_alpha = (d->active) ? meta_active_shade_opacity : meta_inactive_shade_opacity; + + if (decoration_alpha == 1.0) +- alpha = 1.0; ++ alpha = 1.0; + + if (cairo_xlib_surface_get_depth (d->surface) == 32) +- { +- context = gtk_widget_get_style_context (d->frame->style_window_rgba); +- style_window = d->frame->style_window_rgba; +- } ++ style_window = d->frame->style_window_rgba; + else +- { +- context = gtk_widget_get_style_context (d->frame->style_window_rgb); +- style_window = d->frame->style_window_rgb; +- } ++ style_window = d->frame->style_window_rgb; ++ ++ context = gtk_widget_get_style_context (style_window); + + cr = cairo_create (d->buffer_surface ? d->buffer_surface : d->surface); + +@@ -635,31 +635,28 @@ + frame_type = meta_frame_type_from_string (d->frame->type); + + if (frame_type == META_FRAME_TYPE_LAST) +- frame_type = META_FRAME_TYPE_NORMAL; ++ frame_type = META_FRAME_TYPE_NORMAL; + + meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout, +- frame_type, &clip); ++ frame_type); + + if ((d->prop_xid || !d->buffer_surface) && !d->frame_window) +- draw_shadow_background (d, cr, d->shadow, d->context); ++ draw_shadow_background (d, cr, d->shadow, d->context); + + for (i = 0; i < META_BUTTON_TYPE_LAST; ++i) +- button_states[i] = meta_button_state_for_button_type (d, i); ++ button_states[i] = meta_button_state_for_button_type (d, i); + +- frame_style = meta_theme_get_frame_style (theme, +- frame_type, +- flags); ++ frame_style = meta_theme_get_frame_style (theme, frame_type, flags); + + gtk_style_context_get_background_color (context, GTK_STATE_FLAG_NORMAL, &bg_rgba); + bg_rgba.alpha = 1.0; + + if (frame_style->window_background_color) + { +- meta_color_spec_render (frame_style->window_background_color, +- gtk_widget_get_style_context (style_window), +- &bg_rgba); ++ meta_color_spec_render (frame_style->window_background_color, ++ context, &bg_rgba); + +- bg_rgba.alpha = frame_style->window_background_alpha / 255.0; ++ bg_rgba.alpha = frame_style->window_background_alpha / 255.0; + } + + /* Draw something that will be almost invisible to user. This is hacky way +@@ -671,286 +668,290 @@ + + cairo_destroy (cr); + +- if (d->frame_window) +- surface = create_surface (clip.width, clip.height, d->frame->style_window_rgb); +- else +- surface = create_surface (clip.width, clip.height, d->frame->style_window_rgba); +- +- cr = cairo_create (surface); +- gdk_cairo_set_source_rgba (cr, &bg_rgba); +- cairo_set_operator (cr, CAIRO_OPERATOR_OVER); ++ if (d->frame_window) ++ surface = create_surface (fgeom.width, fgeom.height, d->frame->style_window_rgb); ++ else ++ surface = create_surface (fgeom.width, fgeom.height, d->frame->style_window_rgba); ++ ++ cr = cairo_create (surface); ++ gdk_cairo_set_source_rgba (cr, &bg_rgba); ++ cairo_set_operator (cr, CAIRO_OPERATOR_OVER); + +- src = XRenderCreatePicture (xdisplay, cairo_xlib_surface_get_drawable (surface), ++ src = XRenderCreatePicture (xdisplay, cairo_xlib_surface_get_drawable (surface), + get_format_for_surface (d, surface), 0, NULL); + + cairo_paint (cr); +- meta_theme_draw_frame (theme, +- style_window, +- cr, +- frame_type, +- flags, +- clip.width - fgeom.left_width - fgeom.right_width, +- clip.height - fgeom.top_height - fgeom.bottom_height, +- d->layout, +- d->frame->text_height, +- &button_layout, +- button_states, +- d->icon_pixbuf, +- NULL); ++ meta_theme_draw_frame (theme, style_window, cr, frame_type, flags, ++ fgeom.width - fgeom.left_width - fgeom.right_width, ++ fgeom.height - fgeom.top_height - fgeom.bottom_height, ++ d->layout, d->frame->text_height, &button_layout, ++ button_states, d->icon_pixbuf, NULL); + + if (fgeom.top_height) +- { +- top_region = meta_get_top_border_region (&fgeom, clip.width); ++ { ++ top_region = meta_get_top_border_region (&fgeom, fgeom.width); ++ ++ decor_blend_border_picture (xdisplay, d->context, src, ++ 0, 0, ++ d->picture, &d->border_layout, ++ BORDER_TOP, top_region, ++ alpha * 0xffff, shade_alpha, 0); ++ } + +- decor_blend_border_picture (xdisplay, +- d->context, +- src, +- 0, 0, +- d->picture, +- &d->border_layout, +- BORDER_TOP, +- top_region, +- alpha * 0xffff, +- shade_alpha, +- 0); +- } +- +- if (fgeom.bottom_height) +- { +- bottom_region = meta_get_bottom_border_region (&fgeom, clip.width); +- +- decor_blend_border_picture (xdisplay, +- d->context, +- src, +- 0, clip.height - fgeom.bottom_height, +- d->picture, +- &d->border_layout, +- BORDER_BOTTOM, +- bottom_region, +- alpha * 0xffff, +- shade_alpha, +- 0); +- +- } +- +- if (fgeom.left_width) +- { +- left_region = meta_get_left_border_region (&fgeom, clip.height); +- +- decor_blend_border_picture (xdisplay, +- d->context, +- src, +- 0, fgeom.top_height, +- d->picture, +- &d->border_layout, +- BORDER_LEFT, +- left_region, +- alpha * 0xffff, +- shade_alpha, +- 0); +- } +- +- if (fgeom.right_width) +- { +- right_region = meta_get_right_border_region (&fgeom, clip.height); +- +- decor_blend_border_picture (xdisplay, +- d->context, +- src, +- clip.width - fgeom.right_width, fgeom.top_height, +- d->picture, +- &d->border_layout, +- BORDER_RIGHT, +- right_region, +- alpha * 0xffff, +- shade_alpha, +- 0); +- } +- +- cairo_destroy (cr); +- cairo_surface_destroy (surface); +- XRenderFreePicture (xdisplay, src); ++ if (fgeom.bottom_height) ++ { ++ bottom_region = meta_get_bottom_border_region (&fgeom, fgeom.width); ++ ++ decor_blend_border_picture (xdisplay, d->context, src, ++ 0, fgeom.height - fgeom.bottom_height, ++ d->picture, &d->border_layout, ++ BORDER_BOTTOM, bottom_region, ++ alpha * 0xffff, shade_alpha, 0); ++ } ++ ++ if (fgeom.left_width) ++ { ++ left_region = meta_get_left_border_region (&fgeom, fgeom.height); ++ ++ decor_blend_border_picture (xdisplay, d->context, src, ++ 0, fgeom.top_height, ++ d->picture, &d->border_layout, ++ BORDER_LEFT, left_region, ++ alpha * 0xffff, shade_alpha, 0); ++ } ++ ++ if (fgeom.right_width) ++ { ++ right_region = meta_get_right_border_region (&fgeom, fgeom.height); ++ ++ decor_blend_border_picture (xdisplay, d->context, src, ++ fgeom.width - fgeom.right_width, fgeom.top_height, ++ d->picture, &d->border_layout, ++ BORDER_RIGHT, right_region, ++ alpha * 0xffff, shade_alpha, 0); ++ } ++ ++ cairo_destroy (cr); ++ cairo_surface_destroy (surface); ++ XRenderFreePicture (xdisplay, src); + + copy_to_front_buffer (d); + + if (d->frame_window) + { +- GdkWindow *gdk_frame_window = gtk_widget_get_window (d->decor_window); +- GdkPixbuf *pixbuf = gdk_pixbuf_get_from_surface (d->surface, 0, 0, d->width, d->height); ++ GdkWindow *gdk_frame_window; ++ GdkPixbuf *pixbuf; ++ ++ gdk_frame_window = gtk_widget_get_window (d->decor_window); + +- gtk_image_set_from_pixbuf (GTK_IMAGE (d->decor_image), pixbuf); +- g_object_unref (pixbuf); ++ pixbuf = gdk_pixbuf_get_from_surface (d->surface, 0, 0, d->width, d->height); ++ gtk_image_set_from_pixbuf (GTK_IMAGE (d->decor_image), pixbuf); ++ g_object_unref (pixbuf); ++ ++ gdk_window_move_resize (gdk_frame_window, ++ d->context->left_corner_space - 1, ++ d->context->top_corner_space - 1, ++ d->width, ++ d->height); + +- gtk_window_resize (GTK_WINDOW (d->decor_window), d->width, d->height); +- gdk_window_move (gdk_frame_window, +- d->context->left_corner_space - 1, +- d->context->top_corner_space - 1); +- gdk_window_lower (gdk_frame_window); ++ gdk_window_lower (gdk_frame_window); + } + + if (d->prop_xid) + { +- /* translate from frame to client window space */ +- if (top_region) +- XOffsetRegion (top_region, -fgeom.left_width, -fgeom.top_height); +- if (bottom_region) +- XOffsetRegion (bottom_region, -fgeom.left_width, 0); +- if (left_region) +- XOffsetRegion (left_region, -fgeom.left_width, 0); +- +- decor_update_meta_window_property (d, theme, flags, +- top_region, +- bottom_region, +- left_region, +- right_region); +- d->prop_xid = 0; ++ /* translate from frame to client window space */ ++ if (top_region) ++ XOffsetRegion (top_region, -fgeom.left_width, -fgeom.top_height); ++ if (bottom_region) ++ XOffsetRegion (bottom_region, -fgeom.left_width, 0); ++ if (left_region) ++ XOffsetRegion (left_region, -fgeom.left_width, 0); ++ ++ decor_update_meta_window_property (d, theme, flags, ++ top_region, bottom_region, ++ left_region, right_region); ++ ++ d->prop_xid = 0; + } + + if (top_region) +- XDestroyRegion (top_region); ++ XDestroyRegion (top_region); + if (bottom_region) +- XDestroyRegion (bottom_region); ++ XDestroyRegion (bottom_region); + if (left_region) +- XDestroyRegion (left_region); ++ XDestroyRegion (left_region); + if (right_region) +- XDestroyRegion (right_region); ++ XDestroyRegion (right_region); + } + +-void ++static void + meta_calc_button_size (decor_t *d) + { ++ MetaTheme *theme; ++ MetaFrameType frame_type; ++ MetaFrameFlags flags; ++ MetaFrameGeometry fgeom; ++ MetaButtonLayout button_layout; ++ MetaFrameBorders borders; ++ gint mutter_draggable_border_width; + gint i, min_x, x, y, w, h, width; + ++ if (!d->context) ++ { ++ d->button_width = 0; ++ return; ++ } ++ ++ theme = meta_theme_get_current (); ++ ++ frame_type = meta_frame_type_from_string (d->frame->type); ++ if (!(frame_type < META_FRAME_TYPE_LAST)) ++ frame_type = META_FRAME_TYPE_NORMAL; ++ ++ meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout, ++ frame_type); ++ meta_theme_get_frame_borders (theme, frame_type, d->frame->text_height, ++ flags, &borders); ++ ++ mutter_draggable_border_width = 0; ++ g_object_get (settings, "draggable-border-width", &mutter_draggable_border_width, NULL); ++ + width = d->border_layout.top.x2 - d->border_layout.top.x1 - +- d->context->left_space - d->context->right_space; ++ d->context->left_space - d->context->right_space + ++ borders.visible.left + borders.visible.right; ++ ++ if (flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE) ++ width += mutter_draggable_border_width; ++ + min_x = width; + + for (i = 0; i < 3; ++i) + { +- static guint button_actions[3] = { +- WNCK_WINDOW_ACTION_CLOSE, +- WNCK_WINDOW_ACTION_MAXIMIZE, +- WNCK_WINDOW_ACTION_MINIMIZE +- }; +- +- if (d->actions & button_actions[i]) +- { +- if (meta_get_button_position (d, i, width, 256, +- &x, &y, &w, &h)) +- { +- if (x > width / 2 && x < min_x) +- min_x = x; +- } +- } ++ static guint button_actions[3] = { ++ WNCK_WINDOW_ACTION_CLOSE, ++ WNCK_WINDOW_ACTION_MAXIMIZE, ++ WNCK_WINDOW_ACTION_MINIMIZE ++ }; ++ ++ if (d->actions & button_actions[i]) ++ { ++ if (meta_get_button_position (d, i, width, 256, &x, &y, &w, &h)) ++ { ++ if (x > width / 2 && x < min_x) ++ min_x = x; ++ } ++ } + } + +- d->button_width = width - min_x + 6; ++ d->button_width = width - min_x; + } + +-gboolean +-meta_get_button_position (decor_t *d, +- gint i, +- gint width, +- gint height, +- gint *x, +- gint *y, +- gint *w, +- gint *h) ++static MetaButtonFunction ++button_to_meta_button_function (gint i) + { +- MetaButtonLayout button_layout; +- MetaFrameGeometry fgeom; +- MetaFrameFlags flags; +- MetaTheme *theme; +- +- GdkRectangle clip; ++ switch (i) ++ { ++ case BUTTON_MENU: ++ return META_BUTTON_FUNCTION_MENU; ++ case BUTTON_MIN: ++ return META_BUTTON_FUNCTION_MINIMIZE; ++ case BUTTON_MAX: ++ return META_BUTTON_FUNCTION_MAXIMIZE; ++ case BUTTON_CLOSE: ++ return META_BUTTON_FUNCTION_CLOSE; ++ case BUTTON_SHADE: ++ return META_BUTTON_FUNCTION_SHADE; ++ case BUTTON_ABOVE: ++ return META_BUTTON_FUNCTION_ABOVE; ++ case BUTTON_STICK: ++ return META_BUTTON_FUNCTION_STICK; ++ case BUTTON_UNSHADE: ++ return META_BUTTON_FUNCTION_UNSHADE; ++ case BUTTON_UNABOVE: ++ return META_BUTTON_FUNCTION_UNABOVE; ++ case BUTTON_UNSTICK: ++ return META_BUTTON_FUNCTION_UNSTICK; ++ default: ++ break; ++ } + +- MetaButtonSpace *space; ++ return META_BUTTON_FUNCTION_LAST; ++} + +- gint mutter_draggable_border_width = 0; ++gboolean ++meta_get_button_position (decor_t *d, ++ gint i, ++ gint width, ++ gint height, ++ gint *x, ++ gint *y, ++ gint *w, ++ gint *h) ++{ ++ MetaButtonLayout button_layout; ++ MetaFrameGeometry fgeom; ++ MetaFrameFlags flags; ++ MetaTheme *theme; ++ MetaButtonFunction button_function; ++ MetaButtonSpace *space; ++ gint mutter_draggable_border_width; + ++ mutter_draggable_border_width = 0; + g_object_get (settings, "draggable-border-width", &mutter_draggable_border_width, NULL); + + if (!d->context) + { +- /* undecorated windows implicitly have no buttons */ +- return FALSE; ++ /* undecorated windows implicitly have no buttons */ ++ return FALSE; + } + + theme = meta_theme_get_current (); + + meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout, +- meta_frame_type_from_string (d->frame->type), +- &clip); ++ meta_frame_type_from_string (d->frame->type)); + +- switch (i) { +- case BUTTON_MENU: +- if (!meta_button_present (&button_layout, META_BUTTON_FUNCTION_MENU)) +- return FALSE; ++ button_function = button_to_meta_button_function (i); ++ if (!meta_button_present (&button_layout, button_function)) ++ return FALSE; + +- space = &fgeom.menu_rect; +- break; ++ switch (i) ++ { ++ case BUTTON_MENU: ++ space = &fgeom.menu_rect; ++ break; + case BUTTON_MIN: +- if (!meta_button_present (&button_layout, +- META_BUTTON_FUNCTION_MINIMIZE)) +- return FALSE; +- +- space = &fgeom.min_rect; +- break; ++ space = &fgeom.min_rect; ++ break; + case BUTTON_MAX: +- if (!meta_button_present (&button_layout, +- META_BUTTON_FUNCTION_MAXIMIZE)) +- return FALSE; +- +- space = &fgeom.max_rect; +- break; ++ space = &fgeom.max_rect; ++ break; + case BUTTON_CLOSE: +- if (!meta_button_present (&button_layout, META_BUTTON_FUNCTION_CLOSE)) +- return FALSE; +- +- space = &fgeom.close_rect; +- break; ++ space = &fgeom.close_rect; ++ break; + case BUTTON_SHADE: +- if (!meta_button_present (&button_layout, META_BUTTON_FUNCTION_SHADE)) +- return FALSE; +- +- space = &fgeom.shade_rect; +- break; ++ space = &fgeom.shade_rect; ++ break; + case BUTTON_ABOVE: +- if (!meta_button_present (&button_layout, META_BUTTON_FUNCTION_ABOVE)) +- return FALSE; +- +- space = &fgeom.above_rect; +- break; ++ space = &fgeom.above_rect; ++ break; + case BUTTON_STICK: +- if (!meta_button_present (&button_layout, META_BUTTON_FUNCTION_STICK)) +- return FALSE; +- +- space = &fgeom.stick_rect; +- break; ++ space = &fgeom.stick_rect; ++ break; + case BUTTON_UNSHADE: +- if (!meta_button_present (&button_layout, META_BUTTON_FUNCTION_UNSHADE)) +- return FALSE; +- +- space = &fgeom.unshade_rect; +- break; ++ space = &fgeom.unshade_rect; ++ break; + case BUTTON_UNABOVE: +- if (!meta_button_present (&button_layout, META_BUTTON_FUNCTION_UNABOVE)) +- return FALSE; +- +- space = &fgeom.unabove_rect; +- break; ++ space = &fgeom.unabove_rect; ++ break; + case BUTTON_UNSTICK: +- if (!meta_button_present (&button_layout, META_BUTTON_FUNCTION_UNSTICK)) +- return FALSE; +- +- space = &fgeom.unstick_rect; +- break; ++ space = &fgeom.unstick_rect; ++ break; + default: +- return FALSE; ++ return FALSE; + } + + if (!space->clickable.width && !space->clickable.height) +- return FALSE; ++ return FALSE; + + *x = space->clickable.x; + *y = space->clickable.y; +@@ -959,19 +960,15 @@ + + if (d->frame_window) + { +- *x += d->frame->win_extents.left + 4; +- *y += d->frame->win_extents.top + 2; ++ *x += d->frame->win_extents.left + 4; ++ *y += d->frame->win_extents.top + 2; + } + + if (flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE) +- { +- *x += mutter_draggable_border_width; +- } ++ *x += mutter_draggable_border_width; + + if (flags & META_FRAME_ALLOWS_VERTICAL_RESIZE) +- { +- *y += mutter_draggable_border_width; +- } ++ *y += mutter_draggable_border_width; + + return TRUE; + } +@@ -979,14 +976,16 @@ + gfloat + meta_get_title_scale (decor_frame_t *frame) + { +- MetaTheme *theme = meta_theme_get_current (); +- MetaFrameType type; +- MetaFrameFlags flags = 0xc33; /* fixme */ ++ MetaTheme *theme; ++ MetaFrameType type; ++ MetaFrameFlags flags; + ++ theme = meta_theme_get_current (); + type = meta_frame_type_from_string (frame->type); ++ flags = 0xc33; /* fixme */ + + if (type == META_FRAME_TYPE_LAST) +- return 1.0f; ++ return 1.0f; + + gfloat scale = meta_theme_get_title_scale (theme, type, flags); + +@@ -995,381 +994,367 @@ + + gboolean + meta_calc_decoration_size (decor_t *d, +- gint w, +- gint h, +- gint name_width, +- gint *width, +- gint *height) ++ gint w, ++ gint h, ++ gint name_width, ++ gint *width, ++ gint *height) + { +- decor_layout_t layout; ++ decor_layout_t layout; + decor_context_t *context; +- decor_shadow_t *shadow; ++ decor_shadow_t *shadow; + + if (!d->decorated) +- return FALSE; ++ return FALSE; + + if ((d->state & META_MAXIMIZED) == META_MAXIMIZED) + { +- if (!d->frame_window) +- { +- if (d->active) +- { +- context = &d->frame->max_window_context_active; +- shadow = d->frame->max_border_shadow_active; +- } +- else +- { +- context = &d->frame->max_window_context_inactive; +- shadow = d->frame->max_border_shadow_inactive; +- } +- } +- else +- { +- context = &d->frame->max_window_context_no_shadow; +- shadow = d->frame->max_border_no_shadow; +- } ++ if (!d->frame_window) ++ { ++ if (d->active) ++ { ++ context = &d->frame->max_window_context_active; ++ shadow = d->frame->max_border_shadow_active; ++ } ++ else ++ { ++ context = &d->frame->max_window_context_inactive; ++ shadow = d->frame->max_border_shadow_inactive; ++ } ++ } ++ else ++ { ++ context = &d->frame->max_window_context_no_shadow; ++ shadow = d->frame->max_border_no_shadow; ++ } + } + else + { +- if (!d->frame_window) +- { +- if (d->active) +- { +- context = &d->frame->window_context_active; +- shadow = d->frame->border_shadow_active; +- } +- else +- { +- context = &d->frame->window_context_inactive; +- shadow = d->frame->border_shadow_inactive; +- } +- } +- else +- { +- context = &d->frame->window_context_no_shadow; +- shadow = d->frame->border_no_shadow; +- } ++ if (!d->frame_window) ++ { ++ if (d->active) ++ { ++ context = &d->frame->window_context_active; ++ shadow = d->frame->border_shadow_active; ++ } ++ else ++ { ++ context = &d->frame->window_context_inactive; ++ shadow = d->frame->border_shadow_inactive; ++ } ++ } ++ else ++ { ++ context = &d->frame->window_context_no_shadow; ++ shadow = d->frame->border_no_shadow; ++ } + } + + if (!d->frame_window) + { +- decor_get_best_layout (context, w, h, &layout); ++ decor_get_best_layout (context, w, h, &layout); ++ ++ if (context != d->context || memcmp (&layout, &d->border_layout, sizeof (layout))) ++ { ++ *width = layout.width; ++ *height = layout.height; + +- if (context != d->context || +- memcmp (&layout, &d->border_layout, sizeof (layout))) +- { +- *width = layout.width; +- *height = layout.height; +- +- d->border_layout = layout; +- d->context = context; +- d->shadow = shadow; ++ d->border_layout = layout; ++ d->context = context; ++ d->shadow = shadow; + +- meta_calc_button_size (d); ++ meta_calc_button_size (d); + +- return TRUE; +- } ++ return TRUE; ++ } + } + else + { +- if ((d->state & META_MAXIMIZED) == META_MAXIMIZED) +- decor_get_default_layout (context, d->client_width, +- d->client_height - d->frame->titlebar_height, +- &layout); +- else +- decor_get_default_layout (context, d->client_width, +- d->client_height, &layout); +- +- *width = layout.width; +- *height = layout.height; +- +- d->border_layout = layout; +- d->shadow = shadow; +- d->context = context; ++ if ((d->state & META_MAXIMIZED) == META_MAXIMIZED) ++ decor_get_default_layout (context, d->client_width, ++ d->client_height - d->frame->titlebar_height, ++ &layout); ++ else ++ decor_get_default_layout (context, d->client_width, ++ d->client_height, &layout); ++ ++ *width = layout.width; ++ *height = layout.height; ++ ++ d->border_layout = layout; ++ d->shadow = shadow; ++ d->context = context; + +- meta_calc_button_size (d); ++ meta_calc_button_size (d); + +- return TRUE; ++ return TRUE; + } + + return FALSE; + } + +-gboolean +-meta_button_present (MetaButtonLayout *button_layout, +- MetaButtonFunction function) +-{ +- int i; +- +- for (i = 0; i < MAX_BUTTONS_PER_CORNER; ++i) +- if (button_layout->left_buttons[i] == function) +- return TRUE; +- +- for (i = 0; i < MAX_BUTTONS_PER_CORNER; ++i) +- if (button_layout->right_buttons[i] == function) +- return TRUE; +- +- return FALSE; +-} +- + #define TOP_RESIZE_HEIGHT 2 + #define RESIZE_EXTENDS 15 + + void + meta_get_event_window_position (decor_t *d, +- gint i, +- gint j, +- gint width, +- gint height, +- gint *x, +- gint *y, +- gint *w, +- gint *h) ++ gint i, ++ gint j, ++ gint width, ++ gint height, ++ gint *x, ++ gint *y, ++ gint *w, ++ gint *h) + { +- MetaButtonLayout button_layout; ++ MetaButtonLayout button_layout; + MetaFrameGeometry fgeom; +- MetaFrameFlags flags; +- MetaTheme *theme; +- GdkRectangle clip; +- +- gint mutter_draggable_border_width = 0; ++ MetaFrameFlags flags; ++ MetaTheme *theme; ++ gint mutter_draggable_border_width; + ++ mutter_draggable_border_width = 0; + g_object_get (settings, "draggable-border-width", &mutter_draggable_border_width, NULL); + + theme = meta_theme_get_current (); + + meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout, +- meta_frame_type_from_string (d->frame->type), +- &clip); ++ meta_frame_type_from_string (d->frame->type)); + +- width += fgeom.right_width + fgeom.left_width; +- height += fgeom.top_height + fgeom.bottom_height; ++ width += fgeom.right_width + fgeom.left_width; ++ height += fgeom.top_height + fgeom.bottom_height; + +- switch (i) { ++ switch (i) ++ { + case 2: /* bottom */ +- switch (j) { +- case 2: /* bottom right */ +- if (d->frame_window) +- { +- *x = width - fgeom.right_width - RESIZE_EXTENDS + +- d->frame->win_extents.left + 2; +- *y = height - fgeom.bottom_height - RESIZE_EXTENDS + +- d->frame->win_extents.top + 2; +- } +- else +- { +- *x = width - fgeom.right_width - RESIZE_EXTENDS; +- *y = height - fgeom.bottom_height - RESIZE_EXTENDS; +- } +- *w = fgeom.right_width + RESIZE_EXTENDS; +- *h = fgeom.bottom_height + RESIZE_EXTENDS; +- +- if (!d->frame_window) +- { +- *x += mutter_draggable_border_width; +- *y += mutter_draggable_border_width; +- *w += mutter_draggable_border_width; +- *h += mutter_draggable_border_width; +- } +- +- break; +- case 1: /* bottom */ +- *x = fgeom.left_width + RESIZE_EXTENDS; +- *y = height - fgeom.bottom_height; +- if (d->frame_window) +- *y += d->frame->win_extents.top + 2; +- *w = width - fgeom.left_width - fgeom.right_width - +- (2 * RESIZE_EXTENDS); +- *h = fgeom.bottom_height; +- +- if (!d->frame_window) +- { +- *x -= mutter_draggable_border_width; +- *y += mutter_draggable_border_width; +- *h += mutter_draggable_border_width; +- *w += mutter_draggable_border_width * 2; +- } +- +- break; +- case 0: /* bottom left */ +- default: +- *x = 0; +- *y = height - fgeom.bottom_height - RESIZE_EXTENDS; +- if (d->frame_window) +- { +- *x += d->frame->win_extents.left + 4; +- *y += d->frame->win_extents.bottom + 2; +- } +- *w = fgeom.left_width + RESIZE_EXTENDS; +- *h = fgeom.bottom_height + RESIZE_EXTENDS; +- +- if (!d->frame_window) +- { +- *y += mutter_draggable_border_width; +- *w += mutter_draggable_border_width; +- *h += mutter_draggable_border_width; +- } +- +- break; +- } +- break; ++ switch (j) ++ { ++ case 2: /* bottom right */ ++ if (d->frame_window) ++ { ++ *x = width - fgeom.right_width - RESIZE_EXTENDS + ++ d->frame->win_extents.left + 2; ++ *y = height - fgeom.bottom_height - RESIZE_EXTENDS + ++ d->frame->win_extents.top + 2; ++ } ++ else ++ { ++ *x = width - fgeom.right_width - RESIZE_EXTENDS; ++ *y = height - fgeom.bottom_height - RESIZE_EXTENDS; ++ } ++ ++ *w = fgeom.right_width + RESIZE_EXTENDS; ++ *h = fgeom.bottom_height + RESIZE_EXTENDS; ++ ++ if (!d->frame_window) ++ { ++ *x += mutter_draggable_border_width; ++ *y += mutter_draggable_border_width; ++ *w += mutter_draggable_border_width; ++ *h += mutter_draggable_border_width; ++ } ++ break; ++ case 1: /* bottom */ ++ *x = fgeom.left_width + RESIZE_EXTENDS; ++ *y = height - fgeom.bottom_height; ++ ++ if (d->frame_window) ++ *y += d->frame->win_extents.top + 2; ++ ++ *w = width - fgeom.left_width - fgeom.right_width - (2 * RESIZE_EXTENDS); ++ *h = fgeom.bottom_height; ++ ++ if (!d->frame_window) ++ { ++ *x -= mutter_draggable_border_width; ++ *y += mutter_draggable_border_width; ++ *h += mutter_draggable_border_width; ++ *w += mutter_draggable_border_width * 2; ++ } ++ break; ++ case 0: /* bottom left */ ++ default: ++ *x = 0; ++ *y = height - fgeom.bottom_height - RESIZE_EXTENDS; ++ ++ if (d->frame_window) ++ { ++ *x += d->frame->win_extents.left + 4; ++ *y += d->frame->win_extents.bottom + 2; ++ } ++ ++ *w = fgeom.left_width + RESIZE_EXTENDS; ++ *h = fgeom.bottom_height + RESIZE_EXTENDS; ++ ++ if (!d->frame_window) ++ { ++ *y += mutter_draggable_border_width; ++ *w += mutter_draggable_border_width; ++ *h += mutter_draggable_border_width; ++ } ++ break; ++ } ++ break; + case 1: /* middle */ +- switch (j) { +- case 2: /* right */ +- *x = width - fgeom.right_width; +- *y = fgeom.top_height + RESIZE_EXTENDS; +- if (d->frame_window) +- *x += d->frame->win_extents.left + 2; +- *w = fgeom.right_width; +- *h = height - fgeom.top_height - fgeom.bottom_height - +- (2 * RESIZE_EXTENDS); +- +- if (!d->frame_window) +- { +- *x += mutter_draggable_border_width; +- *y += mutter_draggable_border_width; +- *w += mutter_draggable_border_width; +- *h += mutter_draggable_border_width; +- } +- +- +- break; +- case 1: /* middle */ +- *x = fgeom.left_width; +- *y = fgeom.title_rect.y + TOP_RESIZE_HEIGHT; +- *w = width - fgeom.left_width - fgeom.right_width; +- *h = height - fgeom.top_titlebar_edge - fgeom.bottom_height; +- +- if (!d->frame_window) +- { +- *x += mutter_draggable_border_width; +- if (flags & META_FRAME_ALLOWS_VERTICAL_RESIZE) +- *y += mutter_draggable_border_width; +- } +- +- break; +- case 0: /* left */ +- default: +- *x = 0; +- if (d->frame_window) +- *x += d->frame->win_extents.left + 4; +- *y = fgeom.top_height + RESIZE_EXTENDS; +- *w = fgeom.left_width; +- *h = height - fgeom.top_height - fgeom.bottom_height - +- (2 * RESIZE_EXTENDS); +- +- if (!d->frame_window) +- { +- *y += mutter_draggable_border_width; +- *h += mutter_draggable_border_width; +- *w += mutter_draggable_border_width; +- } +- +- +- break; +- } +- break; ++ switch (j) ++ { ++ case 2: /* right */ ++ *x = width - fgeom.right_width; ++ *y = fgeom.top_height + RESIZE_EXTENDS; ++ ++ if (d->frame_window) ++ *x += d->frame->win_extents.left + 2; ++ ++ *w = fgeom.right_width; ++ *h = height - fgeom.top_height - fgeom.bottom_height - (2 * RESIZE_EXTENDS); ++ ++ if (!d->frame_window) ++ { ++ *x += mutter_draggable_border_width; ++ *y += mutter_draggable_border_width; ++ *w += mutter_draggable_border_width; ++ *h += mutter_draggable_border_width; ++ } ++ break; ++ case 1: /* middle */ ++ *x = fgeom.left_width; ++ *y = fgeom.title_rect.y + TOP_RESIZE_HEIGHT; ++ *w = width - fgeom.left_width - fgeom.right_width; ++ *h = height - fgeom.top_titlebar_edge - fgeom.bottom_height; ++ ++ if (!d->frame_window) ++ { ++ *x += mutter_draggable_border_width; ++ ++ if (flags & META_FRAME_ALLOWS_VERTICAL_RESIZE) ++ *y += mutter_draggable_border_width; ++ } ++ break; ++ case 0: /* left */ ++ default: ++ *x = 0; ++ ++ if (d->frame_window) ++ *x += d->frame->win_extents.left + 4; ++ ++ *y = fgeom.top_height + RESIZE_EXTENDS; ++ *w = fgeom.left_width; ++ *h = height - fgeom.top_height - fgeom.bottom_height - (2 * RESIZE_EXTENDS); ++ ++ if (!d->frame_window) ++ { ++ *y += mutter_draggable_border_width; ++ *h += mutter_draggable_border_width; ++ *w += mutter_draggable_border_width; ++ } ++ break; ++ } ++ break; + case 0: /* top */ + default: +- switch (j) { +- case 2: /* top right */ +- *x = width - fgeom.right_width - RESIZE_EXTENDS; +- *y = 0; +- if (d->frame_window) +- { +- *x += d->frame->win_extents.left + 2; +- *y += d->frame->win_extents.top + 2 - fgeom.title_rect.height; +- } +- *w = fgeom.right_width + RESIZE_EXTENDS; +- *h = fgeom.top_height + RESIZE_EXTENDS; +- +- if (!d->frame_window) +- { +- *x += mutter_draggable_border_width; +- *w += mutter_draggable_border_width; +- *h += mutter_draggable_border_width; +- } +- break; +- case 1: /* top */ +- *x = fgeom.left_width + RESIZE_EXTENDS; +- *y = 0; +- if (d->frame_window) +- *y += d->frame->win_extents.top + 2; +- *w = width - fgeom.left_width - fgeom.right_width - +- (2 * RESIZE_EXTENDS); +- *h = fgeom.title_rect.y + TOP_RESIZE_HEIGHT; +- +- if (!d->frame_window) +- { +- *x -= mutter_draggable_border_width; +- *w += mutter_draggable_border_width * 2; +- *h += mutter_draggable_border_width; +- } +- +- break; +- case 0: /* top left */ +- default: +- *x = 0; +- *y = 0; +- if (d->frame_window) +- { +- *x += d->frame->win_extents.left + 4; +- *y += d->frame->win_extents.top + 2 - fgeom.title_rect.height; +- } +- *w = fgeom.left_width + RESIZE_EXTENDS; +- *h = fgeom.top_height + RESIZE_EXTENDS; +- +- if (!d->frame_window) +- { +- *w += mutter_draggable_border_width; +- *h += mutter_draggable_border_width; +- } ++ switch (j) ++ { ++ case 2: /* top right */ ++ *x = width - fgeom.right_width - RESIZE_EXTENDS; ++ *y = 0; ++ ++ if (d->frame_window) ++ { ++ *x += d->frame->win_extents.left + 2; ++ *y += d->frame->win_extents.top + 2 - fgeom.title_rect.height; ++ } ++ ++ *w = fgeom.right_width + RESIZE_EXTENDS; ++ *h = fgeom.top_height + RESIZE_EXTENDS; ++ ++ if (!d->frame_window) ++ { ++ *x += mutter_draggable_border_width; ++ *w += mutter_draggable_border_width; ++ *h += mutter_draggable_border_width; ++ } ++ break; ++ case 1: /* top */ ++ *x = fgeom.left_width + RESIZE_EXTENDS; ++ *y = 0; ++ ++ if (d->frame_window) ++ *y += d->frame->win_extents.top + 2; ++ ++ *w = width - fgeom.left_width - fgeom.right_width - (2 * RESIZE_EXTENDS); ++ *h = fgeom.title_rect.y + TOP_RESIZE_HEIGHT; ++ ++ if (!d->frame_window) ++ { ++ *x -= mutter_draggable_border_width; ++ *w += mutter_draggable_border_width * 2; ++ *h += mutter_draggable_border_width; ++ } ++ break; ++ case 0: /* top left */ ++ default: ++ *x = 0; ++ *y = 0; + +- break; +- } ++ if (d->frame_window) ++ { ++ *x += d->frame->win_extents.left + 4; ++ *y += d->frame->win_extents.top + 2 - fgeom.title_rect.height; ++ } ++ ++ *w = fgeom.left_width + RESIZE_EXTENDS; ++ *h = fgeom.top_height + RESIZE_EXTENDS; ++ ++ if (!d->frame_window) ++ { ++ *w += mutter_draggable_border_width; ++ *h += mutter_draggable_border_width; ++ } ++ break; ++ } ++ break; + } + + if (!(flags & META_FRAME_ALLOWS_VERTICAL_RESIZE)) + { +- /* turn off top and bottom event windows */ +- if (i == 0 || i == 2) +- *w = *h = 0; ++ /* turn off top and bottom event windows */ ++ if (i == 0 || i == 2) ++ *w = *h = 0; + } + + if (!(flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE)) + { +- /* turn off left and right event windows */ +- if (j == 0 || j == 2) +- *w = *h = 0; ++ /* turn off left and right event windows */ ++ if (j == 0 || j == 2) ++ *w = *h = 0; + } + } + +- + static MetaButtonFunction + meta_button_function_from_string (const char *str) + { + if (strcmp (str, "menu") == 0) +- return META_BUTTON_FUNCTION_MENU; ++ return META_BUTTON_FUNCTION_MENU; + else if (strcmp (str, "minimize") == 0) +- return META_BUTTON_FUNCTION_MINIMIZE; ++ return META_BUTTON_FUNCTION_MINIMIZE; + else if (strcmp (str, "maximize") == 0) +- return META_BUTTON_FUNCTION_MAXIMIZE; ++ return META_BUTTON_FUNCTION_MAXIMIZE; + else if (strcmp (str, "close") == 0) +- return META_BUTTON_FUNCTION_CLOSE; ++ return META_BUTTON_FUNCTION_CLOSE; + else if (strcmp (str, "shade") == 0) +- return META_BUTTON_FUNCTION_SHADE; ++ return META_BUTTON_FUNCTION_SHADE; + else if (strcmp (str, "above") == 0) +- return META_BUTTON_FUNCTION_ABOVE; ++ return META_BUTTON_FUNCTION_ABOVE; + else if (strcmp (str, "stick") == 0) +- return META_BUTTON_FUNCTION_STICK; ++ return META_BUTTON_FUNCTION_STICK; + else if (strcmp (str, "unshade") == 0) +- return META_BUTTON_FUNCTION_UNSHADE; ++ return META_BUTTON_FUNCTION_UNSHADE; + else if (strcmp (str, "unabove") == 0) +- return META_BUTTON_FUNCTION_UNABOVE; ++ return META_BUTTON_FUNCTION_UNABOVE; + else if (strcmp (str, "unstick") == 0) +- return META_BUTTON_FUNCTION_UNSTICK; ++ return META_BUTTON_FUNCTION_UNSTICK; + else +- return META_BUTTON_FUNCTION_LAST; ++ return META_BUTTON_FUNCTION_LAST; + } + + static MetaButtonFunction +@@ -1378,22 +1363,22 @@ + switch (ofwhat) + { + case META_BUTTON_FUNCTION_SHADE: +- return META_BUTTON_FUNCTION_UNSHADE; ++ return META_BUTTON_FUNCTION_UNSHADE; + case META_BUTTON_FUNCTION_UNSHADE: +- return META_BUTTON_FUNCTION_SHADE; ++ return META_BUTTON_FUNCTION_SHADE; + + case META_BUTTON_FUNCTION_ABOVE: +- return META_BUTTON_FUNCTION_UNABOVE; ++ return META_BUTTON_FUNCTION_UNABOVE; + case META_BUTTON_FUNCTION_UNABOVE: +- return META_BUTTON_FUNCTION_ABOVE; ++ return META_BUTTON_FUNCTION_ABOVE; + + case META_BUTTON_FUNCTION_STICK: +- return META_BUTTON_FUNCTION_UNSTICK; ++ return META_BUTTON_FUNCTION_UNSTICK; + case META_BUTTON_FUNCTION_UNSTICK: +- return META_BUTTON_FUNCTION_STICK; ++ return META_BUTTON_FUNCTION_STICK; + + default: +- return META_BUTTON_FUNCTION_LAST; ++ return META_BUTTON_FUNCTION_LAST; + } + } + +@@ -1404,20 +1389,20 @@ + + for (i = 0; i < MAX_BUTTONS_PER_CORNER; ++i) + { +- layout->left_buttons[i] = META_BUTTON_FUNCTION_LAST; +- layout->right_buttons[i] = META_BUTTON_FUNCTION_LAST; +- layout->left_buttons_has_spacer[i] = FALSE; +- layout->right_buttons_has_spacer[i] = FALSE; ++ layout->left_buttons[i] = META_BUTTON_FUNCTION_LAST; ++ layout->right_buttons[i] = META_BUTTON_FUNCTION_LAST; ++ layout->left_buttons_has_spacer[i] = FALSE; ++ layout->right_buttons_has_spacer[i] = FALSE; + } + } + + void + meta_update_button_layout (const char *value) + { +- MetaButtonLayout new_layout; ++ MetaButtonLayout new_layout; + MetaButtonFunction f; +- char **sides; +- int i; ++ char **sides; ++ int i; + + meta_initialize_button_layout (&new_layout); + +@@ -1425,96 +1410,97 @@ + + if (sides[0] != NULL) + { +- char **buttons; +- int b; +- gboolean used[META_BUTTON_FUNCTION_LAST]; +- +- for (i = 0; i < META_BUTTON_FUNCTION_LAST; ++i) +- used[i] = FALSE; +- +- buttons = g_strsplit (sides[0], ",", -1); +- +- i = b = 0; +- while (buttons[b] != NULL) +- { +- f = meta_button_function_from_string (buttons[b]); +- if (i > 0 && strcmp ("spacer", buttons[b]) == 0) +- { +- new_layout.left_buttons_has_spacer[i - 1] = TRUE; +- f = meta_button_opposite_function (f); +- +- if (f != META_BUTTON_FUNCTION_LAST) +- new_layout.left_buttons_has_spacer[i - 2] = TRUE; +- } +- else +- { +- if (f != META_BUTTON_FUNCTION_LAST && !used[f]) +- { +- used[f] = TRUE; +- new_layout.left_buttons[i++] = f; +- +- f = meta_button_opposite_function (f); +- +- if (f != META_BUTTON_FUNCTION_LAST) +- new_layout.left_buttons[i++] = f; +- +- } +- else +- { +- fprintf (stderr, "%s: Ignoring unknown or already-used " +- "button name \"%s\"\n", program_name, buttons[b]); +- } +- } +- ++b; +- } +- +- new_layout.left_buttons[i] = META_BUTTON_FUNCTION_LAST; +- +- g_strfreev (buttons); +- +- if (sides[1] != NULL) +- { +- for (i = 0; i < META_BUTTON_FUNCTION_LAST; ++i) +- used[i] = FALSE; +- +- buttons = g_strsplit (sides[1], ",", -1); +- +- i = b = 0; +- while (buttons[b] != NULL) +- { +- f = meta_button_function_from_string (buttons[b]); +- if (i > 0 && strcmp ("spacer", buttons[b]) == 0) +- { +- new_layout.right_buttons_has_spacer[i - 1] = TRUE; +- f = meta_button_opposite_function (f); +- if (f != META_BUTTON_FUNCTION_LAST) +- new_layout.right_buttons_has_spacer[i - 2] = TRUE; +- } +- else +- { +- if (f != META_BUTTON_FUNCTION_LAST && !used[f]) +- { +- used[f] = TRUE; +- new_layout.right_buttons[i++] = f; +- +- f = meta_button_opposite_function (f); +- +- if (f != META_BUTTON_FUNCTION_LAST) +- new_layout.right_buttons[i++] = f; +- } +- else +- { +- fprintf (stderr, "%s: Ignoring unknown or " +- "already-used button name \"%s\"\n", +- program_name, buttons[b]); +- } +- } +- ++b; +- } +- new_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST; ++ char **buttons; ++ int b; ++ gboolean used[META_BUTTON_FUNCTION_LAST]; ++ ++ for (i = 0; i < META_BUTTON_FUNCTION_LAST; ++i) ++ used[i] = FALSE; ++ ++ buttons = g_strsplit (sides[0], ",", -1); ++ ++ i = b = 0; ++ while (buttons[b] != NULL) ++ { ++ f = meta_button_function_from_string (buttons[b]); ++ if (i > 0 && strcmp ("spacer", buttons[b]) == 0) ++ { ++ new_layout.left_buttons_has_spacer[i - 1] = TRUE; ++ f = meta_button_opposite_function (f); ++ ++ if (f != META_BUTTON_FUNCTION_LAST) ++ new_layout.left_buttons_has_spacer[i - 2] = TRUE; ++ } ++ else ++ { ++ if (f != META_BUTTON_FUNCTION_LAST && !used[f]) ++ { ++ used[f] = TRUE; ++ new_layout.left_buttons[i++] = f; ++ ++ f = meta_button_opposite_function (f); ++ ++ if (f != META_BUTTON_FUNCTION_LAST) ++ new_layout.left_buttons[i++] = f; ++ ++ } ++ else ++ { ++ fprintf (stderr, "%s: Ignoring unknown or already-used " ++ "button name \"%s\"\n", program_name, buttons[b]); ++ } ++ } ++ ++b; ++ } ++ ++ new_layout.left_buttons[i] = META_BUTTON_FUNCTION_LAST; ++ ++ g_strfreev (buttons); ++ ++ if (sides[1] != NULL) ++ { ++ for (i = 0; i < META_BUTTON_FUNCTION_LAST; ++i) ++ used[i] = FALSE; ++ ++ buttons = g_strsplit (sides[1], ",", -1); ++ ++ i = b = 0; ++ while (buttons[b] != NULL) ++ { ++ f = meta_button_function_from_string (buttons[b]); ++ if (i > 0 && strcmp ("spacer", buttons[b]) == 0) ++ { ++ new_layout.right_buttons_has_spacer[i - 1] = TRUE; ++ f = meta_button_opposite_function (f); ++ if (f != META_BUTTON_FUNCTION_LAST) ++ new_layout.right_buttons_has_spacer[i - 2] = TRUE; ++ } ++ else ++ { ++ if (f != META_BUTTON_FUNCTION_LAST && !used[f]) ++ { ++ used[f] = TRUE; ++ new_layout.right_buttons[i++] = f; ++ ++ f = meta_button_opposite_function (f); ++ ++ if (f != META_BUTTON_FUNCTION_LAST) ++ new_layout.right_buttons[i++] = f; ++ } ++ else ++ { ++ fprintf (stderr, "%s: Ignoring unknown or " ++ "already-used button name \"%s\"\n", ++ program_name, buttons[b]); ++ } ++ } ++ ++b; ++ } ++ ++ new_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST; + +- g_strfreev (buttons); +- } ++ g_strfreev (buttons); ++ } + } + + g_strfreev (sides); +@@ -1522,42 +1508,38 @@ + /* Invert the button layout for RTL languages */ + if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL) + { +- MetaButtonLayout rtl_layout; +- int j; ++ MetaButtonLayout rtl_layout; ++ int j; + +- meta_initialize_button_layout (&rtl_layout); ++ meta_initialize_button_layout (&rtl_layout); + +- i = 0; +- while (new_layout.left_buttons[i] != META_BUTTON_FUNCTION_LAST) +- ++i; +- +- for (j = 0; j < i; ++j) +- { +- rtl_layout.right_buttons[j] = new_layout.left_buttons[i - j - 1]; +- if (j == 0) +- rtl_layout.right_buttons_has_spacer[i - 1] = +- new_layout.left_buttons_has_spacer[i - j - 1]; +- else +- rtl_layout.right_buttons_has_spacer[j - 1] = +- new_layout.left_buttons_has_spacer[i - j - 1]; +- } +- +- i = 0; +- while (new_layout.right_buttons[i] != META_BUTTON_FUNCTION_LAST) +- ++i; +- +- for (j = 0; j < i; ++j) +- { +- rtl_layout.left_buttons[j] = new_layout.right_buttons[i - j - 1]; +- if (j == 0) +- rtl_layout.left_buttons_has_spacer[i - 1] = +- new_layout.right_buttons_has_spacer[i - j - 1]; +- else +- rtl_layout.left_buttons_has_spacer[j - 1] = +- new_layout.right_buttons_has_spacer[i - j - 1]; +- } ++ i = 0; ++ while (new_layout.left_buttons[i] != META_BUTTON_FUNCTION_LAST) ++ ++i; ++ ++ for (j = 0; j < i; ++j) ++ { ++ rtl_layout.right_buttons[j] = new_layout.left_buttons[i - j - 1]; ++ if (j == 0) ++ rtl_layout.right_buttons_has_spacer[i - 1] = new_layout.left_buttons_has_spacer[i - j - 1]; ++ else ++ rtl_layout.right_buttons_has_spacer[j - 1] = new_layout.left_buttons_has_spacer[i - j - 1]; ++ } ++ ++ i = 0; ++ while (new_layout.right_buttons[i] != META_BUTTON_FUNCTION_LAST) ++ ++i; ++ ++ for (j = 0; j < i; ++j) ++ { ++ rtl_layout.left_buttons[j] = new_layout.right_buttons[i - j - 1]; ++ if (j == 0) ++ rtl_layout.left_buttons_has_spacer[i - 1] = new_layout.right_buttons_has_spacer[i - j - 1]; ++ else ++ rtl_layout.left_buttons_has_spacer[j - 1] = new_layout.right_buttons_has_spacer[i - j - 1]; ++ } + +- new_layout = rtl_layout; ++ new_layout = rtl_layout; + } + + meta_button_layout = new_layout; +@@ -1566,37 +1548,36 @@ + void + meta_update_border_extents (decor_frame_t *frame) + { +- MetaTheme *theme = meta_theme_get_current (); ++ MetaTheme *theme; + #ifdef HAVE_METACITY_3_14_0 + MetaFrameBorders borders; + #endif ++ MetaFrameType frame_type; ++ gint top_height; ++ gint bottom_height; ++ gint left_width; ++ gint right_width; + + gwd_decor_frame_ref (frame); +- MetaFrameType frame_type = meta_frame_type_from_string (frame->type); +- gint top_height, bottom_height, left_width, right_width; + ++ frame_type = meta_frame_type_from_string (frame->type); + if (!(frame_type < META_FRAME_TYPE_LAST)) +- frame_type = META_FRAME_TYPE_NORMAL; ++ frame_type = META_FRAME_TYPE_NORMAL; ++ ++ theme = meta_theme_get_current (); + + #ifdef HAVE_METACITY_3_14_0 +- meta_theme_get_frame_borders (theme, +- frame_type, +- frame->text_height, +- 0, +- &borders); ++ meta_theme_get_frame_borders (theme, frame_type, frame->text_height, ++ 0, &borders); ++ + top_height = borders.visible.top; + bottom_height = borders.visible.bottom; + left_width = borders.visible.left; + right_width = borders.visible.right; + #else +- meta_theme_get_frame_borders (theme, +- frame_type, +- frame->text_height, +- 0, +- &top_height, +- &bottom_height, +- &left_width, +- &right_width); ++ meta_theme_get_frame_borders (theme, frame_type, frame->text_height, ++ 0, &top_height, &bottom_height, ++ &left_width, &right_width); + #endif + + frame->win_extents.top = frame->win_extents.top; +@@ -1607,24 +1588,18 @@ + frame->titlebar_height = top_height - frame->win_extents.top; + + #ifdef HAVE_METACITY_3_14_0 +- meta_theme_get_frame_borders (theme, +- frame_type, +- frame->text_height, +- META_FRAME_MAXIMIZED, +- &borders); ++ meta_theme_get_frame_borders (theme, frame_type, frame->text_height, ++ META_FRAME_MAXIMIZED, &borders); ++ + top_height = borders.visible.top; + bottom_height = borders.visible.bottom; + left_width = borders.visible.left; + right_width = borders.visible.right; + #else +- meta_theme_get_frame_borders (theme, +- frame_type, +- frame->text_height, +- META_FRAME_MAXIMIZED, +- &top_height, +- &bottom_height, +- &left_width, +- &right_width); ++ meta_theme_get_frame_borders (theme, frame_type, frame->text_height, ++ META_FRAME_MAXIMIZED, ++ &top_height, &bottom_height, ++ &left_width, &right_width); + #endif + + frame->max_win_extents.top = frame->win_extents.top; +@@ -1637,4 +1612,5 @@ + gwd_decor_frame_unref (frame); + } + +-#endif ++#endif /* HAVE_METACITY_3_16_0 */ ++#endif /* USE_METACITY */ +diff -Nur original/gtk/window-decorator/settings.c modified/gtk/window-decorator/settings.c +--- original/gtk/window-decorator/settings.c 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/settings.c 2015-04-11 14:34:11.000000000 +0100 +@@ -45,11 +45,14 @@ + #ifdef USE_GSETTINGS + #define STORAGE_USED + GSettings *compiz = gwd_get_org_compiz_gwd_settings (); ++ GSettings *metacity = gwd_get_org_gnome_metacity_settings (); + GSettings *mutter = gwd_get_org_gnome_mutter_settings (); + GSettings *gnome = gwd_get_org_gnome_desktop_wm_preferences_settings (); +- storage = gwd_settings_storage_gsettings_new (gnome, mutter, compiz, writable); ++ ++ storage = gwd_settings_storage_gsettings_new (gnome, metacity, mutter, compiz, writable); + + gwd_connect_org_compiz_gwd_settings (compiz, storage); ++ gwd_connect_org_gnome_metacity_settings (metacity, storage); + gwd_connect_org_gnome_mutter_settings (mutter, storage); + gwd_connect_org_gnome_desktop_wm_preferences_settings (gnome, storage); + #endif +@@ -70,7 +73,6 @@ + gwd_settings_storage_update_titlebar_actions (storage); + gwd_settings_storage_update_blur (storage); + gwd_settings_storage_update_draggable_border_width (storage); +- gwd_settings_storage_update_attach_modal_dialogs (storage); + gwd_settings_storage_update_use_tooltips (storage); + gwd_process_decor_shadow_property_update (); + #else +diff -Nur original/gtk/window-decorator/switcher.c modified/gtk/window-decorator/switcher.c +--- original/gtk/window-decorator/switcher.c 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/switcher.c 2015-04-11 14:34:11.000000000 +0100 +@@ -25,6 +25,8 @@ + + #include "gtk-window-decorator.h" + ++#define SWITCHER_SPACE 40 ++ + decor_frame_t * + create_switcher_frame (const gchar *type) + { +@@ -319,7 +321,7 @@ + copy_to_front_buffer (d); + } + +-void ++static void + draw_switcher_decoration (decor_t *d) + { + if (d->prop_xid) +@@ -328,7 +330,8 @@ + draw_switcher_foreground (d); + } + +-void ++#if 0 ++static void + switcher_window_closed () + { + decor_t *d = switcher_window; +@@ -356,10 +359,11 @@ + g_free (switcher_window); + switcher_window = NULL; + } ++#endif + + /* Switcher is override-redirect now, we need to track + * it separately */ +-decor_t * ++static decor_t * + switcher_window_opened (Window popup, Window window) + { + decor_t *d; +diff -Nur original/gtk/window-decorator/tests/CMakeLists.txt modified/gtk/window-decorator/tests/CMakeLists.txt +--- original/gtk/window-decorator/tests/CMakeLists.txt 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/tests/CMakeLists.txt 2015-04-11 14:34:11.000000000 +0100 +@@ -75,6 +75,21 @@ + + add_gsettings_schema_to_recompilation_list (compiz_gwd_gsettings_org_gnome_desktop_wm_preferences_schema) + ++ set (_metacity_gschema_name org.gnome.metacity) ++ set (_metacity_gschema_filename ${_metacity_gschema_name}.gschema.xml) ++ set (_metacity_gschema_filepath ${CMAKE_CURRENT_SOURCE_DIR}/${_metacity_gschema_filename}) ++ set (_metacity_gschema_generated_location ${CMAKE_BINARY_DIR}/generated/glib-2.0/schemas/${_metacity_gschema_filename}) ++ ++ add_custom_command (OUTPUT ${_metacity_gschema_generated_location} ++ COMMAND cp -r ${_metacity_gschema_filepath} ${_metacity_gschema_generated_location} ++ DEPENDS ${_metacity_gschema_filepath} ++ VERBATIM) ++ ++ add_custom_target (compiz_gwd_gsettings_org_gnome_metacity_schema ALL ++ DEPENDS ${_metacity_gschema_generated_location}) ++ ++ add_gsettings_schema_to_recompilation_list (compiz_gwd_gsettings_org_gnome_metacity_schema) ++ + set (_mutter_gschema_name org.gnome.mutter) + set (_mutter_gschema_filename ${_mutter_gschema_name}.gschema.xml) + set (_mutter_gschema_filepath ${CMAKE_CURRENT_SOURCE_DIR}/${_mutter_gschema_filename}) +diff -Nur original/gtk/window-decorator/tests/compiz_gwd_mock_settings_storage.cpp modified/gtk/window-decorator/tests/compiz_gwd_mock_settings_storage.cpp +--- original/gtk/window-decorator/tests/compiz_gwd_mock_settings_storage.cpp 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/tests/compiz_gwd_mock_settings_storage.cpp 2015-04-11 14:34:11.000000000 +0100 +@@ -73,13 +73,6 @@ + return settingsGMock->updateDraggableBorderWidth (); + } + +-gboolean gwd_mock_settings_storage_update_attach_modal_dialogs (GWDSettingsStorage *settings) +-{ +- GWDMockSettingsStorage *settingsStorageMock = GWD_MOCK_SETTINGS_STORAGE (settings) +- GWDMockSettingsStorageGMockInterface *settingsGMock = GET_PRIVATE (settingsStorageMock)->mock; +- return settingsGMock->updateAttachModalDialogs (); +-} +- + gboolean gwd_mock_settings_storage_update_blur (GWDSettingsStorage *settings) + { + GWDMockSettingsStorage *settingsStorageMock = GWD_MOCK_SETTINGS_STORAGE (settings); +@@ -126,7 +119,6 @@ + { + interface->update_use_tooltips = gwd_mock_settings_storage_update_use_tooltips; + interface->update_draggable_border_width = gwd_mock_settings_storage_update_draggable_border_width; +- interface->update_attach_modal_dialogs = gwd_mock_settings_storage_update_attach_modal_dialogs; + interface->update_blur = gwd_mock_settings_storage_update_blur; + interface->update_metacity_theme = gwd_mock_settings_storage_update_metacity_theme; + interface->update_opacity = gwd_mock_settings_storage_update_opacity; +diff -Nur original/gtk/window-decorator/tests/compiz_gwd_mock_settings_writable.cpp modified/gtk/window-decorator/tests/compiz_gwd_mock_settings_writable.cpp +--- original/gtk/window-decorator/tests/compiz_gwd_mock_settings_writable.cpp 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/tests/compiz_gwd_mock_settings_writable.cpp 2015-04-11 14:34:11.000000000 +0100 +@@ -116,14 +116,6 @@ + } + + gboolean +-gwd_mock_settings_writable_attach_modal_dialogs_changed (GWDSettingsWritable *settings, +- gboolean attach_modal_dialogs) +-{ +- GWDMockSettingsWritableGMockInterface *gmockSettingsWritable = GET_PRIVATE (settings)->mock; +- return gmockSettingsWritable->attachModalDialogsChanged (attach_modal_dialogs); +-} +- +-gboolean + gwd_mock_settings_writable_blur_changed (GWDSettingsWritable *settings, + const gchar *blur_type) + { +@@ -187,7 +179,6 @@ + interface->shadow_property_changed = gwd_mock_settings_writable_shadow_property_changed; + interface->use_tooltips_changed = gwd_mock_settings_writable_use_tooltips_changed; + interface->draggable_border_width_changed = gwd_mock_settings_writable_draggable_border_width_changed; +- interface->attach_modal_dialogs_changed = gwd_mock_settings_writable_attach_modal_dialogs_changed; + interface->blur_changed = gwd_mock_settings_writable_blur_changed; + interface->metacity_theme_changed = gwd_mock_settings_writable_metacity_theme_changed; + interface->opacity_changed = gwd_mock_settings_writable_opacity_changed; +diff -Nur original/gtk/window-decorator/tests/compiz_gwd_mock_settings_writable.h modified/gtk/window-decorator/tests/compiz_gwd_mock_settings_writable.h +--- original/gtk/window-decorator/tests/compiz_gwd_mock_settings_writable.h 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/tests/compiz_gwd_mock_settings_writable.h 2015-04-11 14:34:11.000000000 +0100 +@@ -59,7 +59,6 @@ + const gchar *inactive_shadow_color) = 0; + virtual gboolean useTooltipsChanged (gboolean newValue) = 0; + virtual gboolean draggableBorderWidthChanged (gint newValue) = 0; +- virtual gboolean attachModalDialogsChanged (gboolean newValue) = 0; + virtual gboolean blurChanged (const gchar *type) = 0; + virtual gboolean metacityThemeChanged (gboolean useMetacityTheme, const gchar *metacityTheme) = 0; + virtual gboolean opacityChanged (gdouble inactiveOpacity, +@@ -90,7 +89,6 @@ + gdouble, gdouble, gdouble, gdouble, const gchar *)); + MOCK_METHOD1 (useTooltipsChanged, gboolean (gboolean)); + MOCK_METHOD1 (draggableBorderWidthChanged, gboolean (gint)); +- MOCK_METHOD1 (attachModalDialogsChanged, gboolean (gboolean)); + MOCK_METHOD1 (blurChanged, gboolean (const gchar *)); + MOCK_METHOD2 (metacityThemeChanged, gboolean (gboolean, const gchar *)); + MOCK_METHOD4 (opacityChanged, gboolean (gdouble, gdouble, gboolean, gboolean)); +diff -Nur original/gtk/window-decorator/tests/org.gnome.metacity.gschema.xml modified/gtk/window-decorator/tests/org.gnome.metacity.gschema.xml +--- original/gtk/window-decorator/tests/org.gnome.metacity.gschema.xml 1970-01-01 01:00:00.000000000 +0100 ++++ modified/gtk/window-decorator/tests/org.gnome.metacity.gschema.xml 2015-04-11 14:34:11.000000000 +0100 +@@ -0,0 +1,10 @@ ++<?xml version="1.0" encoding="UTF-8"?> ++<schemalist> ++ <schema path="/org/gnome/metacity/" id="org.gnome.metacity" gettext-domain="@GETTEXT_DOMAIN"> ++ <key type="s" name="theme"> ++ <default>'Adwaita'</default> ++ <summary>Current theme</summary> ++ <description>The theme determines the appearance of window borders, titlebar, and so forth.</description> ++ </key> ++ </schema> ++</schemalist> +diff -Nur original/gtk/window-decorator/tests/org.gnome.mutter.gschema.xml modified/gtk/window-decorator/tests/org.gnome.mutter.gschema.xml +--- original/gtk/window-decorator/tests/org.gnome.mutter.gschema.xml 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/tests/org.gnome.mutter.gschema.xml 2015-04-11 14:34:11.000000000 +0100 +@@ -1,13 +1,6 @@ + <?xml version="1.0" encoding="UTF-8"?> + <schemalist> + <schema path="/org/gnome/mutter/" id="org.gnome.mutter" gettext-domain="@GETTEXT_DOMAIN"> +- +- <key type="b" name="attach-modal-dialogs"> +- <default>false</default> +- <summary>Attach modal dialogs</summary> +- <description>When true, instead of having independent titlebars, modal dialogs appear attached to the titlebar of the parent window and are moved together with the parent window.</description> +- </key> +- + <key type="i" name="draggable-border-width"> + <default>10</default> + <range min="0" max="64"/> +diff -Nur original/gtk/window-decorator/tests/test_gwd_settings.cpp modified/gtk/window-decorator/tests/test_gwd_settings.cpp +--- original/gtk/window-decorator/tests/test_gwd_settings.cpp 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/tests/test_gwd_settings.cpp 2015-04-11 14:34:11.000000000 +0100 +@@ -198,7 +198,6 @@ + const gushort INACTIVE_SHADOW_COLOR_VALUE[] = { 0, 0, 0 }; + const gboolean USE_TOOLTIPS_VALUE = !USE_TOOLTIPS_DEFAULT; + const guint DRAGGABLE_BORDER_WIDTH_VALUE = 1; +- const gboolean ATTACH_MODAL_DIALOGS_VALUE = TRUE; + const std::string BLUR_TYPE_TITLEBAR_VALUE ("titlebar"); + const gint BLUR_TYPE_TITLEBAR_INT_VALUE = BLUR_TYPE_TITLEBAR; + const std::string BLUR_TYPE_ALL_VALUE ("all"); +@@ -330,7 +329,6 @@ + Eq (testing_values::INACTIVE_SHADOW_COLOR_STR_VALUE))).WillOnce (Return (TRUE)); + EXPECT_CALL (writableGMock, useTooltipsChanged (testing_values::USE_TOOLTIPS_VALUE)).WillOnce (Return (TRUE)); + EXPECT_CALL (writableGMock, draggableBorderWidthChanged (testing_values::DRAGGABLE_BORDER_WIDTH_VALUE)).WillOnce (Return (TRUE)); +- EXPECT_CALL (writableGMock, attachModalDialogsChanged (testing_values::ATTACH_MODAL_DIALOGS_VALUE)).WillOnce (Return (TRUE)); + EXPECT_CALL (writableGMock, blurChanged (Eq (testing_values::BLUR_TYPE_TITLEBAR_VALUE))).WillOnce (Return (TRUE)); + EXPECT_CALL (writableGMock, metacityThemeChanged (TRUE, Eq (testing_values::METACITY_THEME_VALUE))).WillOnce (Return (TRUE)); + EXPECT_CALL (writableGMock, opacityChanged (testing_values::ACTIVE_OPACITY_VALUE, +@@ -364,7 +362,6 @@ + testing_values::INACTIVE_SHADOW_COLOR_STR_VALUE.c_str ()), IsTrue ()); + EXPECT_THAT (gwd_settings_writable_use_tooltips_changed (writableMock.get (), testing_values::USE_TOOLTIPS_VALUE), IsTrue ()); + EXPECT_THAT (gwd_settings_writable_draggable_border_width_changed (writableMock.get (), testing_values::DRAGGABLE_BORDER_WIDTH_VALUE), IsTrue ()); +- EXPECT_THAT (gwd_settings_writable_attach_modal_dialogs_changed (writableMock.get (), testing_values::ATTACH_MODAL_DIALOGS_VALUE), IsTrue ()); + EXPECT_THAT (gwd_settings_writable_blur_changed (writableMock.get (), testing_values::BLUR_TYPE_TITLEBAR_VALUE.c_str ()), IsTrue ()); + EXPECT_THAT (gwd_settings_writable_metacity_theme_changed (writableMock.get (), + testing_values::USE_METACITY_THEME_VALUE, +@@ -472,14 +469,6 @@ + "draggable-border-width", + &integerGValue); + +- EXPECT_CALL (settingsGMock, getProperty (GWD_MOCK_SETTINGS_PROPERTY_ATTACH_MODAL_DIALOGS, +- GValueMatch <gboolean> (FALSE, g_value_get_boolean), +- _)); +- +- g_object_get_property (G_OBJECT (settingsMock.get ()), +- "attach-modal-dialogs", +- &booleanGValue); +- + EXPECT_CALL (settingsGMock, getProperty (GWD_MOCK_SETTINGS_PROPERTY_BLUR_CHANGED, + GValueMatch <gint> (0, g_value_get_int), + _)); +@@ -783,29 +772,6 @@ + DRAGGABLE_BORDER_WIDTH_DEFAULT), IsFalse ()); + } + +-TEST_F(GWDSettingsTest, TestAttachModalDialogsChanged) +-{ +- EXPECT_CALL (*mGMockNotified, updateDecorations ()); +- EXPECT_THAT (gwd_settings_writable_attach_modal_dialogs_changed (GWD_SETTINGS_WRITABLE_INTERFACE (mSettings.get ()), +- testing_values::ATTACH_MODAL_DIALOGS_VALUE), IsTrue ()); +- +- AutoUnsetGValue attachModalDialogsValue (G_TYPE_BOOLEAN); +- GValue &attachModalDialogsGValue = attachModalDialogsValue; +- +- g_object_get_property (G_OBJECT (mSettings.get ()), +- "attach-modal-dialogs", +- &attachModalDialogsGValue); +- +- EXPECT_THAT (&attachModalDialogsGValue, GValueMatch <gboolean> (testing_values::ATTACH_MODAL_DIALOGS_VALUE, +- g_value_get_boolean)); +-} +- +-TEST_F(GWDSettingsTest, TestAttachModalDialogsChangedIsDefault) +-{ +- EXPECT_THAT (gwd_settings_writable_attach_modal_dialogs_changed (GWD_SETTINGS_WRITABLE_INTERFACE (mSettings.get ()), +- ATTACH_MODAL_DIALOGS_DEFAULT), IsFalse ()); +-} +- + TEST_F(GWDSettingsTest, TestBlurChangedTitlebar) + { + EXPECT_CALL (*mGMockNotified, updateDecorations ()); +@@ -1218,7 +1184,6 @@ + virtual GWDSettingsStorage * GetStorage () = 0; + virtual void SetUseTooltips (gboolean useTooltips) = 0; + virtual void SetDraggableBorderWidth (gint draggableBorderWidth) = 0; +- virtual void SetAttachModalDialogs (gboolean attachModalDialogs) = 0; + virtual void SetBlur (const std::string &blurType) = 0; + virtual void SetOpacity (gdouble activeOpacity, + gdouble inactiveOpacity, +@@ -1292,16 +1257,6 @@ + gwd_settings_storage_update_draggable_border_width (storage); + } + +-TEST_P (GWDSettingsTestStorageUpdates, TestSetAttachModalDialogs) +-{ +- GWDSettingsStorage *storage = GetParam ()->GetStorage (); +- GetParam ()->SetAttachModalDialogs (testing_values::ATTACH_MODAL_DIALOGS_VALUE); +- +- EXPECT_CALL (*mSettingsMock, attachModalDialogsChanged (testing_values::ATTACH_MODAL_DIALOGS_VALUE)); +- +- gwd_settings_storage_update_attach_modal_dialogs (storage); +-} +- + TEST_P (GWDSettingsTestStorageUpdates, TestSetBlur) + { + GWDSettingsStorage *storage = GetParam ()->GetStorage (); +@@ -1414,15 +1369,6 @@ + gwd_settings_writable_draggable_border_width_changed, mWritable, draggableBorderWidth))); + } + +- virtual void SetAttachModalDialogs (gboolean attachModalDialogs) +- { +- EXPECT_CALL (*mStorageMock, updateAttachModalDialogs ()) +- .WillOnce ( +- InvokeFunctor ( +- boost::bind ( +- gwd_settings_writable_attach_modal_dialogs_changed, mWritable, attachModalDialogs))); +- } +- + virtual void SetBlur (const std::string &blurType) + { + EXPECT_CALL (*mStorageMock, updateBlur ()) +@@ -1535,6 +1481,7 @@ + boost::bind (gwd_settings_storage_unref, _1)); + + gwd_connect_org_compiz_gwd_settings (NULL, mStorage.get ()); ++ gwd_connect_org_gnome_metacity_settings (NULL, mStorage.get ()); + gwd_connect_org_gnome_mutter_settings (NULL, mStorage.get ()); + gwd_connect_org_gnome_desktop_wm_preferences_settings (NULL, mStorage.get ()); + +@@ -1554,10 +1501,12 @@ + + /* We do not need to keep a reference to these */ + mGWDSettings = gwd_get_org_compiz_gwd_settings (); ++ mMetacitySettings = gwd_get_org_gnome_mutter_settings (); + mMutterSettings = gwd_get_org_gnome_mutter_settings (); + mDesktopSettings = gwd_get_org_gnome_desktop_wm_preferences_settings (); + + mStorage.reset (gwd_settings_storage_gsettings_new (mDesktopSettings, ++ mMetacitySettings, + mMutterSettings, + mGWDSettings, + writable), +@@ -1579,11 +1528,6 @@ + g_settings_set_int (mMutterSettings, ORG_GNOME_MUTTER_DRAGGABLE_BORDER_WIDTH, draggableBorderWidth); + } + +- virtual void SetAttachModalDialogs (gboolean attachModalDialogs) +- { +- g_settings_set_boolean (mMutterSettings, ORG_GNOME_MUTTER_ATTACH_MODAL_DIALOGS, attachModalDialogs); +- } +- + virtual void SetBlur (const std::string &blurType) + { + g_settings_set_string (mGWDSettings, ORG_COMPIZ_GWD_KEY_BLUR_TYPE, blurType.c_str ()); +@@ -1655,6 +1599,7 @@ + { + mStorage.reset (); + mGWDSettings = NULL; ++ mMetacitySettings = NULL; + mMutterSettings = NULL; + mDesktopSettings = NULL; + gsettingsEnv.TearDownEnv (); +@@ -1664,6 +1609,7 @@ + private: + + GSettings *mGWDSettings; ++ GSettings *mMetacitySettings; + GSettings *mMutterSettings; + GSettings *mDesktopSettings; + boost::shared_ptr <GWDSettingsStorage> mStorage; +diff -Nur original/gtk/window-decorator/util.c modified/gtk/window-decorator/util.c +--- original/gtk/window-decorator/util.c 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/util.c 2015-04-11 14:34:11.000000000 +0100 +@@ -21,19 +21,6 @@ + + #include "gtk-window-decorator.h" + +-double +-square (double x) +-{ +- return x * x; +-} +- +-double +-dist (double x1, double y1, +- double x2, double y2) +-{ +- return sqrt (square (x1 - x2) + square (y1 - y2)); +-} +- + gboolean + get_window_prop (Window xwindow, + Atom atom, +@@ -110,190 +97,3 @@ + + return decor; + } +- +-/* from clearlooks theme */ +-static void +-rgb_to_hls (gdouble *r, +- gdouble *g, +- gdouble *b) +-{ +- gdouble min; +- gdouble max; +- gdouble red; +- gdouble green; +- gdouble blue; +- gdouble h, l, s; +- gdouble delta; +- +- red = *r; +- green = *g; +- blue = *b; +- +- if (red > green) +- { +- if (red > blue) +- max = red; +- else +- max = blue; +- +- if (green < blue) +- min = green; +- else +- min = blue; +- } +- else +- { +- if (green > blue) +- max = green; +- else +- max = blue; +- +- if (red < blue) +- min = red; +- else +- min = blue; +- } +- +- l = (max + min) / 2; +- s = 0; +- h = 0; +- +- if (max != min) +- { +- if (l <= 0.5) +- s = (max - min) / (max + min); +- else +- s = (max - min) / (2 - max - min); +- +- delta = max -min; +- if (red == max) +- h = (green - blue) / delta; +- else if (green == max) +- h = 2 + (blue - red) / delta; +- else if (blue == max) +- h = 4 + (red - green) / delta; +- +- h *= 60; +- if (h < 0.0) +- h += 360; +- } +- +- *r = h; +- *g = l; +- *b = s; +-} +- +-static void +-hls_to_rgb (gdouble *h, +- gdouble *l, +- gdouble *s) +-{ +- gdouble hue; +- gdouble lightness; +- gdouble saturation; +- gdouble m1, m2; +- gdouble r, g, b; +- +- lightness = *l; +- saturation = *s; +- +- if (lightness <= 0.5) +- m2 = lightness * (1 + saturation); +- else +- m2 = lightness + saturation - lightness * saturation; +- +- m1 = 2 * lightness - m2; +- +- if (saturation == 0) +- { +- *h = lightness; +- *l = lightness; +- *s = lightness; +- } +- else +- { +- hue = *h + 120; +- while (hue > 360) +- hue -= 360; +- while (hue < 0) +- hue += 360; +- +- if (hue < 60) +- r = m1 + (m2 - m1) * hue / 60; +- else if (hue < 180) +- r = m2; +- else if (hue < 240) +- r = m1 + (m2 - m1) * (240 - hue) / 60; +- else +- r = m1; +- +- hue = *h; +- while (hue > 360) +- hue -= 360; +- while (hue < 0) +- hue += 360; +- +- if (hue < 60) +- g = m1 + (m2 - m1) * hue / 60; +- else if (hue < 180) +- g = m2; +- else if (hue < 240) +- g = m1 + (m2 - m1) * (240 - hue) / 60; +- else +- g = m1; +- +- hue = *h - 120; +- while (hue > 360) +- hue -= 360; +- while (hue < 0) +- hue += 360; +- +- if (hue < 60) +- b = m1 + (m2 - m1) * hue / 60; +- else if (hue < 180) +- b = m2; +- else if (hue < 240) +- b = m1 + (m2 - m1) * (240 - hue) / 60; +- else +- b = m1; +- +- *h = r; +- *l = g; +- *s = b; +- } +-} +- +-void +-shade (const decor_color_t *a, +- decor_color_t *b, +- float k) +-{ +- double red; +- double green; +- double blue; +- +- red = a->r; +- green = a->g; +- blue = a->b; +- +- rgb_to_hls (&red, &green, &blue); +- +- green *= k; +- if (green > 1.0) +- green = 1.0; +- else if (green < 0.0) +- green = 0.0; +- +- blue *= k; +- if (blue > 1.0) +- blue = 1.0; +- else if (blue < 0.0) +- blue = 0.0; +- +- hls_to_rgb (&red, &green, &blue); +- +- b->r = red; +- b->g = green; +- b->b = blue; +-} +- +diff -Nur original/gtk/window-decorator/wnck.c modified/gtk/window-decorator/wnck.c +--- original/gtk/window-decorator/wnck.c 2015-04-11 14:38:52.624406000 +0100 ++++ modified/gtk/window-decorator/wnck.c 2015-04-11 14:34:11.000000000 +0100 +@@ -162,7 +162,7 @@ + } + } + +-void ++static void + update_frames_border_extents (gpointer key, + gpointer value, + gpointer user_data) +@@ -590,7 +590,7 @@ + draw_list = g_slist_remove (draw_list, d); + } + +-void ++static void + connect_window (WnckWindow *win) + { + g_signal_connect_object (win, "name_changed", +@@ -762,7 +762,7 @@ + } + } + +-void ++static void + window_opened (WnckScreen *screen, + WnckWindow *win) + { diff --git a/set-gwd-default.patch b/set-gwd-default.patch new file mode 100644 index 000000000000..624cffbdd5f5 --- /dev/null +++ b/set-gwd-default.patch @@ -0,0 +1,12 @@ +diff -Naur original/plugins/decor/decor.xml.in modified/plugins/decor/decor.xml.in +--- original/plugins/decor/decor.xml.in 2013-07-23 20:58:03.000000000 +0100 ++++ modified/plugins/decor/decor.xml.in 2014-06-11 00:01:50.332286339 +0100 +@@ -101,7 +101,7 @@ + <option name="command" type="string"> + <_short>Command</_short> + <_long>Decorator command line that is executed if no decorator is already running.</_long> +- <default>exec \"${COMPIZ_BIN_PATH}compiz-decorator\"</default> ++ <default>gtk-window-decorator</default> + </option> + <option name="mipmap" type="bool"> + <_short>Mipmap</_short> |