summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob McCathie2016-10-20 10:17:00 +1100
committerRob McCathie2016-10-20 10:17:00 +1100
commit8331527f7d5b8ceda0074d8b2820d5e07bc2ff0e (patch)
treefcadb59474bd79700711a30473ca7b5e777db4b3
parent4a939da17d19b89725c0248e9f494f601cafc3e3 (diff)
downloadaur-compiz-manjaro.tar.gz
update for metacity 3.22 support
-rw-r--r--.SRCINFO8
-rw-r--r--PKGBUILD9
-rwxr-xr-xcompiz-gtk-decorator-theme-selector4
-rw-r--r--metacity322-branch-rollup.patch1617
4 files changed, 1631 insertions, 7 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 666c5ebc7267..420b70667396 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,9 +1,9 @@
# Generated by makepkg 5.0.1
-# Wed Aug 3 06:18:17 UTC 2016
+# Wed Oct 19 23:08:28 UTC 2016
pkgbase = compiz-manjaro
pkgdesc = OpenGL compositing window manager. Includes friendly defaults, GWD theme selector and autostart for Xfce & MATE.
pkgver = 0.9.13.0
- pkgrel = 3
+ pkgrel = 5
url = https://launchpad.net/compiz
install = compiz-manjaro.install
arch = i686
@@ -61,6 +61,7 @@ pkgbase = compiz-manjaro
source = focus-prevention-disable.patch
source = gtk-extents.patch
source = trailfocus-fix.patch
+ source = metacity322-branch-rollup.patch
source = compiz-manjaro-defaults.patch
source = compiz-manjaro.gschema.override
source = compiz-gtk-decorator-theme-selector
@@ -74,9 +75,10 @@ pkgbase = compiz-manjaro
sha256sums = f4897590b0f677ba34767a29822f8f922a750daf66e8adf47be89f7c2550cf4b
sha256sums = 16ddb6311ce42d958505e21ca28faae5deeddce02cb558d55e648380274ba4d9
sha256sums = 01e94ac52cd39eb5462a8505c7df61c7b14b05159de64f8700dfadb524bdb2ce
+ sha256sums = 4deb954e539853ab5297d0603b1dd7ce72361425d7d88e4e49c9351d91bf0a91
sha256sums = b635bfbefd558cd255d6cb119378b01d9b3815b8f5f6b3a03dfe736c0cd5746b
sha256sums = 149213e0b29e34744b6e8e51cdaccc4011fd29c5f9475c59aa7482f3fe4a68af
- sha256sums = aca18e14854a466262f876bf7463d786c88453820abc89027608d732bb79a542
+ sha256sums = 28d14e5ec0694b4a451540f35210eac5699e9daf1b00020bf59d8b0296d7d9bf
sha256sums = 0faaf9e9df28d2857108ccd0910d50ba631c34c2b1659b8860da8c2b552fc889
sha256sums = 3e46a0b50a16d9fd6fd4f9d28f6082fc76f39dff8a82a79af312126a6bcf7cc2
sha256sums = d23b8633186bb3a2a841734ad0b917500f3536a67046f5d8fbb08818eab59160
diff --git a/PKGBUILD b/PKGBUILD
index 991f6aca6e7d..dad1d3feab30 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -6,7 +6,7 @@ _name=compiz
pkgname=compiz-manjaro
_series=0.9.13
pkgver=${_series}.0
-pkgrel=3
+pkgrel=5
_greybirdver=1.6.2
pkgdesc="OpenGL compositing window manager. Includes friendly defaults, GWD theme selector and autostart for Xfce & MATE."
arch=('i686' 'x86_64')
@@ -26,6 +26,7 @@ source=("${url}/${_series}/${pkgver}/+download/${_name}-${pkgver}.tar.bz2"
"focus-prevention-disable.patch"
"gtk-extents.patch"
"trailfocus-fix.patch"
+ "metacity322-branch-rollup.patch"
"${pkgname}-defaults.patch"
"${pkgname}.gschema.override"
"compiz-gtk-decorator-theme-selector"
@@ -39,9 +40,10 @@ sha256sums=('f08eb54d578be559e3e723f3fe4291a56f5c96b2fdfb9c9e74ebb6596a1ca702'
'f4897590b0f677ba34767a29822f8f922a750daf66e8adf47be89f7c2550cf4b'
'16ddb6311ce42d958505e21ca28faae5deeddce02cb558d55e648380274ba4d9'
'01e94ac52cd39eb5462a8505c7df61c7b14b05159de64f8700dfadb524bdb2ce'
+ '4deb954e539853ab5297d0603b1dd7ce72361425d7d88e4e49c9351d91bf0a91'
'b635bfbefd558cd255d6cb119378b01d9b3815b8f5f6b3a03dfe736c0cd5746b'
'149213e0b29e34744b6e8e51cdaccc4011fd29c5f9475c59aa7482f3fe4a68af'
- 'aca18e14854a466262f876bf7463d786c88453820abc89027608d732bb79a542'
+ '28d14e5ec0694b4a451540f35210eac5699e9daf1b00020bf59d8b0296d7d9bf'
'0faaf9e9df28d2857108ccd0910d50ba631c34c2b1659b8860da8c2b552fc889'
'3e46a0b50a16d9fd6fd4f9d28f6082fc76f39dff8a82a79af312126a6bcf7cc2'
'd23b8633186bb3a2a841734ad0b917500f3536a67046f5d8fbb08818eab59160'
@@ -72,6 +74,9 @@ prepare() {
# Fix ambiguous function call in trailfocus plugin
patch -p1 -i "${srcdir}/trailfocus-fix.patch"
+ # Metacity 3.22 support
+ patch -p1 -i "${srcdir}/metacity322-branch-rollup.patch"
+
# Manjaro defaults
patch -p1 -i "${srcdir}/${pkgname}-defaults.patch"
}
diff --git a/compiz-gtk-decorator-theme-selector b/compiz-gtk-decorator-theme-selector
index 32076d0c848b..b8f3119084dc 100755
--- a/compiz-gtk-decorator-theme-selector
+++ b/compiz-gtk-decorator-theme-selector
@@ -10,10 +10,10 @@ fi
main_window() {
selection=$(
zenity --height 450 --width 320 --list --ok-label="Apply" --cancel-label="Close" --title="Metacity themes" \
- --column="Current theme: $( if [ $(gsettings get org.gnome.metacity theme) == "''" ]; then
+ --column="Current theme: $( if [ $(gsettings get org.gnome.desktop.wm.preferences theme) == "''" ]; then
echo Default
else
- gsettings get org.gnome.metacity theme
+ gsettings get org.gnome.desktop.wm.preferences theme
fi)" \
"Compiz GWD default" \
$(
diff --git a/metacity322-branch-rollup.patch b/metacity322-branch-rollup.patch
new file mode 100644
index 000000000000..68eb38897fd8
--- /dev/null
+++ b/metacity322-branch-rollup.patch
@@ -0,0 +1,1617 @@
+diff -Nur original/gtk/CMakeLists.txt modified/gtk/CMakeLists.txt
+--- original/gtk/CMakeLists.txt 2016-10-15 09:33:19.000000000 +0100
++++ modified/gtk/CMakeLists.txt 2016-10-15 09:32:49.000000000 +0100
+@@ -25,24 +25,15 @@
+ set (CMAKE_REQUIRED_LIBRARIES "")
+
+ if (USE_METACITY)
+- pkg_check_modules (LIBMETACITY libmetacity>=3.19.1)
++ pkg_check_modules (LIBMETACITY libmetacity>=3.20.0)
+
+ if (LIBMETACITY_FOUND)
+- compiz_set (HAVE_METACITY_3_20_0 1)
++ compiz_pkg_check_modules (HAVE_METACITY_3_22_0 libmetacity>=3.22.0)
+
+ set (METACITY_INCLUDE_DIRS ${LIBMETACITY_INCLUDE_DIRS})
+ set (METACITY_LIBRARIES ${LIBMETACITY_LIBRARIES})
+ else (LIBMETACITY_FOUND)
+- pkg_check_modules (LIBMETACITY_PRIVATE libmetacity-private>=3.16.0)
+-
+- if (LIBMETACITY_PRIVATE_FOUND)
+- compiz_set (HAVE_METACITY_3_20_0 0)
+-
+- set (METACITY_INCLUDE_DIRS ${LIBMETACITY_PRIVATE_INCLUDE_DIRS})
+- set (METACITY_LIBRARIES ${LIBMETACITY_PRIVATE_LIBRARIES})
+- else (LIBMETACITY_PRIVATE_FOUND)
+- compiz_set (USE_METACITY 0)
+- endif (LIBMETACITY_PRIVATE_FOUND)
++ compiz_set (USE_METACITY 0)
+ endif (LIBMETACITY_FOUND)
+ endif (USE_METACITY)
+
+diff -Nur original/gtk/config.h.gtk.in modified/gtk/config.h.gtk.in
+--- original/gtk/config.h.gtk.in 2016-10-15 09:33:19.000000000 +0100
++++ modified/gtk/config.h.gtk.in 2016-10-15 09:32:49.000000000 +0100
+@@ -1,7 +1,7 @@
+ /* Define to 1 if Metacity support is enabled */
+ #cmakedefine USE_METACITY 1
+
+-/* Define to 1 if Metacity version >= 3.20.0 */
+-#cmakedefine HAVE_METACITY_3_20_0 1
++/* Define to 1 if Metacity version >= 3.22.0 */
++#cmakedefine HAVE_METACITY_3_22_0 1
+
+ #define GETTEXT_PACKAGE "${GETTEXT_PACKAGE}"
+diff -Nur original/gtk/window-decorator/decorator.c modified/gtk/window-decorator/decorator.c
+--- original/gtk/window-decorator/decorator.c 2016-10-15 09:33:19.000000000 +0100
++++ modified/gtk/window-decorator/decorator.c 2016-10-15 09:32:49.000000000 +0100
+@@ -778,11 +778,26 @@
+ decor_shadow_options_t *opt_shadow,
+ decor_shadow_options_t *opt_no_shadow)
+ {
++ gint left, right, top, bottom;
++
+ if (*shadow_normal)
+ {
+ decor_shadow_destroy (xdisplay, *shadow_normal);
+ *shadow_normal = NULL;
+ }
++
++ left = frame->win_extents.left;
++ right = frame->win_extents.right;
++ top = frame->win_extents.top;
++ bottom = frame->win_extents.bottom;
++
++ if (frame->has_shadow_extents)
++ {
++ left += frame->shadow_extents.left;
++ right += frame->shadow_extents.right;
++ top += frame->shadow_extents.top;
++ bottom += frame->shadow_extents.bottom;
++ }
+
+ /*
+ * Warning: decor_shadow_create does more than return a decor_shadow_t*
+@@ -793,19 +808,12 @@
+ *shadow_normal = decor_shadow_create (xdisplay,
+ screen,
+ 1, 1,
+- frame->win_extents.left,
+- frame->win_extents.right,
+- frame->win_extents.top,
+- frame->win_extents.bottom,
+- frame->win_extents.left -
+- TRANSLUCENT_CORNER_SIZE,
+- frame->win_extents.right -
+- TRANSLUCENT_CORNER_SIZE,
+- frame->win_extents.top -
+- TRANSLUCENT_CORNER_SIZE,
+- frame->win_extents.bottom -
+- TRANSLUCENT_CORNER_SIZE,
+- opt_shadow,
++ left, right, top, bottom,
++ left - TRANSLUCENT_CORNER_SIZE,
++ right - TRANSLUCENT_CORNER_SIZE,
++ top - TRANSLUCENT_CORNER_SIZE,
++ bottom - TRANSLUCENT_CORNER_SIZE,
++ frame->has_shadow_extents ? opt_no_shadow : opt_shadow,
+ context_normal,
+ draw_border_shape,
+ (void *) info);
+@@ -817,6 +825,19 @@
+ *shadow_max = NULL;
+ }
+
++ left = frame->max_win_extents.left;
++ right = frame->max_win_extents.right;
++ top = frame->max_win_extents.top;
++ bottom = frame->max_win_extents.bottom;
++
++ if (frame->has_shadow_extents)
++ {
++ left += frame->max_shadow_extents.left;
++ right += frame->max_shadow_extents.right;
++ top += frame->max_shadow_extents.top;
++ bottom += frame->max_shadow_extents.bottom;
++ }
++
+ info->state = (WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY |
+ WNCK_WINDOW_STATE_MAXIMIZED_VERTICALLY);
+
+@@ -824,14 +845,11 @@
+ decor_shadow_create (xdisplay,
+ screen,
+ 1, 1,
+- frame->max_win_extents.left,
+- frame->max_win_extents.right,
+- frame->max_win_extents.top,
+- frame->max_win_extents.bottom,
+- frame->max_win_extents.left - TRANSLUCENT_CORNER_SIZE,
+- frame->max_win_extents.right - TRANSLUCENT_CORNER_SIZE,
+- frame->max_win_extents.top - TRANSLUCENT_CORNER_SIZE,
+- frame->max_win_extents.bottom - TRANSLUCENT_CORNER_SIZE,
++ left, right, top, bottom,
++ left - TRANSLUCENT_CORNER_SIZE,
++ right - TRANSLUCENT_CORNER_SIZE,
++ top - TRANSLUCENT_CORNER_SIZE,
++ bottom - TRANSLUCENT_CORNER_SIZE,
+ opt_no_shadow, /* No shadow when maximized */
+ context_max,
+ draw_border_shape,
+@@ -1360,13 +1378,16 @@
+
+ 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->max_window_context_active = _shadow_context;
+ frame->max_window_context_inactive = _shadow_context;
+ frame->update_shadow = bare_frame_update_shadow;
+
++ frame->has_shadow_extents = FALSE;
++ frame->shadow_extents = _shadow_extents;
++ frame->max_shadow_extents = _shadow_extents;
++
+ return frame;
+ }
+
+@@ -1387,6 +1408,7 @@
+ 0, 0, 0, 0
+ };
+
++ decor_extents_t _shadow_extents = { 0, 0, 0, 0 };
+ decor_extents_t _win_extents = { 6, 6, 6, 6 };
+ decor_extents_t _max_win_extents = { 6, 6, 4, 6 };
+
+@@ -1398,5 +1420,9 @@
+ frame->max_window_context_active = _max_window_context;
+ frame->max_window_context_inactive = _max_window_context;
+
++ frame->has_shadow_extents = FALSE;
++ frame->shadow_extents = _shadow_extents;
++ frame->max_shadow_extents = _shadow_extents;
++
+ return frame;
+ }
+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 2016-10-15 09:33:19.000000000 +0100
++++ modified/gtk/window-decorator/gtk-window-decorator.h 2016-10-15 09:32:49.000000000 +0100
+@@ -221,6 +221,10 @@
+ gint text_height;
+ gchar *type;
+
++ gboolean has_shadow_extents;
++ decor_extents_t shadow_extents;
++ decor_extents_t max_shadow_extents;
++
+ frame_update_shadow_proc update_shadow;
+ gint refcount;
+ };
+diff -Nur original/gtk/window-decorator/gwd-settings-storage.c modified/gtk/window-decorator/gwd-settings-storage.c
+--- original/gtk/window-decorator/gwd-settings-storage.c 2016-10-15 09:33:19.000000000 +0100
++++ modified/gtk/window-decorator/gwd-settings-storage.c 2016-10-15 09:32:49.000000000 +0100
+@@ -24,7 +24,7 @@
+
+ #include <gtk/gtk.h>
+
+-#ifdef HAVE_METACITY_3_20_0
++#ifdef USE_METACITY
+ #include <libmetacity/meta-theme.h>
+ #endif
+
+@@ -33,13 +33,7 @@
+
+ static const gchar * ORG_COMPIZ_GWD = "org.compiz.gwd";
+ static const gchar * ORG_GNOME_DESKTOP_WM_PREFERENCES = "org.gnome.desktop.wm.preferences";
+-
+-#ifdef HAVE_METACITY_3_20_0
+ static const gchar * ORG_GNOME_METACITY_THEME = "org.gnome.metacity.theme";
+-#else
+-static const gchar * ORG_GNOME_METACITY = "org.gnome.metacity";
+-#endif
+-
+ static const gchar * ORG_MATE_MARCO_GENERAL = "org.mate.Marco.general";
+
+ static const gchar * ORG_COMPIZ_GWD_KEY_USE_TOOLTIPS = "use-tooltips";
+@@ -51,12 +45,8 @@
+ static const gchar * ORG_COMPIZ_GWD_KEY_USE_METACITY_THEME = "use-metacity-theme";
+ static const gchar * ORG_COMPIZ_GWD_KEY_MOUSE_WHEEL_ACTION = "mouse-wheel-action";
+
+-#ifdef HAVE_METACITY_3_20_0
+ static const gchar * ORG_GNOME_METACITY_THEME_NAME = "name";
+ static const gchar * ORG_GNOME_METACITY_THEME_TYPE = "type";
+-#else
+-static const gchar * ORG_GNOME_METACITY_THEME = "theme";
+-#endif
+
+ static const gchar * ORG_GNOME_DESKTOP_WM_PREFERENCES_ACTION_DOUBLE_CLICK_TITLEBAR = "action-double-click-titlebar";
+ static const gchar * ORG_GNOME_DESKTOP_WM_PREFERENCES_ACTION_MIDDLE_CLICK_TITLEBAR = "action-middle-click-titlebar";
+@@ -213,7 +203,6 @@
+ if (storage->current_desktop == GWD_DESKTOP_MATE && storage->marco) {
+ metacity_theme_name = g_settings_get_string (storage->marco, ORG_MATE_MARCO_GENERAL_THEME);
+ } else if (storage->current_desktop == GWD_DESKTOP_GNOME_FLASHBACK && storage->metacity) {
+-#ifdef HAVE_METACITY_3_20_0
+ metacity_theme_type = g_settings_get_enum (storage->metacity, ORG_GNOME_METACITY_THEME_TYPE);
+
+ if (metacity_theme_type == META_THEME_TYPE_GTK) {
+@@ -221,9 +210,6 @@
+ } else {
+ metacity_theme_name = g_settings_get_string (storage->metacity, ORG_GNOME_METACITY_THEME_NAME);
+ }
+-#else
+- metacity_theme_name = g_settings_get_string (storage->metacity, ORG_GNOME_METACITY_THEME);
+-#endif
+ } else if (storage->desktop) {
+ metacity_theme_name = g_settings_get_string (storage->desktop, ORG_GNOME_DESKTOP_WM_PREFERENCES_THEME);
+ } else {
+@@ -385,14 +371,9 @@
+ const gchar *key,
+ GWDSettingsStorage *storage)
+ {
+-#ifdef HAVE_METACITY_3_20_0
+ if (strcmp (key, ORG_GNOME_METACITY_THEME_NAME) == 0 ||
+ strcmp (key, ORG_GNOME_METACITY_THEME_TYPE) == 0)
+ update_metacity_theme (storage);
+-#else
+- if (strcmp (key, ORG_GNOME_METACITY_THEME) == 0)
+- update_metacity_theme (storage);
+-#endif
+ }
+
+ static void
+@@ -423,12 +404,12 @@
+ update_button_layout (storage);
+ }
+
+-#ifdef HAVE_METACITY_3_20_0
+ static void
+ gtk_theme_name_changed (GtkSettings *settings,
+ GParamSpec *pspec,
+ GWDSettingsStorage *storage)
+ {
++#ifdef USE_METACITY
+ MetaThemeType type;
+
+ if (!storage->metacity)
+@@ -438,8 +419,8 @@
+
+ if (type == META_THEME_TYPE_GTK)
+ update_metacity_theme (storage);
+-}
+ #endif
++}
+
+ static void
+ gwd_settings_storage_constructed (GObject *object)
+@@ -573,22 +554,15 @@
+ case GWD_DESKTOP_GNOME_FLASHBACK:
+ storage->gwd = get_settings_no_abort (ORG_COMPIZ_GWD);
+ storage->desktop = get_settings_no_abort (ORG_GNOME_DESKTOP_WM_PREFERENCES);
+-
+-#ifdef HAVE_METACITY_3_20_0
+ storage->metacity = get_settings_no_abort (ORG_GNOME_METACITY_THEME);
+-#else
+- storage->metacity = get_settings_no_abort (ORG_GNOME_METACITY);
+-#endif
+
+ storage->gtk_decoration_layout_id =
+ g_signal_connect (gtk_settings_get_default (), "notify::gtk-decoration-layout",
+ G_CALLBACK (gtk_decoration_layout_changed), storage);
+
+-#ifdef HAVE_METACITY_3_20_0
+ storage->gtk_theme_name_id =
+ g_signal_connect (gtk_settings_get_default (), "notify::gtk-theme-name",
+ G_CALLBACK (gtk_theme_name_changed), storage);
+-#endif
+ break;
+
+ case GWD_DESKTOP_MATE:
+diff -Nur original/gtk/window-decorator/gwd-theme.c modified/gtk/window-decorator/gwd-theme.c
+--- original/gtk/window-decorator/gwd-theme.c 2016-10-15 09:33:19.000000000 +0100
++++ modified/gtk/window-decorator/gwd-theme.c 2016-10-15 09:32:49.000000000 +0100
+@@ -248,13 +248,6 @@
+ {
+ }
+
+-static PangoFontDescription *
+-gwd_theme_real_get_titlebar_font (GWDTheme *theme,
+- decor_frame_t *frame)
+-{
+- return NULL;
+-}
+-
+ static void
+ gwd_theme_class_init (GWDThemeClass *theme_class)
+ {
+@@ -275,7 +268,6 @@
+ theme_class->get_event_window_position = gwd_theme_real_get_event_window_position;
+ theme_class->get_button_position = gwd_theme_real_get_button_position;
+ theme_class->update_titlebar_font = gwd_theme_real_update_titlebar_font;
+- theme_class->get_titlebar_font = gwd_theme_real_get_titlebar_font;
+
+ properties[PROP_SETTINGS] =
+ g_param_spec_object ("settings", "GWDSettings", "GWDSettings",
+@@ -433,11 +425,6 @@
+ GWDThemePrivate *priv = gwd_theme_get_instance_private (theme);
+ GtkStyleContext *context = gtk_widget_get_style_context (priv->style_window);
+
+- /* Check if Metacity or Cairo will create titlebar font */
+- font_desc = GWD_THEME_GET_CLASS (theme)->get_titlebar_font (theme, frame);
+- if (font_desc)
+- return font_desc;
+-
+ /* Check if non-system font is in use */
+ if (priv->titlebar_font)
+ return pango_font_description_copy (priv->titlebar_font);
+diff -Nur original/gtk/window-decorator/gwd-theme.h modified/gtk/window-decorator/gwd-theme.h
+--- original/gtk/window-decorator/gwd-theme.h 2016-10-15 09:33:19.000000000 +0100
++++ modified/gtk/window-decorator/gwd-theme.h 2016-10-15 09:32:49.000000000 +0100
+@@ -37,53 +37,50 @@
+ {
+ GObjectClass parent_class;
+
+- void (* style_updated) (GWDTheme *theme);
++ void (* style_updated) (GWDTheme *theme);
+
+- void (* get_shadow) (GWDTheme *theme,
+- decor_frame_t *frame,
+- decor_shadow_options_t *options,
+- gboolean active);
+-
+- void (* draw_window_decoration) (GWDTheme *theme,
+- decor_t *decor);
+-
+- gboolean (* calc_decoration_size) (GWDTheme *theme,
+- decor_t *decor,
+- gint w,
+- gint h,
+- gint name_width,
+- gint *width,
+- gint *height);
+-
+- void (* update_border_extents) (GWDTheme *theme,
+- decor_frame_t *frame);
+-
+- void (* get_event_window_position) (GWDTheme *theme,
+- decor_t *decor,
+- gint i,
+- gint j,
+- gint width,
+- gint height,
+- gint *x,
+- gint *y,
+- gint *w,
+- gint *h);
+-
+- gboolean (* get_button_position) (GWDTheme *theme,
+- decor_t *decor,
+- gint i,
+- gint width,
+- gint height,
+- gint *x,
+- gint *y,
+- gint *w,
+- gint *h);
++ void (* get_shadow) (GWDTheme *theme,
++ decor_frame_t *frame,
++ decor_shadow_options_t *options,
++ gboolean active);
++
++ void (* draw_window_decoration) (GWDTheme *theme,
++ decor_t *decor);
++
++ gboolean (* calc_decoration_size) (GWDTheme *theme,
++ decor_t *decor,
++ gint w,
++ gint h,
++ gint name_width,
++ gint *width,
++ gint *height);
++
++ void (* update_border_extents) (GWDTheme *theme,
++ decor_frame_t *frame);
++
++ void (* get_event_window_position) (GWDTheme *theme,
++ decor_t *decor,
++ gint i,
++ gint j,
++ gint width,
++ gint height,
++ gint *x,
++ gint *y,
++ gint *w,
++ gint *h);
++
++ gboolean (* get_button_position) (GWDTheme *theme,
++ decor_t *decor,
++ gint i,
++ gint width,
++ gint height,
++ gint *x,
++ gint *y,
++ gint *w,
++ gint *h);
+
+- void (* update_titlebar_font) (GWDTheme *theme,
+- const PangoFontDescription *titlebar_font);
+-
+- PangoFontDescription * (* get_titlebar_font) (GWDTheme *theme,
+- decor_frame_t *frame);
++ void (* update_titlebar_font) (GWDTheme *theme,
++ const PangoFontDescription *titlebar_font);
+ };
+
+ typedef enum
+diff -Nur original/gtk/window-decorator/gwd-theme-metacity.c modified/gtk/window-decorator/gwd-theme-metacity.c
+--- original/gtk/window-decorator/gwd-theme-metacity.c 2016-10-15 09:33:19.000000000 +0100
++++ modified/gtk/window-decorator/gwd-theme-metacity.c 2016-10-15 09:32:49.000000000 +0100
+@@ -27,12 +27,7 @@
+
+ #include "config.h"
+
+-#ifdef HAVE_METACITY_3_20_0
+ #include <libmetacity/meta-theme.h>
+-#else
+-#include <metacity-private/theme.h>
+-#include <metacity-private/theme-parser.h>
+-#endif
+
+ #include "gtk-window-decorator.h"
+ #include "gwd-settings.h"
+@@ -40,47 +35,19 @@
+
+ struct _GWDThemeMetacity
+ {
+- GObject parent;
++ GObject parent;
+
+- MetaTheme *theme;
+-
+-#ifndef HAVE_METACITY_3_20_0
+- GHashTable *style_variants;
+-#endif
++ MetaTheme *theme;
+
+- gulong button_layout_id;
+- MetaButtonLayout button_layout;
++ gulong button_layout_id;
+
+-#ifndef HAVE_METACITY_3_20_0
+- const PangoFontDescription *titlebar_font;
++#ifndef HAVE_METACITY_3_22_0
++ MetaButtonLayout button_layout;
+ #endif
+ };
+
+ G_DEFINE_TYPE (GWDThemeMetacity, gwd_theme_metacity, GWD_TYPE_THEME)
+
+-#ifndef HAVE_METACITY_3_20_0
+-static MetaStyleInfo *
+-get_style_info (GWDThemeMetacity *metacity,
+- decor_t *decor)
+-{
+- const gchar *variant = decor != NULL ? decor->gtk_theme_variant : NULL;
+- const gchar *key = variant != NULL ? variant : "default";
+- MetaStyleInfo *style = g_hash_table_lookup (metacity->style_variants, key);
+-
+- if (style == NULL) {
+- GWDTheme *theme = GWD_THEME (metacity);
+- GtkWidget *style_window = gwd_theme_get_style_window (theme);
+- GdkScreen *screen = gtk_widget_get_screen (style_window);
+-
+- style = meta_theme_create_style_info (screen, variant);
+-
+- g_hash_table_insert (metacity->style_variants, g_strdup (key), style);
+- }
+-
+- return style;
+-}
+-#endif
+-
+ static MetaFrameType
+ frame_type_from_string (const gchar *str)
+ {
+@@ -96,234 +63,77 @@
+ return META_FRAME_TYPE_NORMAL;
+ }
+
+-#ifndef HAVE_METACITY_3_20_0
+-static void
+-initialize_button_layout (MetaButtonLayout *layout)
+-{
+- gint 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;
+- }
+-}
+-
+-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;
+- }
+-}
+-#endif
+-
+ static void
+ update_metacity_button_layout_cb (GWDSettings *settings,
+ const gchar *button_layout,
+ GWDThemeMetacity *metacity)
+ {
+-#ifdef HAVE_METACITY_3_20_0
+ gboolean invert = gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL;
+
+- metacity->button_layout = meta_button_layout_new (button_layout, invert);
++#ifdef HAVE_METACITY_3_22_0
++ meta_theme_set_button_layout (metacity->theme, button_layout, invert);
+ #else
+- MetaButtonLayout new_layout;
+-
+- initialize_button_layout (&new_layout);
+-
+- if (button_layout != NULL) {
+- gint i;
+- gchar **sides;
+- MetaButtonFunction f;
+-
+- sides = g_strsplit (button_layout, ":", 2);
+-
+- if (sides[0] != NULL) {
+- gchar **buttons;
+- gint 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 {
+- g_warning ("Ignoring unknown or already-used "
+- "button name \"%s\"", 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 {
+- g_warning ("Ignoring unknown or already-used "
+- "button name \"%s\"", 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;
+- gint j;
+-
+- 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];
+- }
++ metacity->button_layout = meta_button_layout_new (button_layout, invert);
++#endif
++}
+
+- 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];
+- }
++static MetaButtonState
++meta_button_state (gint state)
++{
++ if (state & IN_EVENT_WINDOW) {
++ if (state & PRESSED_EVENT_WINDOW)
++ return META_BUTTON_STATE_PRESSED;
+
+- new_layout = rtl_layout;
+- }
+- } else {
+- gint i;
++ return META_BUTTON_STATE_PRELIGHT;
++ }
+
+- new_layout.left_buttons[0] = META_BUTTON_FUNCTION_MENU;
++ return META_BUTTON_STATE_NORMAL;
++}
+
+- for (i = 1; i < MAX_BUTTONS_PER_CORNER; ++i)
+- new_layout.left_buttons[i] = META_BUTTON_FUNCTION_LAST;
++#ifdef HAVE_METACITY_3_22_0
++static MetaButtonState
++meta_button_state_for_button_type (decor_t *decor,
++ MetaButtonType type)
++{
++ switch (type) {
++ case META_BUTTON_TYPE_CLOSE:
++ return meta_button_state (decor->button_states[BUTTON_CLOSE]);
++ case META_BUTTON_TYPE_MAXIMIZE:
++ return meta_button_state (decor->button_states[BUTTON_MAX]);
++ case META_BUTTON_TYPE_MINIMIZE:
++ return meta_button_state (decor->button_states[BUTTON_MIN]);
++ case META_BUTTON_TYPE_MENU:
++ return meta_button_state (decor->button_states[BUTTON_MENU]);
++ case META_BUTTON_TYPE_SHADE:
++ return meta_button_state (decor->button_states[BUTTON_SHADE]);
++ case META_BUTTON_TYPE_ABOVE:
++ return meta_button_state (decor->button_states[BUTTON_ABOVE]);
++ case META_BUTTON_TYPE_STICK:
++ return meta_button_state (decor->button_states[BUTTON_STICK]);
++ case META_BUTTON_TYPE_UNSHADE:
++ return meta_button_state (decor->button_states[BUTTON_UNSHADE]);
++ case META_BUTTON_TYPE_UNABOVE:
++ return meta_button_state (decor->button_states[BUTTON_UNABOVE]);
++ case META_BUTTON_TYPE_UNSTICK:
++ return meta_button_state (decor->button_states[BUTTON_UNSTICK]);
++ default:
++ break;
++ }
+
+- new_layout.right_buttons[0] = META_BUTTON_FUNCTION_MINIMIZE;
+- new_layout.right_buttons[1] = META_BUTTON_FUNCTION_MAXIMIZE;
+- new_layout.right_buttons[2] = META_BUTTON_FUNCTION_CLOSE;
++ return META_BUTTON_STATE_NORMAL;
++}
+
+- for (i = 3; i < MAX_BUTTONS_PER_CORNER; ++i)
+- new_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST;
+- }
++static MetaButtonState
++update_button_state (MetaButtonType type,
++ GdkRectangle rect,
++ gpointer user_data)
++{
++ decor_t *decor = (decor_t *) user_data;
+
+- metacity->button_layout = new_layout;
+-#endif
++ return meta_button_state_for_button_type (decor, type);
+ }
+
++#else
+ static MetaButtonType
+ meta_function_to_type (MetaButtonFunction function)
+ {
+@@ -356,19 +166,6 @@
+ }
+
+ static MetaButtonState
+-meta_button_state (gint 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 MetaButtonState
+ meta_button_state_for_button_type (GWDThemeMetacity *metacity,
+ decor_t *decor,
+ MetaButtonType type)
+@@ -422,6 +219,7 @@
+
+ return META_BUTTON_STATE_NORMAL;
+ }
++#endif
+
+ static gint
+ radius_to_width (gint radius,
+@@ -448,8 +246,10 @@
+
+ static Region
+ get_top_border_region (const MetaFrameGeometry *fgeom,
+- gint width)
++ gboolean subtract_borders)
+ {
++ GtkBorder invisible = fgeom->borders.invisible;
++ GtkBorder shadow = fgeom->borders.shadow;
+ Region corners_xregion;
+ Region border_xregion;
+ XRectangle xrect;
+@@ -459,6 +259,7 @@
+ gint bottom_right_radius;
+ gint w;
+ gint i;
++ gint width;
+ gint height;
+
+ corners_xregion = XCreateRegion ();
+@@ -466,10 +267,10 @@
+ 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;
++ width = fgeom->width - invisible.left - invisible.right + shadow.left + shadow.right;
++ height = fgeom->borders.visible.top + shadow.top;
+
+- if (top_left_radius) {
++ if (top_left_radius && subtract_borders) {
+ for (i = 0; i < top_left_radius; ++i) {
+ w = radius_to_width (top_left_radius, i);
+
+@@ -482,7 +283,7 @@
+ }
+ }
+
+- if (top_right_radius) {
++ if (top_right_radius && subtract_borders) {
+ for (i = 0; i < top_right_radius; ++i) {
+ w = radius_to_width (top_right_radius, i);
+
+@@ -512,8 +313,10 @@
+
+ static Region
+ get_bottom_border_region (const MetaFrameGeometry *fgeom,
+- gint width)
++ gboolean subtract_borders)
+ {
++ GtkBorder invisible = fgeom->borders.invisible;
++ GtkBorder shadow = fgeom->borders.shadow;
+ Region corners_xregion;
+ Region border_xregion;
+ XRectangle xrect;
+@@ -523,6 +326,7 @@
+ gint bottom_right_radius;
+ gint w;
+ gint i;
++ gint width;
+ gint height;
+
+ corners_xregion = XCreateRegion ();
+@@ -530,10 +334,10 @@
+ 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;
++ width = fgeom->width - invisible.left - invisible.right + shadow.left + shadow.right;
++ height = fgeom->borders.visible.bottom + shadow.bottom;
+
+- if (bottom_left_radius) {
++ if (bottom_left_radius && subtract_borders) {
+ for (i = 0; i < bottom_left_radius; ++i) {
+ w = radius_to_width (bottom_left_radius, i);
+
+@@ -546,7 +350,7 @@
+ }
+ }
+
+- if (bottom_right_radius) {
++ if (bottom_right_radius && subtract_borders) {
+ for (i = 0; i < bottom_right_radius; ++i) {
+ w = radius_to_width (bottom_right_radius, i);
+
+@@ -575,8 +379,7 @@
+ }
+
+ static Region
+-get_left_border_region (const MetaFrameGeometry *fgeom,
+- gint height)
++get_left_border_region (const MetaFrameGeometry *fgeom)
+ {
+ Region border_xregion;
+ XRectangle xrect;
+@@ -585,8 +388,8 @@
+
+ xrect.x = 0;
+ xrect.y = 0;
+- xrect.width = fgeom->borders.visible.left;
+- xrect.height = height - fgeom->borders.total.top - fgeom->borders.total.bottom;
++ xrect.width = fgeom->borders.visible.left + fgeom->borders.shadow.left;
++ xrect.height = fgeom->height - fgeom->borders.total.top - fgeom->borders.total.bottom;
+
+ XUnionRectWithRegion (&xrect, border_xregion, border_xregion);
+
+@@ -594,8 +397,7 @@
+ }
+
+ static Region
+-get_right_border_region (const MetaFrameGeometry *fgeom,
+- gint height)
++get_right_border_region (const MetaFrameGeometry *fgeom)
+ {
+ Region border_xregion;
+ XRectangle xrect;
+@@ -604,8 +406,8 @@
+
+ xrect.x = 0;
+ xrect.y = 0;
+- xrect.width = fgeom->borders.visible.right;
+- xrect.height = height - fgeom->borders.total.top - fgeom->borders.total.bottom;
++ xrect.width = fgeom->borders.visible.right + fgeom->borders.shadow.right;
++ xrect.height = fgeom->height - fgeom->borders.total.top - fgeom->borders.total.bottom;
+
+ XUnionRectWithRegion (&xrect, border_xregion, border_xregion);
+
+@@ -652,42 +454,22 @@
+ MetaFrameBorders borders;
+
+ tmp_flags = flags & ~META_FRAME_MAXIMIZED;
+-#ifdef HAVE_METACITY_3_20_0
+ meta_theme_get_frame_borders (metacity->theme, d->gtk_theme_variant,
+ type, tmp_flags, &borders);
+-#else
+- meta_theme_get_frame_borders (metacity->theme, get_style_info (metacity, d),
+- type, d->frame->text_height, tmp_flags, &borders);
+-#endif
+-
+- if (flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE) {
+- frame_win_extents.left += borders.invisible.left;
+- frame_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_win_extents.left += borders.resize.left;
++ frame_win_extents.right += borders.resize.right;
++ frame_win_extents.bottom += borders.resize.bottom;
++ frame_win_extents.top += borders.resize.top;
+
+ tmp_flags = flags | META_FRAME_MAXIMIZED;
+-#ifdef HAVE_METACITY_3_20_0
+ meta_theme_get_frame_borders (metacity->theme, d->gtk_theme_variant,
+ type, tmp_flags, &borders);
+-#else
+- meta_theme_get_frame_borders (metacity->theme, get_style_info (metacity, d),
+- type, d->frame->text_height, tmp_flags, &borders);
+-#endif
+-
+- if (flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE) {
+- frame_max_win_extents.left += borders.invisible.left;
+- frame_max_win_extents.right += borders.invisible.right;
+- }
+
+- if (flags & META_FRAME_ALLOWS_VERTICAL_RESIZE) {
+- frame_max_win_extents.bottom += borders.invisible.bottom;
+- frame_max_win_extents.top += borders.invisible.top;
+- }
++ frame_max_win_extents.left += borders.resize.left;
++ frame_max_win_extents.right += borders.resize.right;
++ frame_max_win_extents.bottom += borders.resize.bottom;
++ frame_max_win_extents.top += borders.resize.top;
+ }
+
+ w = d->border_layout.top.x2 - d->border_layout.top.x1 -
+@@ -807,14 +589,14 @@
+ else
+ client_height = decor->border_layout.left.y2 - decor->border_layout.left.y1;
+
+-#ifdef HAVE_METACITY_3_20_0
++#ifdef HAVE_METACITY_3_22_0
+ meta_theme_calc_geometry (metacity->theme, decor->gtk_theme_variant,
+ frame_type, *flags, client_width, client_height,
+- &metacity->button_layout, fgeom);
++ fgeom);
+ #else
+- meta_theme_calc_geometry (metacity->theme, get_style_info (metacity, decor),
+- frame_type, decor->frame->text_height, *flags, client_width,
+- client_height, &metacity->button_layout, fgeom);
++ meta_theme_calc_geometry (metacity->theme, decor->gtk_theme_variant,
++ frame_type, *flags, client_width, client_height,
++ &metacity->button_layout, fgeom);
+ #endif
+ }
+
+@@ -862,6 +644,38 @@
+ decor->button_width = width - min_x;
+ }
+
++#ifdef HAVE_METACITY_3_22_0
++static MetaButtonType
++button_to_meta_button_type (gint i)
++{
++ switch (i) {
++ case BUTTON_MENU:
++ return META_BUTTON_TYPE_MENU;
++ case BUTTON_MIN:
++ return META_BUTTON_TYPE_MINIMIZE;
++ case BUTTON_MAX:
++ return META_BUTTON_TYPE_MAXIMIZE;
++ case BUTTON_CLOSE:
++ return META_BUTTON_TYPE_CLOSE;
++ case BUTTON_SHADE:
++ return META_BUTTON_TYPE_SHADE;
++ case BUTTON_ABOVE:
++ return META_BUTTON_TYPE_ABOVE;
++ case BUTTON_STICK:
++ return META_BUTTON_TYPE_STICK;
++ case BUTTON_UNSHADE:
++ return META_BUTTON_TYPE_UNSHADE;
++ case BUTTON_UNABOVE:
++ return META_BUTTON_TYPE_UNABOVE;
++ case BUTTON_UNSTICK:
++ return META_BUTTON_TYPE_UNSTICK;
++ default:
++ break;
++ }
++
++ return META_BUTTON_TYPE_LAST;
++}
++#else
+ static gboolean
+ button_present (GWDThemeMetacity *metacity,
+ MetaButtonFunction function)
+@@ -909,18 +723,15 @@
+
+ return META_BUTTON_FUNCTION_LAST;
+ }
++#endif
+
+ static gboolean
+ setup_theme (GWDThemeMetacity *metacity)
+ {
+ GWDSettings *settings = gwd_theme_get_settings (GWD_THEME (metacity));
+ const gchar *metacity_theme_name = gwd_settings_get_metacity_theme_name (settings);
+-#ifdef HAVE_METACITY_3_20_0
+ gint metacity_theme_type = gwd_settings_get_metacity_theme_type (settings);
+ GError *error = NULL;
+-#else
+- MetaTheme *theme;
+-#endif
+
+ /* metacity_theme can be NULL only in one case - if user has disabled
+ * metacity theme with use-metacity-theme setting. In that case
+@@ -928,7 +739,6 @@
+ */
+ g_assert (metacity_theme_name != NULL);
+
+-#ifdef HAVE_METACITY_3_20_0
+ if (metacity_theme_type == -1)
+ metacity_theme_type = META_THEME_TYPE_METACITY;
+
+@@ -943,25 +753,6 @@
+
+ return FALSE;
+ }
+-#else
+-
+- /* meta_theme_get_current returns the last good theme, so we will try to
+- * load theme manually to know that theme is 100% valid.
+- */
+- theme = meta_theme_load (metacity_theme_name, NULL);
+- if (theme == NULL)
+- return FALSE;
+-
+- /* We can not use this manually loaded theme because Metacity internaly
+- * also use meta_theme_get_current wich in this case will return NULL,
+- * boom - segfault...
+- */
+- meta_theme_free (theme);
+-
+- /* If we are here then we know that this will not fail. */
+- meta_theme_set_current (metacity_theme_name, TRUE);
+- metacity->theme = meta_theme_get_current ();
+-#endif
+
+ return TRUE;
+ }
+@@ -997,11 +788,7 @@
+ {
+ GWDThemeMetacity *metacity = GWD_THEME_METACITY (object);
+
+-#ifdef HAVE_METACITY_3_20_0
+ g_clear_object (&metacity->theme);
+-#else
+- g_clear_pointer (&metacity->style_variants, g_hash_table_destroy);
+-#endif
+
+ if (metacity->button_layout_id != 0) {
+ GWDSettings *settings = gwd_theme_get_settings (GWD_THEME (metacity));
+@@ -1010,10 +797,6 @@
+ metacity->button_layout_id = 0;
+ }
+
+-#ifndef HAVE_METACITY_3_20_0
+- metacity->titlebar_font = NULL;
+-#endif
+-
+ G_OBJECT_CLASS (gwd_theme_metacity_parent_class)->dispose (object);
+ }
+
+@@ -1022,11 +805,7 @@
+ {
+ GWDThemeMetacity *metacity = GWD_THEME_METACITY (theme);
+
+-#ifdef HAVE_METACITY_3_20_0
+ meta_theme_invalidate (metacity->theme);
+-#else
+- g_hash_table_remove_all (metacity->style_variants);
+-#endif
+ }
+
+ static void
+@@ -1034,32 +813,28 @@
+ decor_t *decor)
+ {
+ GWDThemeMetacity *metacity = GWD_THEME_METACITY (theme);
+- GWDSettings *settings = gwd_theme_get_settings (gwd_theme);
++ GWDSettings *settings = gwd_theme_get_settings (theme);
+ GdkDisplay *display = gdk_display_get_default ();
+ Display *xdisplay = gdk_x11_display_get_xdisplay (display);
+ GtkWidget *style_window = gwd_theme_get_style_window (theme);
+-#ifndef HAVE_METACITY_3_20_0
+- MetaStyleInfo *style_info = get_style_info (metacity, decor);
+- GtkStyleContext *context = gtk_widget_get_style_context (style_window);
+-#endif
+ cairo_surface_t *surface;
+ Picture src;
++#ifndef HAVE_METACITY_3_22_0
+ MetaButtonState button_states [META_BUTTON_TYPE_LAST];
++#endif
+ MetaFrameGeometry fgeom;
+ MetaFrameFlags flags;
+ MetaFrameType frame_type;
+ cairo_t *cr;
++#ifndef HAVE_METACITY_3_22_0
+ gint i;
++#endif
+ Region top_region;
+ Region bottom_region;
+ Region left_region;
+ Region right_region;
+ double alpha;
+ gboolean shade_alpha;
+-#ifndef HAVE_METACITY_3_20_0
+- MetaFrameStyle *frame_style;
+- GdkRGBA bg_rgba;
+-#endif
+
+ if (!decor->surface || !decor->picture)
+ return;
+@@ -1088,24 +863,14 @@
+
+ get_decoration_geometry (metacity, decor, &flags, &fgeom, frame_type);
+
+- if (decor->prop_xid || !decor->buffer_surface)
++ if (!decor->frame->has_shadow_extents &&
++ (decor->prop_xid || !decor->buffer_surface)) {
+ draw_shadow_background (decor, cr, decor->shadow, decor->context);
++ }
+
++#ifndef HAVE_METACITY_3_22_0
+ for (i = 0; i < META_BUTTON_TYPE_LAST; ++i)
+ button_states[i] = meta_button_state_for_button_type (metacity, decor, i);
+-
+-#ifndef HAVE_METACITY_3_20_0
+- frame_style = meta_theme_get_frame_style (metacity->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;
+- }
+ #endif
+
+ /* Draw something that will be almost invisible to user. This is hacky way
+@@ -1118,67 +883,59 @@
+ cairo_destroy (cr);
+
+ surface = create_surface (fgeom.width, fgeom.height, style_window);
+-
+ cr = cairo_create (surface);
+
+-#ifndef HAVE_METACITY_3_20_0
+- gdk_cairo_set_source_rgba (cr, &bg_rgba);
+- cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+- cairo_paint (cr);
+-#endif
+-
+ src = XRenderCreatePicture (xdisplay, cairo_xlib_surface_get_drawable (surface),
+ xformat_rgba, 0, NULL);
+
+-#ifdef HAVE_METACITY_3_20_0
++#ifdef HAVE_METACITY_3_22_0
+ meta_theme_draw_frame (metacity->theme, decor->gtk_theme_variant, cr, frame_type, flags,
+ fgeom.width - fgeom.borders.total.left - fgeom.borders.total.right,
+ fgeom.height - fgeom.borders.total.top - fgeom.borders.total.bottom,
+- decor->name, &metacity->button_layout,
+- button_states, decor->icon_pixbuf, NULL);
++ decor->name, update_button_state, decor, decor->icon_pixbuf, NULL);
+ #else
+- meta_theme_draw_frame (metacity->theme, style_info, cr, frame_type, flags,
++ meta_theme_draw_frame (metacity->theme, decor->gtk_theme_variant, cr, frame_type, flags,
+ fgeom.width - fgeom.borders.total.left - fgeom.borders.total.right,
+ fgeom.height - fgeom.borders.total.top - fgeom.borders.total.bottom,
+- decor->layout, decor->frame->text_height, &metacity->button_layout,
++ decor->name, &metacity->button_layout,
+ button_states, decor->icon_pixbuf, NULL);
+ #endif
+
+- if (fgeom.borders.visible.top) {
+- top_region = get_top_border_region (&fgeom, fgeom.width);
++ if (fgeom.borders.visible.top + fgeom.borders.shadow.top) {
++ top_region = get_top_border_region (&fgeom, !decor->frame->has_shadow_extents);
+
+ decor_blend_border_picture (xdisplay, decor->context, src,
+- fgeom.borders.invisible.left,
+- fgeom.borders.invisible.top,
++ fgeom.borders.invisible.left - fgeom.borders.shadow.left,
++ fgeom.borders.invisible.top - fgeom.borders.shadow.top,
+ decor->picture, &decor->border_layout,
+ BORDER_TOP, top_region,
+ alpha * 0xffff, shade_alpha, 0);
+ }
+
+- if (fgeom.borders.visible.bottom) {
+- bottom_region = get_bottom_border_region (&fgeom, fgeom.width);
++ if (fgeom.borders.visible.bottom + fgeom.borders.shadow.bottom) {
++ bottom_region = get_bottom_border_region (&fgeom, !decor->frame->has_shadow_extents);
+
+ decor_blend_border_picture (xdisplay, decor->context, src,
+- fgeom.borders.invisible.left,
++ fgeom.borders.invisible.left - fgeom.borders.shadow.left,
+ fgeom.height - fgeom.borders.total.bottom,
+ decor->picture, &decor->border_layout,
+ BORDER_BOTTOM, bottom_region,
+ alpha * 0xffff, shade_alpha, 0);
+ }
+
+- if (fgeom.borders.visible.left) {
+- left_region = get_left_border_region (&fgeom, fgeom.height);
++ if (fgeom.borders.visible.left + fgeom.borders.shadow.left) {
++ left_region = get_left_border_region (&fgeom);
+
+ decor_blend_border_picture (xdisplay, decor->context, src,
+- fgeom.borders.invisible.left,
++ fgeom.borders.invisible.left - fgeom.borders.shadow.left,
+ fgeom.borders.total.top,
+ decor->picture, &decor->border_layout,
+ BORDER_LEFT, left_region,
+ alpha * 0xffff, shade_alpha, 0);
+ }
+
+- if (fgeom.borders.visible.right) {
+- right_region = get_right_border_region (&fgeom, fgeom.height);
++ if (fgeom.borders.visible.right + fgeom.borders.shadow.right) {
++ right_region = get_right_border_region (&fgeom);
+
+ decor_blend_border_picture (xdisplay, decor->context, src,
+ fgeom.width - fgeom.borders.total.right,
+@@ -1278,40 +1035,39 @@
+ decor_frame_t *frame)
+ {
+ GWDThemeMetacity *metacity = GWD_THEME_METACITY (theme);
+-#ifndef HAVE_METACITY_3_20_0
+- MetaStyleInfo *style_info = get_style_info (metacity, NULL);
+-#endif
++ GWDSettings *settings = gwd_theme_get_settings (theme);
++ gint theme_type = gwd_settings_get_metacity_theme_type (settings);
+ MetaFrameType frame_type = frame_type_from_string (frame->type);
+ MetaFrameBorders borders;
+
+ gwd_decor_frame_ref (frame);
+
+-#ifdef HAVE_METACITY_3_20_0
++ /* Shadow extents is used only with GTK+ theme */
++ frame->has_shadow_extents = theme_type == META_THEME_TYPE_GTK;
++
+ meta_theme_get_frame_borders (metacity->theme, NULL, frame_type,
+ 0, &borders);
+-#else
+- meta_theme_get_frame_borders (metacity->theme, style_info, frame_type,
+- frame->text_height, 0, &borders);
+-#endif
+
+ frame->win_extents.top = borders.visible.top;
+ frame->win_extents.bottom = borders.visible.bottom;
+ frame->win_extents.left = borders.visible.left;
+ frame->win_extents.right = borders.visible.right;
++ frame->shadow_extents.top = borders.shadow.top;
++ frame->shadow_extents.bottom = borders.shadow.bottom;
++ frame->shadow_extents.left = borders.shadow.left;
++ frame->shadow_extents.right = borders.shadow.right;
+
+-#ifdef HAVE_METACITY_3_20_0
+ meta_theme_get_frame_borders (metacity->theme, NULL, frame_type,
+ META_FRAME_MAXIMIZED, &borders);
+-#else
+- meta_theme_get_frame_borders (metacity->theme, style_info, frame_type,
+- frame->text_height, META_FRAME_MAXIMIZED,
+- &borders);
+-#endif
+
+ frame->max_win_extents.top = borders.visible.top;
+ frame->max_win_extents.bottom = borders.visible.bottom;
+ frame->max_win_extents.left = borders.visible.left;
+ frame->max_win_extents.right = borders.visible.right;
++ frame->max_shadow_extents.top = borders.shadow.top;
++ frame->max_shadow_extents.bottom = borders.shadow.bottom;
++ frame->max_shadow_extents.left = borders.shadow.left;
++ frame->max_shadow_extents.right = borders.shadow.right;
+
+ gwd_decor_frame_unref (frame);
+ }
+@@ -1331,12 +1087,30 @@
+ GWDThemeMetacity *metacity = GWD_THEME_METACITY (theme);
+ MetaFrameGeometry fgeom;
+ MetaFrameFlags flags;
++ GtkBorder visible;
++ GtkBorder resize;
++ GtkBorder total;
++ gint top_border;
+
+ get_decoration_geometry (metacity, decor, &flags, &fgeom,
+ frame_type_from_string (decor->frame->type));
+
+- width += fgeom.borders.total.right + fgeom.borders.total.left;
+- height += fgeom.borders.total.top + fgeom.borders.total.bottom;
++ visible = fgeom.borders.visible;
++ resize = fgeom.borders.resize;
++
++ /* We can not use `fgeom->borders.total` border here - it includes also
++ * `shadow` border, but it is not included in frame extents! Create new
++ * `total` border that includes only `visible` border and `resize` border.
++ */
++ total.left = visible.left + resize.left;
++ total.right = visible.right + resize.right;
++ total.top = visible.top + resize.top;
++ total.bottom = visible.bottom + resize.bottom;
++
++ width += total.left + total.right;
++ height += total.top + total.bottom;
++
++ top_border = fgeom.title_rect.y - fgeom.borders.invisible.top;
+
+ #define TOP_RESIZE_HEIGHT 2
+ #define RESIZE_EXTENDS 15
+@@ -1345,51 +1119,51 @@
+ 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;
++ *x = width - total.right - RESIZE_EXTENDS;
++ *y = height - total.bottom - RESIZE_EXTENDS;
+
+- *w = fgeom.borders.total.right + RESIZE_EXTENDS;
+- *h = fgeom.borders.total.bottom + RESIZE_EXTENDS;
++ *w = total.right + RESIZE_EXTENDS;
++ *h = total.bottom + RESIZE_EXTENDS;
+ break;
+ case 1: /* bottom */
+- *x = fgeom.borders.total.left + RESIZE_EXTENDS;
+- *y = height - fgeom.borders.total.bottom;
++ *x = total.left + RESIZE_EXTENDS;
++ *y = height - total.bottom;
+
+- *w = width - fgeom.borders.total.left - fgeom.borders.total.right - (2 * RESIZE_EXTENDS);
+- *h = fgeom.borders.total.bottom;
++ *w = width - total.left - total.right - (2 * RESIZE_EXTENDS);
++ *h = total.bottom;
+ break;
+ case 0: /* bottom left */
+ default:
+ *x = 0;
+- *y = height - fgeom.borders.total.bottom - RESIZE_EXTENDS;
++ *y = height - total.bottom - RESIZE_EXTENDS;
+
+- *w = fgeom.borders.total.left + RESIZE_EXTENDS;
+- *h = fgeom.borders.total.bottom + RESIZE_EXTENDS;
++ *w = total.left + RESIZE_EXTENDS;
++ *h = 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;
++ *x = width - total.right;
++ *y = resize.top + top_border + RESIZE_EXTENDS;
+
+- *w = fgeom.borders.total.right;
+- *h = height - fgeom.borders.total.top - fgeom.borders.total.bottom - (2 * RESIZE_EXTENDS);
++ *w = total.right;
++ *h = height - resize.top - top_border - 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.borders.total.top - fgeom.borders.total.bottom;
++ *x = total.left;
++ *y = resize.top + top_border + TOP_RESIZE_HEIGHT;
++ *w = width - total.left - total.right;
++ *h = visible.top - top_border - TOP_RESIZE_HEIGHT;
+ break;
+ case 0: /* left */
+ default:
+ *x = 0;
+- *y = fgeom.borders.total.top + RESIZE_EXTENDS;
++ *y = resize.top + top_border + RESIZE_EXTENDS;
+
+- *w = fgeom.borders.total.left;
+- *h = height - fgeom.borders.total.top - fgeom.borders.total.bottom - (2 * RESIZE_EXTENDS);
++ *w = total.left;
++ *h = height - resize.top - top_border - total.bottom - (2 * RESIZE_EXTENDS);
+ break;
+ }
+ break;
+@@ -1397,26 +1171,26 @@
+ default:
+ switch (j) {
+ case 2: /* top right */
+- *x = width - fgeom.borders.total.right - RESIZE_EXTENDS;
++ *x = width - total.right - RESIZE_EXTENDS;
+ *y = 0;
+
+- *w = fgeom.borders.total.right + RESIZE_EXTENDS;
+- *h = fgeom.borders.total.top + RESIZE_EXTENDS;
++ *w = total.right + RESIZE_EXTENDS;
++ *h = resize.top + top_border + RESIZE_EXTENDS;
+ break;
+ case 1: /* top */
+- *x = fgeom.borders.total.left + RESIZE_EXTENDS;
++ *x = total.left + RESIZE_EXTENDS;
+ *y = 0;
+
+- *w = width - fgeom.borders.total.left - fgeom.borders.total.right - (2 * RESIZE_EXTENDS);
+- *h = fgeom.borders.total.top - fgeom.title_rect.height;
++ *w = width - total.left - total.right - (2 * RESIZE_EXTENDS);
++ *h = resize.top + top_border + TOP_RESIZE_HEIGHT;
+ break;
+ case 0: /* top left */
+ default:
+ *x = 0;
+ *y = 0;
+
+- *w = fgeom.borders.total.left + RESIZE_EXTENDS;
+- *h = fgeom.borders.total.top + RESIZE_EXTENDS;
++ *w = total.left + RESIZE_EXTENDS;
++ *h = resize.top + top_border + RESIZE_EXTENDS;
+ break;
+ }
+ break;
+@@ -1453,8 +1227,14 @@
+ MetaFrameGeometry fgeom;
+ MetaFrameType frame_type;
+ MetaFrameFlags flags;
++#ifdef HAVE_METACITY_3_22_0
++ MetaButtonType button_type;
++ MetaButton **buttons;
++ gint index;
++#else
+ MetaButtonFunction button_function;
+ MetaButtonSpace *space;
++#endif
+
+ if (!decor->context) {
+ /* undecorated windows implicitly have no buttons */
+@@ -1465,6 +1245,34 @@
+
+ get_decoration_geometry (metacity, decor, &flags, &fgeom, frame_type);
+
++#ifdef HAVE_METACITY_3_22_0
++ button_type = button_to_meta_button_type (i);
++ buttons = meta_theme_get_buttons (metacity->theme);
++
++ for (index = 0; buttons[index]; index++) {
++ if (meta_button_get_type (buttons[index]) == button_type) {
++ GdkRectangle rect;
++
++ meta_button_get_event_rect (buttons[index], &rect);
++
++ if (rect.width != 0 && rect.height != 0) {
++ *x = rect.x;
++ *y = rect.y;
++ *w = rect.width;
++ *h = rect.height;
++
++ *x = *x - fgeom.borders.invisible.left + fgeom.borders.resize.left;
++ *y = *y - fgeom.borders.invisible.top + fgeom.borders.resize.top;
++
++ g_free (buttons);
++ return TRUE;
++ }
++ }
++ }
++
++ g_free (buttons);
++ return FALSE;
++#else
+ button_function = button_to_meta_button_function (i);
+ if (!button_present (metacity, button_function))
+ return FALSE;
+@@ -1512,7 +1320,11 @@
+ *w = space->clickable.width;
+ *h = space->clickable.height;
+
++ *x = *x - fgeom.borders.invisible.left + fgeom.borders.resize.left;
++ *y = *y - fgeom.borders.invisible.top + fgeom.borders.resize.top;
++
+ return TRUE;
++#endif
+ }
+
+ static void
+@@ -1521,32 +1333,7 @@
+ {
+ GWDThemeMetacity *metacity = GWD_THEME_METACITY (theme);
+
+-#ifdef HAVE_METACITY_3_20_0
+ meta_theme_set_titlebar_font (metacity->theme, titlebar_font);
+-#else
+- metacity->titlebar_font = titlebar_font;
+-#endif
+-}
+-
+-static PangoFontDescription *
+-gwd_theme_metacity_get_titlebar_font (GWDTheme *theme,
+- decor_frame_t *frame)
+-{
+-#ifdef HAVE_METACITY_3_20_0
+- return NULL;
+-#else
+- GWDThemeMetacity *metacity = GWD_THEME_METACITY (theme);
+- MetaStyleInfo *style_info = get_style_info (metacity, NULL);
+- PangoFontDescription *font_desc = meta_style_info_create_font_desc (style_info);
+- MetaFrameType type = frame_type_from_string (frame->type);
+- MetaFrameFlags flags = 0xc33; /* FIXME */
+- MetaFrameStyle *style = meta_theme_get_frame_style (metacity->theme, type, flags);
+-
+- pango_font_description_merge (font_desc, metacity->titlebar_font, TRUE);
+- meta_frame_style_apply_scale (style, font_desc);
+-
+- return font_desc;
+-#endif
+ }
+
+ static void
+@@ -1565,16 +1352,11 @@
+ theme_class->get_event_window_position = gwd_theme_metacity_get_event_window_position;
+ theme_class->get_button_position = gwd_theme_metacity_get_button_position;
+ theme_class->update_titlebar_font = gwd_theme_metacity_update_titlebar_font;
+- theme_class->get_titlebar_font = gwd_theme_metacity_get_titlebar_font;
+ }
+
+ static void
+ gwd_theme_metacity_init (GWDThemeMetacity *metacity)
+ {
+-#ifndef HAVE_METACITY_3_20_0
+- metacity->style_variants = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
+- (GDestroyNotify) meta_style_info_unref);
+-#endif
+ }
+
+ /**