From a21bef8bce9216975c60d34b21e3e381f5ef4bb7 Mon Sep 17 00:00:00 2001 From: Michael Webster Date: Sat, 18 May 2013 21:36:51 -0400 Subject: [PATCH 1/4] Some upstream fixes --- src/compositor/meta-window-actor.c | 51 ++++++++++++++++-------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index de8d292cc..b9bdc2b55 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -1194,31 +1194,36 @@ meta_window_actor_should_unredirect (MetaWindowActor *self) MetaWindow *metaWindow = meta_window_actor_get_meta_window (self); MetaScreen *screen = meta_window_get_screen (metaWindow); MetaWindowActorPrivate *priv = self->priv; + int screen_width, screen_height; + MetaRectangle window_rect, monitor_rect; + int num_monitors = meta_screen_get_n_monitors (screen); + int i; - if (meta_window_is_override_redirect (metaWindow) && priv->opacity == 0xff && !priv->argb32) - { - int screen_width, screen_height; - MetaRectangle window_rect; - meta_screen_get_size (screen, &screen_width, &screen_height); - meta_window_get_outer_rect (metaWindow, &window_rect); - - if (window_rect.x == 0 && window_rect.y == 0 && - window_rect.width == screen_width && window_rect.height == screen_height) - return TRUE; - else - { - int num_monitors = meta_screen_get_n_monitors (screen); - int i; - MetaRectangle monitor_rect; + if (!meta_window_is_override_redirect (metaWindow)) + return FALSE; - for (i = 0; i < num_monitors; i++) - { - meta_screen_get_monitor_geometry (screen , i, &monitor_rect); - if (monitor_rect.x == window_rect.x && monitor_rect.y == window_rect.y && - monitor_rect.width == window_rect.width && monitor_rect.height == window_rect.height) - return TRUE; - } - } + if (priv->opacity != 0xff) + return FALSE; + + if (priv->argb32) + return FALSE; + + if (metaWindow->has_shape) + return FALSE; + + meta_screen_get_size (screen, &screen_width, &screen_height); + meta_window_get_outer_rect (metaWindow, &window_rect); + + if (window_rect.x == 0 && window_rect.y == 0 && + window_rect.width == screen_width && window_rect.height == screen_height) + return TRUE; + + for (i = 0; i < num_monitors; i++) + { + meta_screen_get_monitor_geometry (screen , i, &monitor_rect); + if (monitor_rect.x == window_rect.x && monitor_rect.y == window_rect.y && + monitor_rect.width == window_rect.width && monitor_rect.height == window_rect.height) + return TRUE; } return FALSE; From fd85c9a2ac2b11c4e816df4aa7db9ac3644c1f7c Mon Sep 17 00:00:00 2001 From: Michael Webster Date: Sat, 18 May 2013 21:51:26 -0400 Subject: [PATCH 2/4] Support _NET_WM_BYPASS_COMPOSITOR and _NET_WM_DONT_BYPASS_COMPOSITOR --- src/compositor/meta-window-actor.c | 12 +++++-- src/core/window-private.h | 4 +++ src/core/window-props.c | 54 ++++++++++++++++++++++++++++++ src/core/window.c | 22 ++++++++++++ src/meta/atomnames.h | 2 ++ src/meta/window.h | 4 +++ 6 files changed, 96 insertions(+), 2 deletions(-) diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index b9bdc2b55..0d54f44ae 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -1199,18 +1199,26 @@ meta_window_actor_should_unredirect (MetaWindowActor *self) int num_monitors = meta_screen_get_n_monitors (screen); int i; - if (!meta_window_is_override_redirect (metaWindow)) + if (meta_window_requested_dont_bypass_compositor (metaWindow)) + return FALSE; + + if (!meta_window_is_override_redirect (metaWindow) && + !meta_window_requested_bypass_compositor (metaWindow)) return FALSE; if (priv->opacity != 0xff) return FALSE; - if (priv->argb32) + if (priv->argb32 && !meta_window_requested_bypass_compositor (metaWindow)) return FALSE; if (metaWindow->has_shape) return FALSE; + if (meta_window_requested_bypass_compositor (metaWindow) && + meta_window_is_fullscreen (metaWindow)) + return TRUE; + meta_screen_get_size (screen, &screen_width, &screen_height); meta_window_get_outer_rect (metaWindow, &window_rect); diff --git a/src/core/window-private.h b/src/core/window-private.h index b9be92437..52fd8a502 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -413,6 +413,10 @@ struct _MetaWindow /* The currently complementary tiled window, if any */ MetaWindow *tile_match; + + /* Bypass compositor hints */ + guint bypass_compositor : 1; + guint dont_bypass_compositor : 1; }; struct _MetaWindowClass diff --git a/src/core/window-props.c b/src/core/window-props.c index 3a8ad0fa9..92037d8f1 100644 --- a/src/core/window-props.c +++ b/src/core/window-props.c @@ -1620,6 +1620,58 @@ reload_gtk_hide_titlebar_when_maximized (MetaWindow *window, } } +static void +reload_bypass_compositor (MetaWindow *window, + MetaPropValue *value, + gboolean initial) +{ + gboolean requested_value = FALSE; + gboolean current_value = window->bypass_compositor; + + if (value->type != META_PROP_VALUE_INVALID) + { + requested_value = ((int) value->v.cardinal == 1); + meta_verbose ("Request to bypass compositor for window %s.\n", window->desc); + } + + if (requested_value == current_value) + return; + + if (requested_value && window->dont_bypass_compositor) + { + meta_verbose ("Setting bypass and dont compositor for same window (%s) makes no sense, ignoring.\n", window->desc); + return; + } + + window->bypass_compositor = requested_value; +} + +static void +reload_dont_bypass_compositor (MetaWindow *window, + MetaPropValue *value, + gboolean initial) +{ + gboolean requested_value = FALSE; + gboolean current_value = window->dont_bypass_compositor; + + if (value->type != META_PROP_VALUE_INVALID) + { + requested_value = ((int) value->v.cardinal == 1); + meta_verbose ("Request to don't bypass compositor for window %s.\n", window->desc); + } + + if (requested_value == current_value) + return; + + if (requested_value && window->bypass_compositor) + { + meta_verbose ("Setting bypass and dont compositor for same window (%s) makes no sense, ignoring.\n", window->desc); + return; + } + + window->dont_bypass_compositor = requested_value; +} + #define RELOAD_STRING(var_name, propname) \ static void \ reload_ ## var_name (MetaWindow *window, \ @@ -1716,6 +1768,8 @@ meta_display_init_window_prop_hooks (MetaDisplay *display) { display->atom__NET_WM_WINDOW_TYPE, META_PROP_VALUE_INVALID, reload_net_wm_window_type, FALSE, TRUE }, { display->atom__NET_WM_STRUT, META_PROP_VALUE_INVALID, reload_struts, FALSE, FALSE }, { display->atom__NET_WM_STRUT_PARTIAL, META_PROP_VALUE_INVALID, reload_struts, FALSE, FALSE }, + { display->atom__NET_WM_BYPASS_COMPOSITOR, META_PROP_VALUE_CARDINAL, reload_bypass_compositor, FALSE, FALSE }, + { display->atom__NET_WM_DONT_BYPASS_COMPOSITOR, META_PROP_VALUE_CARDINAL, reload_dont_bypass_compositor, FALSE, FALSE }, { 0 }, }; diff --git a/src/core/window.c b/src/core/window.c index 90162b6a1..35c9c682f 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -3632,6 +3632,28 @@ meta_window_is_on_primary_monitor (MetaWindow *window) return window->monitor->is_primary; } +/** + * meta_window_requested_bypass_compositor: + * + * Return value: %TRUE if the window requested to bypass the compositor + */ +gboolean +meta_window_requested_bypass_compositor (MetaWindow *window) +{ + return window->bypass_compositor; +} + +/** + * meta_window_requested_dont_bypass_compositor: + * + * Return value: %TRUE if the window requested to opt out of unredirecting + */ +gboolean +meta_window_requested_dont_bypass_compositor (MetaWindow *window) +{ + return window->dont_bypass_compositor; +} + LOCAL_SYMBOL void meta_window_tile (MetaWindow *window) { diff --git a/src/meta/atomnames.h b/src/meta/atomnames.h index df1e28ce2..81aa65e37 100644 --- a/src/meta/atomnames.h +++ b/src/meta/atomnames.h @@ -172,6 +172,8 @@ item(_NET_WM_ACTION_BELOW) item(_NET_WM_STATE_STICKY) item(_NET_WM_FULLSCREEN_MONITORS) item(_NET_WM_STATE_FOCUSED) +item(_NET_WM_BYPASS_COMPOSITOR) +item(_NET_WM_DONT_BYPASS_COMPOSITOR) #if 0 /* We apparently never use: */ diff --git a/src/meta/window.h b/src/meta/window.h index 1d3cb5bae..1f8e9e099 100644 --- a/src/meta/window.h +++ b/src/meta/window.h @@ -145,6 +145,10 @@ gboolean meta_window_is_on_primary_monitor (MetaWindow *window); gboolean meta_window_is_demanding_attention (MetaWindow *window); gboolean meta_window_is_urgent (MetaWindow *window); + +gboolean meta_window_requested_bypass_compositor (MetaWindow *window); +gboolean meta_window_requested_dont_bypass_compositor (MetaWindow *window); + gboolean meta_window_is_mapped (MetaWindow *window); gboolean meta_window_toplevel_is_mapped (MetaWindow *window); gboolean meta_window_get_icon_geometry (MetaWindow *window, From c01ccdb0000b378ddb2fc7fac65976aa19767aaf Mon Sep 17 00:00:00 2001 From: Michael Webster Date: Sat, 18 May 2013 21:56:03 -0400 Subject: [PATCH 3/4] Improve unredirect heuristic See: https://git.gnome.org/browse/mutter/commit/?id=90f2a3ae4ca205f7cbbc2daeba2ab7cfa5ed1613 --- src/compositor/meta-window-actor.c | 81 +++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 24 deletions(-) diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index 0d54f44ae..8da336ba6 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -116,6 +116,10 @@ struct _MetaWindowActorPrivate guint no_more_x_calls : 1; guint unredirected : 1; + + /* This is used to detect fullscreen windows that need to be unredirected */ + guint full_damage_frames_count; + guint does_full_damage : 1; }; enum @@ -1192,47 +1196,58 @@ LOCAL_SYMBOL gboolean meta_window_actor_should_unredirect (MetaWindowActor *self) { MetaWindow *metaWindow = meta_window_actor_get_meta_window (self); - MetaScreen *screen = meta_window_get_screen (metaWindow); MetaWindowActorPrivate *priv = self->priv; - int screen_width, screen_height; - MetaRectangle window_rect, monitor_rect; - int num_monitors = meta_screen_get_n_monitors (screen); - int i; + + gboolean occupies_full_monitors = FALSE; if (meta_window_requested_dont_bypass_compositor (metaWindow)) return FALSE; - if (!meta_window_is_override_redirect (metaWindow) && - !meta_window_requested_bypass_compositor (metaWindow)) + if (priv->opacity != 0xff) return FALSE; - if (priv->opacity != 0xff) + if (metaWindow->has_shape) return FALSE; if (priv->argb32 && !meta_window_requested_bypass_compositor (metaWindow)) return FALSE; - if (metaWindow->has_shape) + if (meta_window_is_fullscreen (metaWindow)) + occupies_full_monitors = TRUE; + else if (meta_window_is_override_redirect (metaWindow)) + { + MetaScreen *screen = meta_window_get_screen (metaWindow); + MetaRectangle window_rect, monitor_rect; + + int num_monitors = meta_screen_get_n_monitors (screen); + int screen_width, screen_height, i; + + meta_screen_get_size (screen, &screen_width, &screen_height); + + if (window_rect.x == 0 && window_rect.y == 0 && + window_rect.width == screen_width && window_rect.height == screen_height) + occupies_full_monitors = TRUE; + + for (i = 0; i < num_monitors; i++) + { + meta_screen_get_monitor_geometry (screen , i, &monitor_rect); + if (monitor_rect.x == window_rect.x && monitor_rect.y == window_rect.y && + monitor_rect.width == window_rect.width && monitor_rect.height == window_rect.height) + occupies_full_monitors = TRUE; + } + } + + if (!occupies_full_monitors) return FALSE; - if (meta_window_requested_bypass_compositor (metaWindow) && - meta_window_is_fullscreen (metaWindow)) + if (meta_window_requested_bypass_compositor (metaWindow)) return TRUE; - meta_screen_get_size (screen, &screen_width, &screen_height); - meta_window_get_outer_rect (metaWindow, &window_rect); - - if (window_rect.x == 0 && window_rect.y == 0 && - window_rect.width == screen_width && window_rect.height == screen_height) + if (meta_window_is_override_redirect (metaWindow)) return TRUE; - for (i = 0; i < num_monitors; i++) - { - meta_screen_get_monitor_geometry (screen , i, &monitor_rect); - if (monitor_rect.x == window_rect.x && monitor_rect.y == window_rect.y && - monitor_rect.width == window_rect.width && monitor_rect.height == window_rect.height) - return TRUE; - } + if (priv->does_full_damage) + return TRUE; return FALSE; } @@ -1994,11 +2009,29 @@ meta_window_actor_process_damage (MetaWindowActor *self, XDamageNotifyEvent *event) { MetaWindowActorPrivate *priv = self->priv; + MetaCompScreen *info = meta_screen_get_compositor_data (priv->screen); priv->received_damage = TRUE; + if (meta_window_is_fullscreen (priv->window) && g_list_last (info->windows)->data == self && !priv->unredirected) + { + MetaRectangle window_rect; + meta_window_get_outer_rect (priv->window, &window_rect); + + if (window_rect.x == event->area.x && + window_rect.y == event->area.y && + window_rect.width == event->area.width && + window_rect.height == event->area.height) + priv->full_damage_frames_count++; + else + priv->full_damage_frames_count = 0; + + if (priv->full_damage_frames_count >= 100) + priv->does_full_damage = TRUE; + } + /* Drop damage event for unredirected windows */ - if (self->priv->unredirected) + if (priv->unredirected) return; if (is_frozen (self)) From aae8654c8165e24346c24d53847ce273edaefadf Mon Sep 17 00:00:00 2001 From: Michael Webster Date: Sat, 18 May 2013 22:15:48 -0400 Subject: [PATCH 4/4] Fix uninitialized variable --- src/compositor/meta-window-actor.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index 8da336ba6..50caa33fe 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -1223,6 +1223,7 @@ meta_window_actor_should_unredirect (MetaWindowActor *self) int screen_width, screen_height, i; meta_screen_get_size (screen, &screen_width, &screen_height); + meta_window_get_outer_rect (priv->window, &window_rect); if (window_rect.x == 0 && window_rect.y == 0 && window_rect.width == screen_width && window_rect.height == screen_height)