Compare commits

...

33 Commits

Author SHA1 Message Date
Carlos Garnacho
8aeec308fb xwayland: Allow setting up maintenance processes
This is made a signal, so the upper layers (read: gnome-shell) may
decide what to spawn, whether to add a GSetting, and whatnot. The
only signal argument contains the appropriate display to use for
this kind of setup.
2019-08-01 18:11:14 +02:00
Carlos Garnacho
252fd771b1 wayland: Set up initialization X11 socket
This is used by GDK and the X11 bits, but may also be used for
other initialization services we might need to run along with
Xwayland initialization.
2019-08-01 18:11:14 +02:00
Carlos Garnacho
41bff1e997 wayland: Implement on-demand start of Xwayland
The Xwayland manager now has 4 distinct phases:
- Init and shutdown (Happening together with the compositor itself)
- Start and stop

In these last 2 phases, handle orderly initialization and shutdown
of Xwayland. On initialization We will simply find out what is a
proper display name, and set up the envvar and socket so that clients
think there is a X server.

Whenever we detect data on this socket, we enter the start phase
that will launch Xwayland, and plunge the socket directly to it.
In this phase we now also set up the MetaX11Display.

The stop phase is pretty much the opposite, we will shutdown the
MetaX11Display and all related data, terminate the Xwayland
process, and restore the listening sockets. This phase happens
on a timeout whenever the last known X11 MetaWindow is gone. If no
new X clients come back in this timeout, the X server will be
eventually terminated.

The shutdown phase happens on compositor shutdown and is completely
uninteresting. Some bits there moved into the stop phase as might
happen over and over.

This is all controlled by META_DISPLAY_POLICY_ON_DEMAND and
the "autostart-xwayland" experimental setting.
2019-08-01 18:11:14 +02:00
Carlos Garnacho
323742e736 core: Avoid queueing a stack operation on the frame when the X11 is closing
When rushing to unmanage X11 windows after the X11 connection is closed/ing,
this would succeed at creating a stack operation for no longer known windows.
Simply avoid to queue a stack operation if we know it's meaningless.
2019-08-01 18:11:14 +02:00
Carlos Garnacho
14f41f3130 x11: Add "closing" flag to MetaX11Display
So code not directly in dispose() can know to avoid certain things
when the X11 display is about to close.
2019-08-01 18:11:14 +02:00
Carlos Garnacho
21b4cf8a50 x11: Shuffle x11-stack destruction in MetaX11Display dispose
Unmanaging the windows may trigger stack operations that we later try
to synchronize despite being in dispose() stage. This may trigger
MetaStackTracker warnings when trying to apply those operations.

Switching destruction order (First dispose the X11 stack representation,
then unmanage windows) won't trigger further stack changes on X11 windows
after having signaled MetaDisplay::x11-display-closing.
2019-08-01 18:11:14 +02:00
Carlos Garnacho
a4f47820c3 wayland: Add setting/api to check the policy to set up the X11 display
This replaces meta_should_autostart_x11_display(). The "on-demand" policy
is not honored yet.
2019-08-01 18:11:14 +02:00
Carlos Garnacho
471eca3745 wayland: Refactor code setting up the display socket
So it may be reused when we need to open those again.
2019-08-01 18:11:14 +02:00
Carlos Garnacho
c1f39514ca wayland: Add tracking of X11 windows
This is unused ATM, but will be used to check whether it is safe to
shut Xwayland down.
2019-08-01 18:11:14 +02:00
Carlos Garnacho
038720fecc compositor: Add explicit API call to redirect X11 windows
This is not useful yet, but will be when Xwayland may restart
2019-08-01 18:11:14 +02:00
Carlos Garnacho
d367d97364 wayland: Disconnect signal when the display closes
It would be potentially left dangling if the display were closed, and
reconnected again when restarting the server.
2019-08-01 18:11:14 +02:00
Carlos Garnacho
885f89a217 wayland: Rename xwayland init/shutdown functions
The start/stop verbs will be reused later when we can start and
stop the X server. Rename these functions to init/shutdown, and
init_xserver() to start_xserver().
2019-08-01 18:11:14 +02:00
Carlos Garnacho
21411faeb1 core: Manage only X11 windows when (re)starting
What "restart" means is somewhat different between x11 and wayland
sessions. A X11 compositor may restart itself, thus having to manage
again all the client windows that were running. A wayland compositor
cannot restart itself, but might restart X11, in which case there's
possibly a number of wayland clients, plus some x11 app that is
being started.

For the latter case, the assert will break, so just make it
conditional. Also rename the function so it's more clear that it
only affects X11 windows.
2019-08-01 18:11:14 +02:00
Carlos Garnacho
cf4a9b3f6a x11: Do not queue stack operation for guard window
In the case mutter is a x11 compositor, it doesn't matter much
since the stack tracker will go away soon. In the case this is a
wayland compositor with mandatory Xwayland, it matters even less
since the session would be shutting down in those paths.

But if this a wayland compositor that can start Xwayland on demand,
this is even harmful, as the MetaStackTracker should be cleared of
x11 windows at this moment, and we actually did right before dispose
on ::x11-display-closing.
2019-08-01 18:11:14 +02:00
Carlos Garnacho
1226c599c9 core: Prepare MetaStackTracker for X11 display being closed
If the display is closed prematurely, go through all windows that
look X11-y and remove them for future calculations. This is not
strictly needed as Xwayland should shut down orderly (thus no client
windows be there), but doesn't hurt to prepare in advance for the
cases where it might not be the case.
2019-08-01 18:11:14 +02:00
Carlos Garnacho
c9459fa096 x11: Add meta_x11_get_display_name() function
Instead of poking the DISPLAY envvar at places.
2019-08-01 18:11:14 +02:00
Carlos Garnacho
d31fb640d5 core: Ensure passive key grabs are only set up on X11
We don't strictly need it for wayland compositors, yet there are
paths where we try to trigger those passive grabs there. Just
skip those on the high level code (where "is it x11" decisions
are taken) like we do with passive button grabs.
2019-08-01 18:11:14 +02:00
Niels De Graef
5b98cc7a3a cursor-tracker: Document cursor-moved signal
It's a bit easier to track what's going on in a signal if you document
it (otherwise you have to check where it was emitted in the code).

https://gitlab.gnome.org/GNOME/mutter/merge_requests/697
2019-07-31 09:34:17 +00:00
Niels De Graef
4de892b02a cursor-tracker: Don't use g_cclosure_marshal_VOID__VOID
Similar to gtk commit f507a790, this ensures that the valist variant of
the marshaller is used. From that commit's message:

```
If we set c_marshaller manually, then g_signal_newv() will not setup a
va_marshaller for us. However, if we provide c_marshaller as NULL, it will
setup both the c_marshaller (to g_cclosure_marshal_VOID__VOID) and
va_marshaller (to g_cclosure_marshal_VOID__VOIDv) for us.
```

https://gitlab.gnome.org/GNOME/mutter/merge_requests/697
2019-07-31 09:34:17 +00:00
Niels De Graef
efe6c13d93 cursor-tracker: Use our own marshal for cursor-moved
By putting `NULL` as the C marshaller in `g_signal_new`, you
automatically get `g_cclosure_marshaller_generic`, which will try to
process its arguments and return value with the help of libffi and
GValue.

Using `glib-genmarshal` and valist_marshallers, we can prevent this so
that we need less instructions for each signal emission.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/697
2019-07-31 09:34:17 +00:00
Carlos Garnacho
aae9f3a3e6 window-actor: Fix rectangle coordinates in culling
The cull methods expect regions with 0,0 in the actor top-left corner,
whereas meta_window_get_frame_rect() returns a rectangle in workarea
coordinates.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/707
2019-07-31 00:27:33 +02:00
Carlos Garnacho
f501fdcc56 window-actor: Remove negation in function name
Double negations are the spawn of the devil, and is_non_opaque() is
used like that to find out if it's opaque most often, change the
function name to see the glass half full.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/698
2019-07-30 23:17:14 +02:00
Carlos Garnacho
90a5582a73 background-actor: Clip obscured background areas
The MetaBackgroundActor was ignoring the unobscured area altogether,
and just painted according to the clip area. Check the unobscured
area too, as it might well be covered by client windows.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/698
2019-07-30 23:17:14 +02:00
Carlos Garnacho
ac7aa11417 window-actor: Cull out areas covered by opaque windows
Wayland clients do this through the opaque region in the surface
actor. However X11 clients were considered fully transparent for
culling purposes, which may result in mutter painting other bits
of the background or other windows that will be painted over in
reality.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/698
2019-07-30 23:17:14 +02:00
Carlos Garnacho
cc5968109b window-actor: Fix check to clip beneath the window
We want to clip it away if 1) The window is fully opaque or
2) If it's translucent but has a frame (as explained in the comment
above). The code didn't quite match and we were only applying it on
case #2.

Case #1 is far more common, and saves us from pushing some drawing
that we know will be covered in the end.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/698
2019-07-30 23:08:51 +02:00
Carlos Garnacho
0f6ab787ac window-actor: Check frame bounds region before use
It may be NULL when the window goes unmanaged. This was unnoticed
as we barely enter the clip_shadow_under_window() check.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/698
2019-07-30 23:08:42 +02:00
Carlos Garnacho
2812338b7a shadow-factory: Optimize shadows entirely if clip region is empty
If the clip region is empty, we don't need to check the 9 slices
separately, nothing will be painted anyway.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/698
2019-07-30 23:08:30 +02:00
Niels De Graef
ddbdb5fa77 clutter: Use g_object_notify_by_pspec()
`g_object_notify()` actually takes a global lock to look up the property
by its name, which means there is a performance hit (albeit tiny) every
time this function is called. For this reason, always try to use
`g_object_notify_by_pspec()` instead.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/703
2019-07-30 13:50:17 +02:00
Fabio Tomat
35007ebae0 Update Friulian translation 2019-07-28 08:06:58 +00:00
Carlos Garnacho
09bab98b1e core: Avoid consecutive workspace changes in window construction
We first set the workspace to the transient-for parent's, and then
try to set on the current workspace. If both happen, we double the
work on adding/removing it from the workspace, and everything that
happens in result.

Should reduce some activity while typing on the Epiphany address
bar, as the animation results in a number of xdg_popup being created
and destroyed to handle the animation.

https://gitlab.gnome.org/GNOME/mutter/issues/556
2019-07-24 21:06:50 +02:00
Carlos Garnacho
aee8bfce3f core: Only notify on MetaWindow::user-time on actual changes
If the timestamp is the same, it doesn't make sense to update and we
don't do so. So it doesn't make sense to notify on the property either.

https://gitlab.gnome.org/GNOME/mutter/issues/556
2019-07-24 13:55:53 +02:00
Florian Müllner
92868182c9 build: Bump API version automatically each development cycle
Since the API version was added, we've bumped it at some point late-ish in
the cycle when enough changes had accumulated (but way after the first ABI
break). Automate that process by computing the API version automatically
from the project version:
With this commit, the new API version will be 5 for the remaining 3.33.x
releases and all 3.34.x stable versions; 3.35.1 will then bump it to 6 and
so forth.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/696
2019-07-23 22:37:54 +02:00
Florian Müllner
08a3cbfc6c clutter: Force an allocation on clone source if necessary
Since commit 0eab73dc, actors are only allocated when they are actually
visible. While this generally works well, it breaks - because of *course*
it does - ClutterClones when the clone source (or any of its ancestors)
is hidden.

Force an allocation in that case to allow the clone's paint to work as
intended.

https://gitlab.gnome.org/GNOME/mutter/issues/683
2019-07-23 01:38:38 +00:00
32 changed files with 636 additions and 242 deletions

View File

@@ -252,6 +252,13 @@ clutter_clone_allocate (ClutterActor *self,
if (priv->clone_source == NULL)
return;
/* ClutterActor delays allocating until the actor is shown; however
* we cannot paint it correctly in that case, so force an allocation.
*/
if (clutter_actor_get_parent (priv->clone_source) != NULL &&
!clutter_actor_has_allocation (priv->clone_source))
clutter_actor_allocate_preferred_size (priv->clone_source, flags);
#if 0
/* XXX - this is wrong: ClutterClone cannot clone unparented
* actors, as it will break all invariants

View File

@@ -179,9 +179,12 @@ enum
PROP_USE_ALPHA,
PROP_KEY_FOCUS,
PROP_NO_CLEAR_HINT,
PROP_ACCEPT_FOCUS
PROP_ACCEPT_FOCUS,
PROP_LAST
};
static GParamSpec *obj_props[PROP_LAST] = { NULL, };
enum
{
ACTIVATE,
@@ -839,7 +842,7 @@ clutter_stage_emit_key_focus_event (ClutterStage *stage,
else
g_signal_emit_by_name (priv->key_focused_actor, "key-focus-out");
g_object_notify (G_OBJECT (stage), "key-focus");
g_object_notify_by_pspec (G_OBJECT (stage), obj_props[PROP_KEY_FOCUS]);
}
static void
@@ -1877,7 +1880,6 @@ clutter_stage_class_init (ClutterStageClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
GParamSpec *pspec;
gobject_class->constructed = clutter_stage_constructed;
gobject_class->set_property = clutter_stage_set_property;
@@ -1908,14 +1910,13 @@ clutter_stage_class_init (ClutterStageClass *klass)
*
* Whether the mouse pointer should be visible
*/
pspec = g_param_spec_boolean ("cursor-visible",
P_("Cursor Visible"),
P_("Whether the mouse pointer is visible on the main stage"),
TRUE,
CLUTTER_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_CURSOR_VISIBLE,
pspec);
obj_props[PROP_CURSOR_VISIBLE] =
g_param_spec_boolean ("cursor-visible",
P_("Cursor Visible"),
P_("Whether the mouse pointer is visible on the main stage"),
TRUE,
CLUTTER_PARAM_READWRITE);
/**
* ClutterStage:color:
*
@@ -1924,13 +1925,13 @@ clutter_stage_class_init (ClutterStageClass *klass)
* Deprecated: 1.10: Use the #ClutterActor:background-color property of
* #ClutterActor instead.
*/
pspec = clutter_param_spec_color ("color",
P_("Color"),
P_("The color of the stage"),
&default_stage_color,
CLUTTER_PARAM_READWRITE |
G_PARAM_DEPRECATED);
g_object_class_install_property (gobject_class, PROP_COLOR, pspec);
obj_props[PROP_COLOR] =
clutter_param_spec_color ("color",
P_("Color"),
P_("The color of the stage"),
&default_stage_color,
CLUTTER_PARAM_READWRITE |
G_PARAM_DEPRECATED);
/**
* ClutterStage:perspective:
@@ -1940,14 +1941,12 @@ clutter_stage_class_init (ClutterStageClass *klass)
*
* Since: 0.8
*/
pspec = g_param_spec_boxed ("perspective",
P_("Perspective"),
P_("Perspective projection parameters"),
CLUTTER_TYPE_PERSPECTIVE,
CLUTTER_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_PERSPECTIVE,
pspec);
obj_props[PROP_PERSPECTIVE] =
g_param_spec_boxed ("perspective",
P_("Perspective"),
P_("Perspective projection parameters"),
CLUTTER_TYPE_PERSPECTIVE,
CLUTTER_PARAM_READWRITE);
/**
* ClutterStage:title:
@@ -1956,12 +1955,12 @@ clutter_stage_class_init (ClutterStageClass *klass)
*
* Since: 0.4
*/
pspec = g_param_spec_string ("title",
P_("Title"),
P_("Stage Title"),
NULL,
CLUTTER_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_TITLE, pspec);
obj_props[PROP_TITLE] =
g_param_spec_string ("title",
P_("Title"),
P_("Stage Title"),
NULL,
CLUTTER_PARAM_READWRITE);
/**
* ClutterStage:use-fog:
@@ -1974,12 +1973,12 @@ clutter_stage_class_init (ClutterStageClass *klass)
*
* Deprecated: 1.10: This property does not do anything.
*/
pspec = g_param_spec_boolean ("use-fog",
P_("Use Fog"),
P_("Whether to enable depth cueing"),
FALSE,
CLUTTER_PARAM_READWRITE | G_PARAM_DEPRECATED);
g_object_class_install_property (gobject_class, PROP_USE_FOG, pspec);
obj_props[PROP_USE_FOG] =
g_param_spec_boolean ("use-fog",
P_("Use Fog"),
P_("Whether to enable depth cueing"),
FALSE,
CLUTTER_PARAM_READWRITE | G_PARAM_DEPRECATED);
/**
* ClutterStage:fog:
@@ -1991,12 +1990,12 @@ clutter_stage_class_init (ClutterStageClass *klass)
*
* Deprecated: 1.10: This property does not do anything.
*/
pspec = g_param_spec_boxed ("fog",
P_("Fog"),
P_("Settings for the depth cueing"),
CLUTTER_TYPE_FOG,
CLUTTER_PARAM_READWRITE | G_PARAM_DEPRECATED);
g_object_class_install_property (gobject_class, PROP_FOG, pspec);
obj_props[PROP_FOG] =
g_param_spec_boxed ("fog",
P_("Fog"),
P_("Settings for the depth cueing"),
CLUTTER_TYPE_FOG,
CLUTTER_PARAM_READWRITE | G_PARAM_DEPRECATED);
/**
* ClutterStage:use-alpha:
@@ -2008,12 +2007,12 @@ clutter_stage_class_init (ClutterStageClass *klass)
*
* Since: 1.2
*/
pspec = g_param_spec_boolean ("use-alpha",
P_("Use Alpha"),
P_("Whether to honour the alpha component of the stage color"),
FALSE,
CLUTTER_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_USE_ALPHA, pspec);
obj_props[PROP_USE_ALPHA] =
g_param_spec_boolean ("use-alpha",
P_("Use Alpha"),
P_("Whether to honour the alpha component of the stage color"),
FALSE,
CLUTTER_PARAM_READWRITE);
/**
* ClutterStage:key-focus:
@@ -2025,12 +2024,12 @@ clutter_stage_class_init (ClutterStageClass *klass)
*
* Since: 1.2
*/
pspec = g_param_spec_object ("key-focus",
P_("Key Focus"),
P_("The currently key focused actor"),
CLUTTER_TYPE_ACTOR,
CLUTTER_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_KEY_FOCUS, pspec);
obj_props[PROP_KEY_FOCUS] =
g_param_spec_object ("key-focus",
P_("Key Focus"),
P_("The currently key focused actor"),
CLUTTER_TYPE_ACTOR,
CLUTTER_PARAM_READWRITE);
/**
* ClutterStage:no-clear-hint:
@@ -2042,12 +2041,12 @@ clutter_stage_class_init (ClutterStageClass *klass)
*
* Since: 1.4
*/
pspec = g_param_spec_boolean ("no-clear-hint",
P_("No Clear Hint"),
P_("Whether the stage should clear its contents"),
FALSE,
CLUTTER_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_NO_CLEAR_HINT, pspec);
obj_props[PROP_NO_CLEAR_HINT] =
g_param_spec_boolean ("no-clear-hint",
P_("No Clear Hint"),
P_("Whether the stage should clear its contents"),
FALSE,
CLUTTER_PARAM_READWRITE);
/**
* ClutterStage:accept-focus:
@@ -2056,12 +2055,14 @@ clutter_stage_class_init (ClutterStageClass *klass)
*
* Since: 1.6
*/
pspec = g_param_spec_boolean ("accept-focus",
P_("Accept Focus"),
P_("Whether the stage should accept focus on show"),
TRUE,
CLUTTER_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_ACCEPT_FOCUS, pspec);
obj_props[PROP_ACCEPT_FOCUS] =
g_param_spec_boolean ("accept-focus",
P_("Accept Focus"),
P_("Whether the stage should accept focus on show"),
TRUE,
CLUTTER_PARAM_READWRITE);
g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
/**
* ClutterStage::activate:
@@ -2359,7 +2360,7 @@ clutter_stage_set_color (ClutterStage *stage,
{
clutter_actor_set_background_color (CLUTTER_ACTOR (stage), color);
g_object_notify (G_OBJECT (stage), "color");
g_object_notify_by_pspec (G_OBJECT (stage), obj_props[PROP_COLOR]);
}
/**
@@ -2649,7 +2650,8 @@ clutter_stage_show_cursor (ClutterStage *stage)
iface->set_cursor_visible (impl, TRUE);
g_object_notify (G_OBJECT (stage), "cursor-visible");
g_object_notify_by_pspec (G_OBJECT (stage),
obj_props[PROP_CURSOR_VISIBLE]);
}
}
}
@@ -2682,7 +2684,8 @@ clutter_stage_hide_cursor (ClutterStage *stage)
iface->set_cursor_visible (impl, FALSE);
g_object_notify (G_OBJECT (stage), "cursor-visible");
g_object_notify_by_pspec (G_OBJECT (stage),
obj_props[PROP_CURSOR_VISIBLE]);
}
}
}
@@ -2894,7 +2897,7 @@ clutter_stage_set_title (ClutterStage *stage,
if (CLUTTER_STAGE_WINDOW_GET_IFACE(impl)->set_title != NULL)
CLUTTER_STAGE_WINDOW_GET_IFACE (impl)->set_title (impl, priv->title);
g_object_notify (G_OBJECT (stage), "title");
g_object_notify_by_pspec (G_OBJECT (stage), obj_props[PROP_TITLE]);
}
/**
@@ -2994,7 +2997,7 @@ clutter_stage_set_key_focus (ClutterStage *stage,
else
g_signal_emit_by_name (stage, "key-focus-in");
g_object_notify (G_OBJECT (stage), "key-focus");
g_object_notify_by_pspec (G_OBJECT (stage), obj_props[PROP_KEY_FOCUS]);
}
/**
@@ -3672,7 +3675,7 @@ clutter_stage_set_use_alpha (ClutterStage *stage,
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
g_object_notify (G_OBJECT (stage), "use-alpha");
g_object_notify_by_pspec (G_OBJECT (stage), obj_props[PROP_USE_ALPHA]);
}
}
@@ -3886,7 +3889,7 @@ clutter_stage_set_no_clear_hint (ClutterStage *stage,
priv->stage_hints = new_hints;
g_object_notify (G_OBJECT (stage), "no-clear-hint");
g_object_notify_by_pspec (G_OBJECT (stage), obj_props[PROP_NO_CLEAR_HINT]);
}
/**
@@ -4128,7 +4131,7 @@ clutter_stage_set_accept_focus (ClutterStage *stage,
if (priv->accept_focus != accept_focus)
{
_clutter_stage_window_set_accept_focus (priv->impl, accept_focus);
g_object_notify (G_OBJECT (stage), "accept-focus");
g_object_notify_by_pspec (G_OBJECT (stage), obj_props[PROP_ACCEPT_FOCUS]);
}
}

View File

@@ -228,8 +228,8 @@ clutter_text_buffer_real_inserted_text (ClutterTextBuffer *buffer,
const gchar *chars,
guint n_chars)
{
g_object_notify (G_OBJECT (buffer), "text");
g_object_notify (G_OBJECT (buffer), "length");
g_object_notify_by_pspec (G_OBJECT (buffer), obj_props[PROP_TEXT]);
g_object_notify_by_pspec (G_OBJECT (buffer), obj_props[PROP_LENGTH]);
}
static void
@@ -237,8 +237,8 @@ clutter_text_buffer_real_deleted_text (ClutterTextBuffer *buffer,
guint position,
guint n_chars)
{
g_object_notify (G_OBJECT (buffer), "text");
g_object_notify (G_OBJECT (buffer), "length");
g_object_notify_by_pspec (G_OBJECT (buffer), obj_props[PROP_TEXT]);
g_object_notify_by_pspec (G_OBJECT (buffer), obj_props[PROP_LENGTH]);
}
/* --------------------------------------------------------------------------------
@@ -598,7 +598,7 @@ clutter_text_buffer_set_max_length (ClutterTextBuffer *buffer,
clutter_text_buffer_delete_text (buffer, max_length, -1);
buffer->priv->max_length = max_length;
g_object_notify (G_OBJECT (buffer), "max-length");
g_object_notify_by_pspec (G_OBJECT (buffer), obj_props[PROP_MAX_LENGTH]);
}
/**

View File

@@ -4821,7 +4821,7 @@ buffer_notify_max_length (ClutterTextBuffer *buffer,
GParamSpec *spec,
ClutterText *self)
{
g_object_notify (G_OBJECT (self), "max-length");
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_MAX_LENGTH]);
}
static void
@@ -4920,9 +4920,9 @@ clutter_text_set_buffer (ClutterText *self,
obj = G_OBJECT (self);
g_object_freeze_notify (obj);
g_object_notify (obj, "buffer");
g_object_notify (obj, "text");
g_object_notify (obj, "max-length");
g_object_notify_by_pspec (obj, obj_props[PROP_BUFFER]);
g_object_notify_by_pspec (obj, obj_props[PROP_TEXT]);
g_object_notify_by_pspec (obj, obj_props[PROP_MAX_LENGTH]);
g_object_thaw_notify (obj);
}

View File

@@ -124,6 +124,8 @@
real-time scheduling. The executable
or user must have CAP_SYS_NICE.
Requires a restart.
• “autostart-xwayland” — initializes Xwayland lazily if there are
X11 clients. Requires restart.
</description>
</key>

View File

@@ -6,7 +6,12 @@ project('mutter', 'c',
mutter_plugin_api_version = '3'
libmutter_api_version = '4'
split_version = meson.project_version().split('.')
# Automatically increase API version each development cycle,
# starting with 0 in 3.23.x
api_version = (split_version[1].to_int() - 23) / 2
libmutter_api_version = '@0@'.format(api_version)
# generic version requirements
fribidi_req = '>= 1.0.0'

View File

@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: mutter master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n"
"POT-Creation-Date: 2019-06-28 19:41+0000\n"
"PO-Revision-Date: 2019-07-01 21:01+0200\n"
"POT-Creation-Date: 2019-07-18 21:05+0000\n"
"PO-Revision-Date: 2019-07-28 10:06+0200\n"
"Last-Translator: Fabio Tomat <f.t.public@gmail.com>\n"
"Language-Team: Friulian <fur@li.org>\n"
"Language: fur\n"
@@ -492,7 +492,6 @@ msgstr ""
"cun Xwayland"
#: data/org.gnome.mutter.wayland.gschema.xml.in:65
#, fuzzy
msgid ""
"Allow all keyboard events to be routed to X11 “override redirect” windows "
"with a grab when running in Xwayland. This option is to support X11 clients "
@@ -504,13 +503,14 @@ msgid ""
"specific X11 ClientMessage to the root window or be among the applications "
"white-listed in key “xwayland-grab-access-rules”."
msgstr ""
"Permet a ducj i events di tastiere di jessi indreçâts sui barcons “override "
"redirect” di X11 cuntun cjapâ il control de tastiere emetût di aplicazions "
"X11 che a zirin in Xwayland, di jessi tignûts in considerazion. Par une "
"cjapade di control di X11, par che e sedi tignude in considerazion sot "
"Wayland, il client al scugne ancje inviâ un specific messaç (X11 "
"ClientMessage) al barcon lidrîs o jessi tra lis aplicazions metudis te liste "
"blancje inte clâf “xwayland-grab-access-rules”."
"Cuant che a zire sot Xwayland, permet a ducj i events di tastiere di jessi "
"indreçâts sui barcons X11 “override redirect” cjapant il control de "
"tastiere. Cheste opzion e ven doprade di râr e no à efiets sui barcons "
"normâi di X11 che a puedin ricevi la concentrazion dai segnai de tastiere "
"sot circostancis normâls. Par une cjapade di control di X11, par che e sedi "
"tignude in considerazion sot Wayland, il client al scugne ancje o inviâ un "
"specific messaç (X11 ClientMessage) al barcon lidrîs o jessi tra lis "
"aplicazions metudis te liste blancje inte clâf “xwayland-grab-access-rules”."
#: data/org.gnome.mutter.wayland.gschema.xml.in:84
msgid "Xwayland applications allowed to issue keyboard grabs"
@@ -698,7 +698,7 @@ msgstr "Stampe version"
msgid "Mutter plugin to use"
msgstr "Plugin Mutter di doprâ"
#: src/core/prefs.c:1834
#: src/core/prefs.c:1849
#, c-format
msgid "Workspace %d"
msgstr "Spazi di lavôr %d"
@@ -712,7 +712,7 @@ msgstr "Mutter al è stât compilât cence supuart pe modalitât fetose\n"
msgid "Mode Switch: Mode %d"
msgstr "Cambie mût: mût %d"
#: src/x11/meta-x11-display.c:681
#: src/x11/meta-x11-display.c:682
#, c-format
msgid ""
"Display “%s” already has a window manager; try using the --replace option to "
@@ -721,16 +721,16 @@ msgstr ""
"Il display “%s” al à za un window manager; prove dopre la opzion --replace "
"par rimplaçâ chel atuâl."
#: src/x11/meta-x11-display.c:1023
#: src/x11/meta-x11-display.c:1024
msgid "Failed to initialize GDK\n"
msgstr "No si è rivâts a inizializâ GDK\n"
#: src/x11/meta-x11-display.c:1047
#: src/x11/meta-x11-display.c:1048
#, c-format
msgid "Failed to open X Window System display “%s”\n"
msgstr "Impussibil vierzi il display “%s” di X Window System\n"
#: src/x11/meta-x11-display.c:1131
#: src/x11/meta-x11-display.c:1132
#, c-format
msgid "Screen %d on display “%s” is invalid\n"
msgstr "Schermi %d su display “%s” no valit\n"

View File

@@ -39,6 +39,7 @@
#include "backends/x11/cm/meta-cursor-sprite-xfixes.h"
#include "cogl/cogl.h"
#include "clutter/clutter.h"
#include "meta-marshal.h"
#include "meta/main.h"
#include "meta/meta-x11-errors.h"
#include "meta/util.h"
@@ -166,20 +167,31 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
NULL, NULL, NULL,
G_TYPE_NONE, 0);
/**
* MetaCursorTracker::cursor-moved:
* @cursor: The #MetaCursorTracker
* @x: The new X coordinate of the cursor
* @y: The new Y coordinate of the cursor
*
* Notifies when the cursor has moved to a new location.
*/
signals[CURSOR_MOVED] = g_signal_new ("cursor-moved",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
NULL, NULL,
meta_marshal_VOID__FLOAT_FLOAT,
G_TYPE_NONE, 2,
G_TYPE_FLOAT,
G_TYPE_FLOAT);
g_signal_set_va_marshaller (signals[CURSOR_MOVED],
G_TYPE_FROM_CLASS (klass),
meta_marshal_VOID__FLOAT_FLOATv);
signals[VISIBILITY_CHANGED] = g_signal_new ("visibility-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
g_cclosure_marshal_VOID__VOID,
0, NULL, NULL, NULL,
G_TYPE_NONE, 0);
}

View File

@@ -34,6 +34,7 @@ typedef enum _MetaExperimentalFeature
META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER = (1 << 0),
META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS = (1 << 1),
META_EXPERIMENTAL_FEATURE_RT_SCHEDULER = (1 << 2),
META_EXPERIMENTAL_FEATURE_AUTOSTART_XWAYLAND = (1 << 3),
} MetaExperimentalFeature;
#define META_TYPE_SETTINGS (meta_settings_get_type ())

View File

@@ -266,6 +266,8 @@ experimental_features_handler (GVariant *features_variant,
features |= META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS;
else if (g_str_equal (feature, "rt-scheduler"))
features |= META_EXPERIMENTAL_FEATURE_RT_SCHEDULER;
else if (g_str_equal (feature, "autostart-xwayland"))
features |= META_EXPERIMENTAL_FEATURE_AUTOSTART_XWAYLAND;
else
g_info ("Unknown experimental feature '%s'\n", feature);
}

View File

@@ -74,4 +74,6 @@ MetaInhibitShortcutsDialog * meta_compositor_create_inhibit_shortcuts_dialog (Me
void meta_compositor_locate_pointer (MetaCompositor *compositor);
void meta_compositor_redirect_x11_windows (MetaCompositor *compositor);
#endif /* META_COMPOSITOR_PRIVATE_H */

View File

@@ -516,6 +516,15 @@ redirect_windows (MetaX11Display *x11_display)
}
}
void
meta_compositor_redirect_x11_windows (MetaCompositor *compositor)
{
MetaDisplay *display = compositor->display;
if (display->x11_display)
redirect_windows (display->x11_display);
}
void
meta_compositor_manage (MetaCompositor *compositor)
{
@@ -595,8 +604,7 @@ meta_compositor_manage (MetaCompositor *compositor)
compositor->have_x11_sync_object = meta_sync_ring_init (xdisplay);
}
if (display->x11_display)
redirect_windows (display->x11_display);
meta_compositor_redirect_x11_windows (compositor);
compositor->plugin_mgr = meta_plugin_manager_new (compositor);
}

View File

@@ -179,6 +179,7 @@ struct _MetaBackgroundActor
gboolean force_bilinear;
cairo_region_t *clip_region;
cairo_region_t *unobscured_region;
};
static void cullable_iface_init (MetaCullableInterface *iface);
@@ -195,12 +196,22 @@ set_clip_region (MetaBackgroundActor *self,
self->clip_region = cairo_region_copy (clip_region);
}
static void
set_unobscured_region (MetaBackgroundActor *self,
cairo_region_t *unobscured_region)
{
g_clear_pointer (&self->unobscured_region, cairo_region_destroy);
if (unobscured_region)
self->unobscured_region = cairo_region_copy (unobscured_region);
}
static void
meta_background_actor_dispose (GObject *object)
{
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object);
set_clip_region (self, NULL);
set_unobscured_region (self, NULL);
meta_background_actor_set_background (self, NULL);
if (self->pipeline)
{
@@ -502,7 +513,8 @@ meta_background_actor_paint (ClutterActor *actor)
ClutterActorBox actor_box;
cairo_rectangle_int_t actor_pixel_rect;
CoglFramebuffer *fb;
int i;
cairo_region_t *region;
int i, n_rects;
if ((self->clip_region && cairo_region_is_empty (self->clip_region)))
return;
@@ -524,27 +536,43 @@ meta_background_actor_paint (ClutterActor *actor)
/* Now figure out what to actually paint.
*/
if (self->clip_region != NULL)
if (self->clip_region)
{
int n_rects = cairo_region_num_rectangles (self->clip_region);
if (n_rects <= MAX_RECTS)
{
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (self->clip_region, i, &rect);
if (!gdk_rectangle_intersect (&actor_pixel_rect, &rect, &rect))
continue;
paint_clipped_rectangle (fb, self->pipeline, &rect, &self->texture_area);
}
return;
}
region = cairo_region_copy (self->clip_region);
cairo_region_intersect_rectangle (region, &actor_pixel_rect);
}
else
{
region = cairo_region_create_rectangle (&actor_pixel_rect);
}
paint_clipped_rectangle (fb, self->pipeline, &actor_pixel_rect, &self->texture_area);
if (self->unobscured_region)
cairo_region_intersect (region, self->unobscured_region);
if (cairo_region_is_empty (region))
{
cairo_region_destroy (region);
return;
}
n_rects = cairo_region_num_rectangles (region);
if (n_rects <= MAX_RECTS)
{
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (region, i, &rect);
paint_clipped_rectangle (fb, self->pipeline, &rect,
&self->texture_area);
}
}
else
{
cairo_rectangle_int_t rect;
cairo_region_get_extents (region, &rect);
paint_clipped_rectangle (fb, self->pipeline, &rect,
&self->texture_area);
}
}
static void
@@ -798,6 +826,8 @@ meta_background_actor_cull_out (MetaCullable *cullable,
cairo_region_t *clip_region)
{
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (cullable);
set_unobscured_region (self, unobscured_region);
set_clip_region (self, clip_region);
}
@@ -805,6 +835,8 @@ static void
meta_background_actor_reset_culling (MetaCullable *cullable)
{
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (cullable);
set_unobscured_region (self, NULL);
set_clip_region (self, NULL);
}

View File

@@ -218,6 +218,9 @@ meta_shadow_paint (MetaShadow *shadow,
int n_x, n_y;
gboolean source_updated = FALSE;
if (clip && cairo_region_is_empty (clip))
return;
if (shadow->scale_width)
{
n_x = 3;

View File

@@ -288,13 +288,13 @@ is_argb32 (MetaWindowActor *self)
}
static gboolean
is_non_opaque (MetaWindowActor *self)
is_opaque (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv =
meta_window_actor_get_instance_private (self);
MetaWindow *window = priv->window;
return is_argb32 (self) || (window->opacity != 0xFF);
return !is_argb32 (self) && (window->opacity == 0xFF);
}
static gboolean
@@ -647,7 +647,10 @@ clip_shadow_under_window (MetaWindowActor *self)
MetaWindowActorPrivate *priv =
meta_window_actor_get_instance_private (self);
return is_non_opaque (self) && priv->window->frame;
if (priv->window->frame)
return TRUE;
return is_opaque (self);
}
static void
@@ -683,7 +686,8 @@ meta_window_actor_paint (ClutterActor *actor)
meta_window_actor_get_shadow_bounds (self, appears_focused, &bounds);
clip = cairo_region_create_rectangle (&bounds);
cairo_region_subtract (clip, frame_bounds);
if (frame_bounds)
cairo_region_subtract (clip, frame_bounds);
}
meta_shadow_paint (shadow,
@@ -787,7 +791,7 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
* Do not add shadows to non-opaque (ARGB32) windows, as we can't easily
* generate shadows for them.
*/
if (is_non_opaque (self))
if (!is_opaque (self))
return FALSE;
/*
@@ -1351,7 +1355,8 @@ meta_window_actor_set_clip_region_beneath (MetaWindowActor *self,
if (clip_shadow_under_window (self))
{
cairo_region_t *frame_bounds = meta_window_get_frame_bounds (priv->window);
cairo_region_subtract (priv->shadow_clip, frame_bounds);
if (frame_bounds)
cairo_region_subtract (priv->shadow_clip, frame_bounds);
}
}
else
@@ -1365,9 +1370,28 @@ meta_window_actor_cull_out (MetaCullable *cullable,
cairo_region_t *clip_region)
{
MetaWindowActor *self = META_WINDOW_ACTOR (cullable);
MetaWindowActorPrivate *priv =
meta_window_actor_get_instance_private (self);
meta_cullable_cull_out_children (cullable, unobscured_region, clip_region);
meta_window_actor_set_clip_region_beneath (self, clip_region);
if (unobscured_region && is_opaque (self))
{
cairo_region_t *region = meta_window_get_frame_bounds (priv->window);
if (region)
{
cairo_region_subtract (unobscured_region, region);
}
else
{
cairo_rectangle_int_t rect;
meta_window_get_frame_rect (priv->window, &rect);
rect.x = rect.y = 0;
cairo_region_subtract_rectangle (unobscured_region, &rect);
}
}
}
static void

View File

@@ -264,7 +264,7 @@ struct _MetaDisplayClass
gboolean meta_display_open (void);
void meta_display_manage_all_windows (MetaDisplay *display);
void meta_display_manage_all_xwindows (MetaDisplay *display);
void meta_display_unmanage_windows (MetaDisplay *display,
guint32 timestamp);

View File

@@ -49,6 +49,7 @@
#include "backends/x11/meta-backend-x11.h"
#include "backends/x11/cm/meta-backend-x11-cm.h"
#include "clutter/x11/clutter-x11.h"
#include "compositor/compositor-private.h"
#include "core/bell.h"
#include "core/boxes-private.h"
#include "core/display-private.h"
@@ -149,6 +150,7 @@ enum
SHOWING_DESKTOP_CHANGED,
RESTACKED,
WORKAREAS_CHANGED,
INIT_XSERVER,
LAST_SIGNAL
};
@@ -479,6 +481,13 @@ meta_display_class_init (MetaDisplayClass *klass)
0, NULL, NULL, NULL,
G_TYPE_NONE, 0);
display_signals[INIT_XSERVER] =
g_signal_new ("init-xserver",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL, NULL,
G_TYPE_NONE, 1, G_TYPE_INT);
g_object_class_install_property (object_class,
PROP_FOCUS_WINDOW,
g_param_spec_object ("focus-window",
@@ -643,10 +652,15 @@ meta_display_init_x11 (MetaDisplay *display,
display->x11_display = x11_display;
g_signal_emit (display, display_signals[X11_DISPLAY_OPENED], 0);
meta_x11_display_create_guard_window (x11_display);
if (!display->display_opening)
meta_display_manage_all_windows (display);
if (meta_get_x11_display_policy () == META_DISPLAY_POLICY_ON_DEMAND)
{
meta_x11_display_create_guard_window (x11_display);
if (!display->display_opening)
meta_display_manage_all_xwindows (display);
meta_compositor_redirect_x11_windows (display->compositor);
}
return TRUE;
}
@@ -758,7 +772,7 @@ meta_display_open (void)
display->selection = meta_selection_new (display);
meta_clipboard_manager_init (display);
if (meta_should_autostart_x11_display ())
if (meta_get_x11_display_policy () == META_DISPLAY_POLICY_MANDATORY)
{
if (!meta_display_init_x11 (display, &error))
g_error ("Failed to start Xwayland: %s", error->message);
@@ -797,7 +811,7 @@ meta_display_open (void)
* we start out with no windows.
*/
if (!meta_is_wayland_compositor ())
meta_display_manage_all_windows (display);
meta_display_manage_all_xwindows (display);
if (old_active_xwindow != None)
{
@@ -2448,7 +2462,7 @@ meta_resize_gravity_from_grab_op (MetaGrabOp op)
}
void
meta_display_manage_all_windows (MetaDisplay *display)
meta_display_manage_all_xwindows (MetaDisplay *display)
{
guint64 *_children;
guint64 *children;
@@ -2462,7 +2476,8 @@ meta_display_manage_all_windows (MetaDisplay *display)
for (i = 0; i < n_children; ++i)
{
g_assert (META_STACK_ID_IS_X11 (children[i]));
if (!META_STACK_ID_IS_X11 (children[i]))
continue;
meta_window_x11_new (display, children[i], TRUE,
META_COMP_EFFECT_NONE);
}

View File

@@ -190,9 +190,14 @@ meta_window_destroy_frame (MetaWindow *window)
"Incrementing unmaps_pending on %s for reparent back to root\n", window->desc);
window->unmaps_pending += 1;
}
meta_stack_tracker_record_add (window->display->stack_tracker,
window->xwindow,
XNextRequest (x11_display->xdisplay));
if (!x11_display->closing)
{
meta_stack_tracker_record_add (window->display->stack_tracker,
window->xwindow,
XNextRequest (x11_display->xdisplay));
}
XReparentWindow (x11_display->xdisplay,
window->xwindow,
x11_display->xroot,

View File

@@ -1570,6 +1570,8 @@ meta_window_grab_keys (MetaWindow *window)
MetaDisplay *display = window->display;
MetaKeyBindingManager *keys = &display->key_binding_manager;
if (!meta_is_wayland_compositor ())
return;
if (window->all_keys_grabbed)
return;
@@ -1604,7 +1606,7 @@ meta_window_grab_keys (MetaWindow *window)
void
meta_window_ungrab_keys (MetaWindow *window)
{
if (window->keys_grabbed)
if (!meta_is_wayland_compositor () && window->keys_grabbed)
{
MetaDisplay *display = window->display;
MetaKeyBindingManager *keys = &display->key_binding_manager;
@@ -1663,7 +1665,11 @@ meta_display_grab_accelerator (MetaDisplay *display,
return META_KEYBINDING_ACTION_NONE;
}
meta_change_keygrab (keys, display->x11_display->xroot, TRUE, &resolved_combo);
if (!meta_is_wayland_compositor ())
{
meta_change_keygrab (keys, display->x11_display->xroot,
TRUE, &resolved_combo);
}
grab = g_new0 (MetaKeyGrab, 1);
grab->action = next_dynamic_keybinding_action ();
@@ -1709,8 +1715,11 @@ meta_display_ungrab_accelerator (MetaDisplay *display,
{
int i;
meta_change_keygrab (keys, display->x11_display->xroot,
FALSE, &binding->resolved_combo);
if (!meta_is_wayland_compositor ())
{
meta_change_keygrab (keys, display->x11_display->xroot,
FALSE, &binding->resolved_combo);
}
for (i = 0; i < binding->resolved_combo.len; i++)
{
@@ -1788,7 +1797,7 @@ meta_window_grab_all_keys (MetaWindow *window,
guint32 timestamp)
{
Window grabwindow;
gboolean retval;
gboolean retval = TRUE;
if (window->all_keys_grabbed)
return FALSE;
@@ -1804,25 +1813,29 @@ meta_window_grab_all_keys (MetaWindow *window,
window->desc);
meta_window_focus (window, timestamp);
grabwindow = meta_window_x11_get_toplevel_xwindow (window);
meta_topic (META_DEBUG_KEYBINDINGS,
"Grabbing all keys on window %s\n", window->desc);
retval = grab_keyboard (grabwindow, timestamp, XIGrabModeAsync);
if (retval)
if (!meta_is_wayland_compositor ())
{
window->keys_grabbed = FALSE;
window->all_keys_grabbed = TRUE;
window->grab_on_frame = window->frame != NULL;
grabwindow = meta_window_x11_get_toplevel_xwindow (window);
meta_topic (META_DEBUG_KEYBINDINGS,
"Grabbing all keys on window %s\n", window->desc);
retval = grab_keyboard (grabwindow, timestamp, XIGrabModeAsync);
if (retval)
{
window->keys_grabbed = FALSE;
window->all_keys_grabbed = TRUE;
window->grab_on_frame = window->frame != NULL;
}
}
return retval;
}
void
meta_window_ungrab_all_keys (MetaWindow *window, guint32 timestamp)
meta_window_ungrab_all_keys (MetaWindow *window,
guint32 timestamp)
{
if (window->all_keys_grabbed)
if (!meta_is_wayland_compositor () && window->all_keys_grabbed)
{
ungrab_keyboard (timestamp);

View File

@@ -30,10 +30,17 @@ typedef enum _MetaCompositorType
META_COMPOSITOR_TYPE_X11,
} MetaCompositorType;
typedef enum _MetaDisplayPolicy
{
META_DISPLAY_POLICY_MANDATORY,
META_DISPLAY_POLICY_ON_DEMAND,
META_DISPLAY_POLICY_DISABLED,
} MetaDisplayPolicy;
META_EXPORT_TEST
void meta_override_compositor_configuration (MetaCompositorType compositor_type,
GType backend_gtype);
gboolean meta_should_autostart_x11_display (void);
MetaDisplayPolicy meta_get_x11_display_policy (void);
#endif /* META_MAIN_PRIVATE_H */

View File

@@ -717,15 +717,27 @@ prefs_changed_callback (MetaPreference pref,
}
}
gboolean
meta_should_autostart_x11_display (void)
MetaDisplayPolicy
meta_get_x11_display_policy (void)
{
MetaBackend *backend = meta_get_backend ();
gboolean wants_x11 = TRUE;
if (META_IS_BACKEND_X11_CM (backend))
return META_DISPLAY_POLICY_MANDATORY;
#ifdef HAVE_WAYLAND
wants_x11 = !opt_no_x11;
if (meta_is_wayland_compositor ())
{
MetaSettings *settings = meta_backend_get_settings (backend);
if (opt_no_x11)
return META_DISPLAY_POLICY_DISABLED;
if (meta_settings_is_experimental_feature_enabled (settings,
META_EXPERIMENTAL_FEATURE_AUTOSTART_XWAYLAND))
return META_DISPLAY_POLICY_ON_DEMAND;
}
#endif
return META_IS_BACKEND_X11_CM (backend) || wants_x11;
return META_DISPLAY_POLICY_MANDATORY;
}

View File

@@ -114,7 +114,7 @@ meta_launch_context_constructed (GObject *object)
G_OBJECT_CLASS (meta_launch_context_parent_class)->constructed (object);
x11_display = getenv ("DISPLAY");
x11_display = meta_x11_get_display_name ();
wayland_display = getenv ("WAYLAND_DISPLAY");
if (x11_display)

View File

@@ -508,6 +508,42 @@ query_xserver_stack (MetaDisplay *display,
XFree (children);
}
static void
drop_x11_windows (MetaDisplay *display,
MetaStackTracker *tracker)
{
GArray *new_stack;
GList *l;
int i;
tracker->xserver_serial = 0;
new_stack = g_array_new (FALSE, FALSE, sizeof (guint64));
for (i = 0; i < tracker->verified_stack->len; i++)
{
guint64 window = g_array_index (tracker->verified_stack, guint64, i);
if (!META_STACK_ID_IS_X11 (window))
g_array_append_val (new_stack, window);
}
g_array_unref (tracker->verified_stack);
tracker->verified_stack = new_stack;
l = tracker->unverified_predictions->head;
while (l)
{
MetaStackOp *op = l->data;
GList *next = l->next;
if (META_STACK_ID_IS_X11 (op->any.window))
g_queue_remove (tracker->unverified_predictions, op);
l = next;
}
}
MetaStackTracker *
meta_stack_tracker_new (MetaDisplay *display)
{
@@ -523,6 +559,10 @@ meta_stack_tracker_new (MetaDisplay *display)
"x11-display-opened",
G_CALLBACK (query_xserver_stack),
tracker);
g_signal_connect (display,
"x11-display-closing",
G_CALLBACK (drop_x11_windows),
tracker);
meta_stack_tracker_dump (tracker);
@@ -546,6 +586,9 @@ meta_stack_tracker_free (MetaStackTracker *tracker)
g_signal_handlers_disconnect_by_func (tracker->display,
(gpointer)query_xserver_stack,
tracker);
g_signal_handlers_disconnect_by_func (tracker->display,
drop_x11_windows,
tracker);
g_free (tracker);
}

View File

@@ -1296,8 +1296,7 @@ _meta_window_shared_new (MetaDisplay *display,
window->transient_for->on_all_workspaces_requested,
window->transient_for->workspace);
}
if (window->on_all_workspaces)
else if (window->on_all_workspaces)
{
meta_topic (META_DEBUG_PLACEMENT,
"Putting window %s on all workspaces\n",
@@ -7101,9 +7100,9 @@ meta_window_set_user_time (MetaWindow *window,
if (meta_prefs_get_focus_new_windows () == G_DESKTOP_FOCUS_NEW_WINDOWS_STRICT &&
window_is_terminal (window))
window->display->allow_terminal_deactivation = FALSE;
}
g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_USER_TIME]);
g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_USER_TIME]);
}
}
/**

View File

@@ -657,6 +657,14 @@ dbus_idle_monitor_built_sources = gnome.gdbus_codegen('meta-dbus-idle-monitor',
)
mutter_built_sources += dbus_idle_monitor_built_sources
mutter_marshal = gnome.genmarshal('meta-marshal',
sources: ['meta-marshal.list'],
prefix: 'meta_marshal',
internal: true,
valist_marshallers: true,
)
mutter_built_sources += mutter_marshal
if have_profiler
mutter_sources += [
'backends/meta-profiler.c',

1
src/meta-marshal.list Normal file
View File

@@ -0,0 +1 @@
VOID:FLOAT,FLOAT

View File

@@ -48,16 +48,26 @@ typedef struct
char *lock_file;
int abstract_fd;
int unix_fd;
char *name;
} MetaXWaylandConnection;
typedef struct
{
MetaXWaylandConnection private_connection;
MetaXWaylandConnection public_connection;
guint xserver_grace_period_id;
struct wl_display *wayland_display;
struct wl_client *client;
struct wl_resource *xserver_resource;
char *display_name;
char *auth_file;
GCancellable *xserver_died_cancellable;
GSubprocess *proc;
GMainLoop *init_loop;
GList *x11_windows;
MetaXWaylandDnd *dnd;
} MetaXWaylandManager;

View File

@@ -418,9 +418,9 @@ meta_wayland_init (void)
meta_wayland_eglstream_controller_init (compositor);
#endif
if (meta_should_autostart_x11_display ())
if (meta_get_x11_display_policy () != META_DISPLAY_POLICY_DISABLED)
{
if (!meta_xwayland_start (&compositor->xwayland_manager, compositor->wayland_display))
if (!meta_xwayland_init (&compositor->xwayland_manager, compositor->wayland_display))
g_error ("Failed to start X Wayland");
}
@@ -443,9 +443,9 @@ meta_wayland_init (void)
compositor->display_name = g_strdup (display_name);
}
if (meta_should_autostart_x11_display ())
if (meta_get_x11_display_policy () != META_DISPLAY_POLICY_DISABLED)
{
set_gnome_env ("DISPLAY", meta_wayland_get_xwayland_display_name (compositor));
set_gnome_env ("DISPLAY", compositor->xwayland_manager.public_connection.name);
set_gnome_env ("XAUTHORITY", meta_wayland_get_xwayland_auth_file (compositor));
}
@@ -461,7 +461,7 @@ meta_wayland_get_wayland_display_name (MetaWaylandCompositor *compositor)
const char *
meta_wayland_get_xwayland_display_name (MetaWaylandCompositor *compositor)
{
return compositor->xwayland_manager.display_name;
return compositor->xwayland_manager.private_connection.name;
}
void
@@ -471,7 +471,7 @@ meta_wayland_finalize (void)
compositor = meta_wayland_compositor_get_default ();
meta_xwayland_stop (&compositor->xwayland_manager);
meta_xwayland_shutdown (&compositor->xwayland_manager);
g_clear_pointer (&compositor->display_name, g_free);
}

View File

@@ -25,14 +25,14 @@
#include "wayland/meta-wayland-private.h"
gboolean
meta_xwayland_start (MetaXWaylandManager *manager,
struct wl_display *display);
meta_xwayland_init (MetaXWaylandManager *manager,
struct wl_display *display);
void
meta_xwayland_complete_init (MetaDisplay *display);
void
meta_xwayland_stop (MetaXWaylandManager *manager);
meta_xwayland_shutdown (MetaXWaylandManager *manager);
/* wl_data_device/X11 selection interoperation */
void meta_xwayland_init_dnd (void);

View File

@@ -41,6 +41,7 @@
#include "compositor/meta-surface-actor-wayland.h"
#include "compositor/meta-window-actor-private.h"
#include "core/main-private.h"
#include "meta/main.h"
#include "wayland/meta-wayland-actor-surface.h"
@@ -70,6 +71,8 @@ G_DEFINE_TYPE (MetaWaylandSurfaceRoleXWayland,
static int display_number_override = -1;
static void meta_xwayland_stop_xserver (MetaXWaylandManager *manager);
void
meta_xwayland_associate_window_with_surface (MetaWindow *window,
MetaWaylandSurface *surface)
@@ -368,24 +371,45 @@ xserver_died (GObject *source,
g_warning ("Failed to finish waiting for Xwayland: %s", error->message);
}
else if (!g_subprocess_get_successful (proc))
g_warning ("X Wayland crashed; exiting");
else
{
/* For now we simply abort if we see the server exit.
*
* In the future X will only be loaded lazily for legacy X support
* but for now it's a hard requirement. */
g_warning ("Spurious exit of X Wayland server");
}
g_warning ("X Wayland process exited");
meta_exit (META_EXIT_ERROR);
if (meta_get_x11_display_policy () == META_DISPLAY_POLICY_MANDATORY)
{
meta_exit (META_EXIT_ERROR);
}
else if (meta_get_x11_display_policy () == META_DISPLAY_POLICY_ON_DEMAND)
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaDisplay *display = meta_get_display ();
if (display->x11_display)
meta_display_shutdown_x11 (display);
if (!meta_xwayland_init (&compositor->xwayland_manager,
compositor->wayland_display))
g_warning ("Failed to init X sockets");
}
}
static gboolean
shutdown_xwayland_cb (gpointer data)
{
MetaXWaylandManager *manager = data;
g_debug ("Shutting down Xwayland");
manager->xserver_grace_period_id = 0;
meta_display_shutdown_x11 (meta_get_display ());
meta_xwayland_stop_xserver (manager);
return G_SOURCE_REMOVE;
}
static int
x_io_error (Display *display)
{
g_warning ("Connection to xwayland lost");
meta_exit (META_EXIT_ERROR);
if (meta_get_x11_display_policy () == META_DISPLAY_POLICY_MANDATORY)
meta_exit (META_EXIT_ERROR);
return 0;
}
@@ -397,7 +421,36 @@ meta_xwayland_override_display_number (int number)
}
static gboolean
choose_xdisplay (MetaXWaylandManager *manager)
open_display_sockets (MetaXWaylandManager *manager,
int display_index,
int *abstract_fd_out,
int *unix_fd_out,
gboolean *fatal)
{
int abstract_fd, unix_fd;
abstract_fd = bind_to_abstract_socket (display_index,
fatal);
if (abstract_fd < 0)
return FALSE;
unix_fd = bind_to_unix_socket (display_index);
if (unix_fd < 0)
{
*fatal = FALSE;
close (abstract_fd);
return FALSE;
}
*abstract_fd_out = abstract_fd;
*unix_fd_out = unix_fd;
return TRUE;
}
static gboolean
choose_xdisplay (MetaXWaylandManager *manager,
MetaXWaylandConnection *connection)
{
int display = 0;
char *lock_file = NULL;
@@ -417,8 +470,10 @@ choose_xdisplay (MetaXWaylandManager *manager)
return FALSE;
}
manager->abstract_fd = bind_to_abstract_socket (display, &fatal);
if (manager->abstract_fd < 0)
if (!open_display_sockets (manager, display,
&connection->abstract_fd,
&connection->unix_fd,
&fatal))
{
unlink (lock_file);
@@ -429,27 +484,18 @@ choose_xdisplay (MetaXWaylandManager *manager)
}
else
{
g_warning ("Failed to bind abstract socket");
g_warning ("Failed to bind X11 socket");
return FALSE;
}
}
manager->unix_fd = bind_to_unix_socket (display);
if (manager->unix_fd < 0)
{
unlink (lock_file);
close (manager->abstract_fd);
display++;
continue;
}
break;
}
while (1);
manager->display_index = display;
manager->display_name = g_strdup_printf (":%d", manager->display_index);
manager->lock_file = lock_file;
connection->display_index = display;
connection->name = g_strdup_printf (":%d", connection->display_index);
connection->lock_file = lock_file;
return TRUE;
}
@@ -536,6 +582,7 @@ on_displayfd_ready (int fd,
gpointer user_data)
{
MetaXWaylandManager *manager = user_data;
MetaDisplay *display = meta_get_display ();
/* The server writes its display name to the displayfd
* socket when it's ready. We don't care about the data
@@ -543,11 +590,17 @@ on_displayfd_ready (int fd,
* that means it's ready. */
xserver_finished_init (manager);
g_signal_emit_by_name (display, "init-xserver",
manager->private_connection.display_index);
if (meta_get_x11_display_policy () == META_DISPLAY_POLICY_ON_DEMAND)
meta_display_init_x11 (display, NULL);
return G_SOURCE_REMOVE;
}
static gboolean
meta_xwayland_init_xserver (MetaXWaylandManager *manager)
meta_xwayland_start_xserver (MetaXWaylandManager *manager)
{
int xwayland_client_fd[2];
int displayfd[2];
@@ -581,14 +634,15 @@ meta_xwayland_init_xserver (MetaXWaylandManager *manager)
launcher = g_subprocess_launcher_new (flags);
g_subprocess_launcher_take_fd (launcher, xwayland_client_fd[1], 3);
g_subprocess_launcher_take_fd (launcher, manager->abstract_fd, 4);
g_subprocess_launcher_take_fd (launcher, manager->unix_fd, 5);
g_subprocess_launcher_take_fd (launcher, manager->public_connection.abstract_fd, 4);
g_subprocess_launcher_take_fd (launcher, manager->public_connection.unix_fd, 5);
g_subprocess_launcher_take_fd (launcher, displayfd[1], 6);
g_subprocess_launcher_take_fd (launcher, manager->private_connection.abstract_fd, 7);
g_subprocess_launcher_setenv (launcher, "WAYLAND_SOCKET", "3", TRUE);
manager->proc = g_subprocess_launcher_spawn (launcher, &error,
XWAYLAND_PATH, manager->display_name,
XWAYLAND_PATH, manager->public_connection.name,
"-rootless",
"-noreset",
"-accessx",
@@ -597,6 +651,7 @@ meta_xwayland_init_xserver (MetaXWaylandManager *manager)
"-listen", "4",
"-listen", "5",
"-displayfd", "6",
"-initfd", "7",
NULL);
if (!manager->proc)
{
@@ -620,30 +675,133 @@ meta_xwayland_init_xserver (MetaXWaylandManager *manager)
return TRUE;
}
gboolean
meta_xwayland_start (MetaXWaylandManager *manager,
struct wl_display *wl_display)
static gboolean
xdisplay_connection_activity_cb (gint fd,
GIOCondition cond,
gpointer user_data)
{
if (!choose_xdisplay (manager))
return FALSE;
MetaXWaylandManager *manager = user_data;
if (!meta_xwayland_start_xserver (manager))
g_critical ("Could not start Xserver");
return G_SOURCE_REMOVE;
}
static void
window_unmanaged_cb (MetaWindow *window,
MetaXWaylandManager *manager)
{
manager->x11_windows = g_list_remove (manager->x11_windows, window);
g_signal_handlers_disconnect_by_func (window,
window_unmanaged_cb,
manager);
if (!manager->x11_windows)
{
g_debug ("All X11 windows gone, setting shutdown timeout");
manager->xserver_grace_period_id =
g_timeout_add_seconds (10, shutdown_xwayland_cb, manager);
}
}
static void
window_created_cb (MetaDisplay *display,
MetaWindow *window,
MetaXWaylandManager *manager)
{
if (window->xwindow &&
meta_window_get_client_pid (window) != getpid ())
{
manager->x11_windows = g_list_prepend (manager->x11_windows, window);
g_signal_connect (window, "unmanaged",
G_CALLBACK (window_unmanaged_cb), manager);
if (manager->xserver_grace_period_id)
{
g_source_remove (manager->xserver_grace_period_id);
manager->xserver_grace_period_id = 0;
}
}
}
static void
meta_xwayland_stop_xserver (MetaXWaylandManager *manager)
{
if (manager->proc)
g_subprocess_send_signal (manager->proc, SIGTERM);
g_signal_handlers_disconnect_by_func (meta_get_display (),
window_created_cb,
manager);
g_clear_object (&manager->xserver_died_cancellable);
g_clear_object (&manager->proc);
}
gboolean
meta_xwayland_init (MetaXWaylandManager *manager,
struct wl_display *wl_display)
{
MetaDisplayPolicy policy;
gboolean fatal;
if (!manager->public_connection.name)
{
if (!choose_xdisplay (manager, &manager->public_connection))
return FALSE;
if (!choose_xdisplay (manager, &manager->private_connection))
return FALSE;
}
else
{
if (!open_display_sockets (manager,
manager->public_connection.display_index,
&manager->public_connection.abstract_fd,
&manager->public_connection.unix_fd,
&fatal))
return FALSE;
if (!open_display_sockets (manager,
manager->private_connection.display_index,
&manager->private_connection.abstract_fd,
&manager->private_connection.unix_fd,
&fatal))
return FALSE;
}
if (!prepare_auth_file (manager))
return FALSE;
manager->wayland_display = wl_display;
return meta_xwayland_init_xserver (manager);
policy = meta_get_x11_display_policy ();
if (policy == META_DISPLAY_POLICY_MANDATORY)
{
return meta_xwayland_start_xserver (manager);
}
else if (policy == META_DISPLAY_POLICY_ON_DEMAND)
{
g_unix_fd_add (manager->public_connection.abstract_fd, G_IO_IN,
xdisplay_connection_activity_cb, manager);
return TRUE;
}
return FALSE;
}
static void
on_x11_display_closing (MetaDisplay *display)
{
meta_xwayland_shutdown_dnd ();
g_signal_handlers_disconnect_by_func (display,
on_x11_display_closing,
NULL);
}
/* To be called right after connecting */
void
meta_xwayland_complete_init (MetaDisplay *display)
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaXWaylandManager *manager = &compositor->xwayland_manager;
/* We install an X IO error handler in addition to the child watch,
because after Xlib connects our child watch may not be called soon
enough, and therefore we won't crash when X exits (and most important
@@ -654,31 +812,41 @@ meta_xwayland_complete_init (MetaDisplay *display)
g_signal_connect (display, "x11-display-closing",
G_CALLBACK (on_x11_display_closing), NULL);
meta_xwayland_init_dnd ();
g_signal_connect (meta_get_display (), "window-created",
G_CALLBACK (window_created_cb), manager);
}
void
meta_xwayland_stop (MetaXWaylandManager *manager)
meta_xwayland_shutdown (MetaXWaylandManager *manager)
{
char path[256];
g_cancellable_cancel (manager->xserver_died_cancellable);
g_clear_object (&manager->proc);
g_clear_object (&manager->xserver_died_cancellable);
snprintf (path, sizeof path, "/tmp/.X11-unix/X%d", manager->display_index);
snprintf (path, sizeof path, "/tmp/.X11-unix/X%d", manager->public_connection.display_index);
unlink (path);
g_clear_pointer (&manager->display_name, g_free);
snprintf (path, sizeof path, "/tmp/.X11-unix/X%d", manager->private_connection.display_index);
unlink (path);
g_clear_pointer (&manager->public_connection.name, g_free);
g_clear_pointer (&manager->private_connection.name, g_free);
if (manager->public_connection.lock_file)
{
unlink (manager->public_connection.lock_file);
g_clear_pointer (&manager->public_connection.lock_file, g_free);
}
if (manager->private_connection.lock_file)
{
unlink (manager->private_connection.lock_file);
g_clear_pointer (&manager->private_connection.lock_file, g_free);
}
if (manager->auth_file)
{
unlink (manager->auth_file);
g_clear_pointer (&manager->auth_file, g_free);
}
if (manager->lock_file)
{
unlink (manager->lock_file);
g_clear_pointer (&manager->lock_file, g_free);
}
}
static void

View File

@@ -144,6 +144,8 @@ struct _MetaX11Display
guint keys_grabbed : 1;
guint closing : 1;
/* we use property updates as sentinels for certain window focus events
* to avoid some race conditions on EnterNotify events
*/
@@ -249,4 +251,6 @@ void meta_x11_display_set_input_focus (MetaX11Display *x11_display,
Window xwindow,
guint32 timestamp);
const gchar * meta_x11_get_display_name (void);
#endif /* META_X11_DISPLAY_PRIVATE_H */

View File

@@ -129,17 +129,19 @@ meta_x11_display_dispose (GObject *object)
{
MetaX11Display *x11_display = META_X11_DISPLAY (object);
x11_display->closing = TRUE;
meta_x11_startup_notification_release (x11_display);
meta_prefs_remove_listener (prefs_changed_callback, x11_display);
meta_x11_display_ungrab_keys (x11_display);
g_clear_object (&x11_display->x11_stack);
meta_x11_selection_shutdown (x11_display);
meta_x11_display_unmanage_windows (x11_display);
g_clear_object (&x11_display->x11_stack);
if (x11_display->ui)
{
meta_ui_free (x11_display->ui);
@@ -182,21 +184,8 @@ meta_x11_display_dispose (GObject *object)
if (x11_display->guard_window != None)
{
MetaStackTracker *stack_tracker = x11_display->display->stack_tracker;
if (stack_tracker)
{
unsigned long serial;
serial = XNextRequest (x11_display->xdisplay);
meta_stack_tracker_record_remove (stack_tracker,
x11_display->guard_window,
serial);
}
XUnmapWindow (x11_display->xdisplay, x11_display->guard_window);
XDestroyWindow (x11_display->xdisplay, x11_display->guard_window);
x11_display->guard_window = None;
}
@@ -988,6 +977,25 @@ meta_set_gnome_wm_keybindings (const char *wm_keybindings)
gnome_wm_keybindings = wm_keybindings;
}
const gchar *
meta_x11_get_display_name (void)
{
#ifdef HAVE_WAYLAND
if (meta_is_wayland_compositor ())
{
MetaWaylandCompositor *compositor;
compositor = meta_wayland_compositor_get_default ();
return meta_wayland_get_xwayland_display_name (compositor);
}
else
#endif
{
return g_getenv ("DISPLAY");
}
}
gboolean
meta_x11_init_gdk_display (GError **error)
{
@@ -996,7 +1004,7 @@ meta_x11_init_gdk_display (GError **error)
const char *gdk_gl_env = NULL;
Display *xdisplay;
xdisplay_name = g_getenv ("DISPLAY");
xdisplay_name = meta_x11_get_display_name ();
if (!xdisplay_name)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,