[mutter/wip/wayland-work: 11/13] wayland: implement transient dialogs for wayland clients
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/wayland-work: 11/13] wayland: implement transient dialogs for wayland clients
- Date: Tue, 3 Sep 2013 15:02:50 +0000 (UTC)
commit 92016c06cdadc0a45581c83dd9231174ab19df24
Author: Giovanni Campagna <gcampagn redhat com>
Date: Tue Sep 3 12:00:29 2013 +0200
wayland: implement transient dialogs for wayland clients
We still don't have attached modal dialogs, because we don't
have window hints, but at least the stacking is correct now.
configure.ac | 2 +-
src/core/window-private.h | 4 ++
src/core/window-props.c | 47 ++---------------
src/core/window.c | 99 ++++++++++++++++++++++++++----------
src/wayland/meta-wayland-surface.c | 43 ++++++++--------
5 files changed, 104 insertions(+), 91 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index efd8fb8..432f74c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@ AC_PREREQ(2.50)
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [9])
-m4_define([mutter_micro_version], [90])
+m4_define([mutter_micro_version], [91])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 3ca2b0a..b0cec17 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -127,6 +127,7 @@ struct _MetaWindow
Window xtransient_for;
Window xgroup_leader;
Window xclient_leader;
+ MetaWindow *transient_for;
/* Initial workspace property */
int initial_workspace;
@@ -716,4 +717,7 @@ void meta_window_set_gtk_dbus_properties (MetaWindow *window,
const char *application_object_path,
const char *window_object_path);
+void meta_window_set_transient_for (MetaWindow *window,
+ MetaWindow *parent);
+
#endif
diff --git a/src/core/window-props.c b/src/core/window-props.c
index 73452cc..1ac5239 100644
--- a/src/core/window-props.c
+++ b/src/core/window-props.c
@@ -1554,9 +1554,6 @@ reload_transient_for (MetaWindow *window,
if (transient_for == window->xtransient_for)
return;
- if (meta_window_appears_focused (window) && window->xtransient_for != None)
- meta_window_propagate_focus_appearance (window, FALSE);
-
old_transient_for = window->xtransient_for;
window->xtransient_for = transient_for;
@@ -1569,46 +1566,14 @@ reload_transient_for (MetaWindow *window,
else
meta_verbose ("Window %s is not transient\n", window->desc);
- /* may now be a dialog */
- meta_window_recalc_window_type (window);
-
- if (!window->constructing)
+ if (window->transient_parent_is_root_window || window->xtransient_for == None)
+ meta_window_set_transient_for (window, NULL);
+ else
{
- /* If the window attaches, detaches, or changes attached
- * parents, we need to destroy the MetaWindow and let a new one
- * be created (which happens as a side effect of
- * meta_window_unmanage()). The condition below is correct
- * because we know window->xtransient_for has changed.
- */
- if (window->attached || meta_window_should_attach_to_parent (window))
- {
- guint32 timestamp;
-
- window->xtransient_for = old_transient_for;
- timestamp = meta_display_get_current_time_roundtrip (window->display);
- meta_window_unmanage (window, timestamp);
- return;
- }
+ parent = meta_display_lookup_x_window (window->display,
+ window->xtransient_for);
+ meta_window_set_transient_for (window, parent);
}
-
- /* update stacking constraints */
- if (!window->override_redirect)
- meta_stack_update_transient (window->screen->stack, window);
-
- /* possibly change its group. We treat being a window's transient as
- * equivalent to making it your group leader, to work around shortcomings
- * in programs such as xmms-- see #328211.
- */
- if (window->xtransient_for != None &&
- window->xgroup_leader != None &&
- window->xtransient_for != window->xgroup_leader)
- meta_window_group_leader_changed (window);
-
- if (!window->constructing && !window->override_redirect)
- meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
-
- if (meta_window_appears_focused (window) && window->xtransient_for != None)
- meta_window_propagate_focus_appearance (window, TRUE);
}
static void
diff --git a/src/core/window.c b/src/core/window.c
index 199799d..2f5fa2d 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -239,6 +239,9 @@ meta_window_finalize (GObject *object)
if (window->opaque_region)
cairo_region_destroy (window->opaque_region);
+ if (window->transient_for)
+ g_object_unref (window->transient_for);
+
meta_icon_cache_free (&window->icon_cache);
g_free (window->sm_client_id);
@@ -1114,11 +1117,6 @@ meta_window_new_shared (MetaDisplay *display,
* can use this time as a fallback.
*/
if (!window->override_redirect && !window->net_wm_user_time_set) {
- MetaWindow *parent = NULL;
- if (window->xtransient_for)
- parent = meta_display_lookup_x_window (window->display,
- window->xtransient_for);
-
/* First, maybe the app was launched with startup notification using an
* obsolete version of the spec; use that timestamp if it exists.
*/
@@ -1127,8 +1125,8 @@ meta_window_new_shared (MetaDisplay *display,
* being recorded as a fallback for potential transients
*/
window->net_wm_user_time = window->initial_timestamp;
- else if (parent != NULL)
- meta_window_set_user_time(window, parent->net_wm_user_time);
+ else if (window->transient_for != NULL)
+ meta_window_set_user_time(window, window->transient_for->net_wm_user_time);
else
/* NOTE: Do NOT toggle net_wm_user_time_set to true; this is just
* being recorded as a fallback for potential transients
@@ -1218,21 +1216,16 @@ meta_window_new_shared (MetaDisplay *display,
if (!window->override_redirect)
{
if (window->workspace == NULL &&
- window->xtransient_for != None)
+ window->transient_for != NULL)
{
/* Try putting dialog on parent's workspace */
- MetaWindow *parent;
-
- parent = meta_display_lookup_x_window (window->display,
- window->xtransient_for);
-
- if (parent && parent->workspace)
+ if (window->transient_for->workspace)
{
meta_topic (META_DEBUG_PLACEMENT,
"Putting window %s on same workspace as parent %s\n",
- window->desc, parent->desc);
+ window->desc, window->transient_for->desc);
- if (parent->on_all_workspaces_requested)
+ if (window->transient_for->on_all_workspaces_requested)
{
window->on_all_workspaces_requested = TRUE;
window->on_all_workspaces = TRUE;
@@ -1240,7 +1233,7 @@ meta_window_new_shared (MetaDisplay *display,
/* this will implicitly add to the appropriate MRU lists
*/
- meta_workspace_add_window (parent->workspace, window);
+ meta_workspace_add_window (window->transient_for->workspace, window);
}
}
@@ -4456,14 +4449,14 @@ window_activate (MetaWindow *window,
/* For non-transient windows, we just set up a pulsing indicator,
rather than move windows or workspaces.
See http://bugzilla.gnome.org/show_bug.cgi?id=482354 */
- if (window->xtransient_for == None &&
+ if (window->transient_for == NULL &&
!meta_window_located_on_workspace (window, workspace))
{
meta_window_set_demands_attention (window);
/* We've marked it as demanding, don't need to do anything else. */
return;
}
- else if (window->xtransient_for != None)
+ else if (window->transient_for != NULL)
{
/* Move transients to current workspace - preference dialogs should appear over
the source window. */
@@ -5995,7 +5988,7 @@ get_modal_transient (MetaWindow *window)
{
MetaWindow *transient = tmp->data;
- if (transient->xtransient_for == modal_transient->xwindow &&
+ if (transient->transient_for == modal_transient &&
transient->wm_state_modal)
{
modal_transient = transient;
@@ -8365,7 +8358,7 @@ recalc_window_type (MetaWindow *window)
XFree (atom_name);
}
}
- else if (window->xtransient_for != None)
+ else if (window->transient_for != NULL)
{
window->type = META_WINDOW_DIALOG;
}
@@ -8708,8 +8701,7 @@ recalc_window_features (MetaWindow *window)
case META_WINDOW_MODAL_DIALOG:
/* only skip taskbar if we have a real transient parent
(and ignore the application hints) */
- if (window->xtransient_for != None &&
- window->xtransient_for != window->screen->xroot)
+ if (window->transient_for != NULL)
window->skip_taskbar = TRUE;
else
window->skip_taskbar = FALSE;
@@ -10313,11 +10305,10 @@ meta_window_foreach_ancestor (MetaWindow *window,
w = window;
do
{
- if (w->xtransient_for == None ||
- w->transient_parent_is_root_window)
+ if (w->transient_for == NULL)
break;
- w = meta_display_lookup_x_window (w->display, w->xtransient_for);
+ w = w->transient_for;
}
while (w && (* func) (w, user_data));
}
@@ -11140,7 +11131,9 @@ meta_window_get_transient_for (MetaWindow *window)
{
g_return_val_if_fail (META_IS_WINDOW (window), NULL);
- if (window->xtransient_for)
+ if (window->transient_for)
+ return window->transient_for;
+ else if (window->xtransient_for)
return meta_display_lookup_x_window (window->display,
window->xtransient_for);
else
@@ -11545,3 +11538,55 @@ meta_window_set_gtk_dbus_properties (MetaWindow *window,
g_object_thaw_notify (G_OBJECT (window));
}
+
+void
+meta_window_set_transient_for (MetaWindow *window,
+ MetaWindow *parent)
+{
+ if (meta_window_appears_focused (window) && window->transient_for != None)
+ meta_window_propagate_focus_appearance (window, FALSE);
+
+ /* may now be a dialog */
+ meta_window_recalc_window_type (window);
+
+ if (!window->constructing)
+ {
+ /* If the window attaches, detaches, or changes attached
+ * parents, we need to destroy the MetaWindow and let a new one
+ * be created (which happens as a side effect of
+ * meta_window_unmanage()). The condition below is correct
+ * because we know window->transient_for has changed.
+ */
+ if (window->attached || meta_window_should_attach_to_parent (window))
+ {
+ guint32 timestamp;
+
+ timestamp = meta_display_get_current_time_roundtrip (window->display);
+ meta_window_unmanage (window, timestamp);
+ return;
+ }
+ }
+
+ /* update stacking constraints */
+ if (!window->override_redirect)
+ meta_stack_update_transient (window->screen->stack, window);
+
+ /* We know this won't create a reference cycle because we check for loops */
+ g_clear_object (&window->transient_for);
+ window->transient_for = parent ? g_object_ref (parent) : NULL;
+
+ /* possibly change its group. We treat being a window's transient as
+ * equivalent to making it your group leader, to work around shortcomings
+ * in programs such as xmms-- see #328211.
+ */
+ if (window->xtransient_for != None &&
+ window->xgroup_leader != None &&
+ window->xtransient_for != window->xgroup_leader)
+ meta_window_group_leader_changed (window);
+
+ if (!window->constructing && !window->override_redirect)
+ meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
+
+ if (meta_window_appears_focused (window) && window->transient_for != None)
+ meta_window_propagate_focus_appearance (window, TRUE);
+}
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index 1ce77f7..bc5fc85 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -632,32 +632,30 @@ shell_surface_resize (struct wl_client *client,
g_warning ("TODO: support shell_surface_resize request");
}
-static void
+static gboolean
ensure_surface_window (MetaWaylandSurface *surface)
{
MetaDisplay *display = meta_get_display ();
+ int width, height;
- if (!surface->window)
- {
- int width, height;
+ if (surface->window)
+ return FALSE;
- if (surface->buffer_ref.buffer)
- {
- MetaWaylandBuffer *buffer = surface->buffer_ref.buffer;
- width = buffer->width;
- height = buffer->width;
- }
- else
- {
- width = 0;
- height = 0;
- }
+ if (surface->buffer_ref.buffer)
+ {
+ MetaWaylandBuffer *buffer = surface->buffer_ref.buffer;
+ width = buffer->width;
+ height = buffer->width;
+ }
+ else
+ {
+ width = 0;
+ height = 0;
+ }
- surface->window =
- meta_window_new_for_wayland (display, width, height, surface);
+ surface->window = meta_window_new_for_wayland (display, width, height, surface);
- meta_window_calc_showing (surface->window);
- }
+ return TRUE;
}
static void
@@ -672,9 +670,8 @@ shell_surface_set_toplevel (struct wl_client *client,
if (client == compositor->xwayland_client)
return;
- ensure_surface_window (surface);
-
- meta_window_unmake_fullscreen (surface->window);
+ if (!ensure_surface_window (surface))
+ meta_window_unmake_fullscreen (surface->window);
}
static void
@@ -687,6 +684,7 @@ shell_surface_set_transient (struct wl_client *client,
{
MetaWaylandSurfaceExtension *shell_surface = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = shell_surface->surface;
+ MetaWaylandSurface *parent_surface = wl_resource_get_user_data (parent);
MetaWaylandCompositor *compositor = surface->compositor;
/* NB: Surfaces from xwayland become managed based on X events. */
@@ -694,6 +692,7 @@ shell_surface_set_transient (struct wl_client *client,
return;
ensure_surface_window (surface);
+ meta_window_set_transient_for (surface->window, parent_surface->window);
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]