Compare commits

...

41 Commits

Author SHA1 Message Date
eb2405f0f4 cogl: Include DRM 4CC conversions into CoglPixelFormat
This is at the moment still part of both MetaRendererNative and
MetaDmaBuf, which means duplicated effort in code sections only barely
related to color formats. By doing this, we can keep more of the pixel
format code together, which is more future-proof as we want to add
support for new pixel formats (like YUV-based ones).

https://gitlab.gnome.org/GNOME/mutter/merge_requests/594
2019-05-28 17:29:18 +02:00
a2c545c321 x11-display: Simplify bell handling
Since commit 956ab4bd made libcanberra mandatory, we never use
the system bell for handling the `audible-bell` setting. So
instead of reacting to settings changes with the exact same call
to XkbChangeEnabledControls(), just call it once when initializing.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/598
2019-05-28 14:34:32 +00:00
3cd8f3b7dc workspace-manager: Remove unnecessary assignment
The initialization to -1 is never used, instead the variables are
re-initialized to 0 before the loop that uses them.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/598
2019-05-28 14:34:32 +00:00
033ce2d956 input-mapper: Remove unnecessary return value
Since commit ae6d9e35bd, there is a fallback to META_MATCH_IS_BUILTIN,
so the condition for returning FALSE is never met.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/598
2019-05-28 14:34:32 +00:00
2b47e89405 renderer-x11-nested: Fix copy-and-paste error
The rounding added in commit c5471e5b8b mixed up some variables,
whoops.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/598
2019-05-28 14:34:32 +00:00
80d11287eb cogl-path: Undeprecate framebuffer functions
It looks like deprecating the functions with explicit framebuffer/pipeline
arguments made it to (cogl) master by mistake:

https://mail.gnome.org/archives/clutter-list/2016-April/msg00008.html

We now use one of them, so this is a good time to undeprecate the lot.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/597
2019-05-27 22:48:19 +00:00
f869e4d54b headless-start-test: Ignore frame counter warnings
When running in slow or busy machines (hey CI!) or under valgrind headless
tests could fail because of a non fatal warning during initialization.

So define a fatal handler that ignores the frame counter warning.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/581
2019-05-27 17:26:30 -05:00
c1059df7f9 test-runner: Always wait after creating a window
Creating a window could take some time, causing false-positive failures when
running in slower or busy hardware like:

  window 1/2 isn't known to Mutter

So before we proceed in doing any operation on it, wait for the client.
Do this in the test runner instead of repeating the same in every .metatest.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/581
2019-05-27 17:23:55 -05:00
e3d3df985f gitlab-ci: Use G_SLICE=always-malloc in tests
This allows to catch errors better, as per MALLOC_CHECK_'s definition

https://gitlab.gnome.org/GNOME/mutter/merge_requests/581
2019-05-27 17:23:55 -05:00
86ff3dfb3c gitlab-ci: Print error logs on failures
https://gitlab.gnome.org/GNOME/mutter/merge_requests/581
2019-05-27 17:23:54 -05:00
7e0d185120 cogl/pipeline: Don't try to access to free'd pointer data
When free'ing a pipeline we destroy the BigState first and then the fragment and
vertex snippets lists using the big state pointer which is now invalid.
This causes a crash  when G_SLICE=always-malloc is set and using MALLOC_CHECK_.

So, invert the operations by free'ing the snippet lists first, and the big state
afterwards.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/581
2019-05-27 17:23:54 -05:00
61c173b777 cogl/xlib-renderer: Save Xlib renderer data in custom winsys pointer
XLib renderer saves its data as the object cogl user data, however this data
is free'd as part of the object destruction that happens before free'ing the
renderer in _cogl_renderer_free(), from where we're calling the renderer
disconnect vfunc.
Thus in _cogl_xlib_renderer_disconnect() we happen to get an invalid pointer to
CoglXlibRenderer and we try access to it in order to close the X11 display.

This causes all the cogl tests to crash when G_SLICE=always-malloc is set and
when using MALLOC_CHECK_.

Fix this using the renderer winsys custom data instead of using cogl object data
for storing the CoglXlibRenderer, and handling the destruction of it manually.

As bonus this also makes access to the renderer data faster.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/581
2019-05-27 17:14:25 -05:00
f99cd18254 clutter/tests/actor-destroy: Check destroying the actor clears the children
Commit df7d8e2cb highlights a crash on test_destroy_destroy, in fact it could
happen that calling clutter_actor_destroy on a child while iterating on the
list, would implicitly call test_destroy_remove that tries to modify the list
at the same time. Causing a memory error.

So instead of manually free the children list, just ensure that this list is
valid and that when the object destruction is done, this is free'd.

See: https://gitlab.gnome.org/GNOME/mutter/merge_requests/576

https://gitlab.gnome.org/GNOME/mutter/merge_requests/581
2019-05-27 17:14:25 -05:00
0405786573 wayland-seat: Use g_free to cleanup MetaWaylandSeat
MetaWaylandSeat is allocated using g_new0(), and thus we should use g_free() to
destroy it.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/581
2019-05-27 17:14:25 -05:00
b016ff29f6 cursor-renderer-native: Free MetaCursorNativePrivate struct
Fix a small leak in native renderer.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/581
2019-05-27 17:14:25 -05:00
3f2e86f67c theme: Remove DEBUG_FILL_STRUCT
This debug statement is actually applied all the times, while it could be useful
for crashes analysis, these days the same can be done using `MALLOC_CHECK_` and
`MALLOC_PERTURB_` env variables.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/581
2019-05-27 17:14:25 -05:00
0aa4a526c6 boxes: Use G_DEFINE_BOXED_TYPE to define the type
https://gitlab.gnome.org/GNOME/mutter/merge_requests/581
2019-05-27 17:14:25 -05:00
85c2aef4bc display: Cleanup Edges when display is closed
This could happen if closing the display when dragging a window, unlikely, but
better to use the cleanup function since we have it.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/581
2019-05-27 17:14:25 -05:00
76664ef891 clutter-text: Fix selection color drawing
Commit cabcad185 removed the call to cogl_set_source_color4ub() before
cogl_fill_path(), so instead of the previously assigned selection color,
the background is drawn with the last set source.

In order to honour the newly added framebuffer parameter and still apply
the correct color, switch from cogl_fill_path() to the (deprecated!)
cogl_framebuffer_fill_path() method.

https://gitlab.gnome.org/GNOME/mutter/issues/494
2019-05-27 18:39:39 +00:00
b1ea768949 wayland: Drop -terminate argument to Xwayland
This argument instructs Xwayland to exit when there are no further
client connections. However we eventually want to handle restarts
ourselves (where, notably, mutter's will be at least the last client
connection).

This behavior could also induce race conditions on startup with clients
that quickly open and close a display, which is a more pressing issue.

Also, add -noreset back (which was also removed in commit 054c25f693 that
added -terminate). We don't want to reset the X server to a pristine state
in that situation either.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/420
2019-05-24 15:30:31 +00:00
ea9d8a895b wayland: Drop error trap
Code underneath seems to handle errors properly, or be x11-agnostic
entirely, this is apparently here to save a few XSync()s on X11. Just
drop this windowing dependent bit to make things cleaner.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/420
2019-05-24 15:30:31 +00:00
38432da328 compositor: Drop error trap
Code underneath seems to handle errors properly, and this is apparently
here to save a few XSync()s on X11. Just drop this windowing dependent
bit to make things cleaner.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/420
2019-05-24 15:30:31 +00:00
430f354cd9 wayland: Split Xwayland initialization in 2 steps
It is now separated into meta_xwayland_start(), which picks an unused
display and sets up the sockets, and meta_xwayland_init_xserver(), which
does the actual exec of Xwayland and MetaX11Display initialization.

This differentiation will be useful when Mutter is able to launch Xwayland
lazily, currently the former calls into the latter.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/420
2019-05-24 15:30:31 +00:00
1cf4279745 x11: Initialize GdkDisplay together with MetaX11Display
It's no longer a "singleton", since it might be closed and opened again.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/420
2019-05-24 15:30:31 +00:00
7713006f5b x11: Unmanage X11 windows on MetaX11Display finalization
This used to be relied upon meta_display_close(), but MetaDisplay
and MetaX11Display lifetimes may be unrelated.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/420
2019-05-24 15:30:31 +00:00
465e13128b core: Add explicit init/shutdown_x11() MetaDisplay calls
The lifetime of MetaX11Display is still tied to MetaDisplay, but these
calls will be useful when it's actually affordable to decouple those.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/420
2019-05-24 15:30:31 +00:00
86de79cfc5 core: Untangle input focus management
In all places (including src/wayland) we tap into meta_x11_display* focus
API, which then calls meta_display* API. This relation is backwards, so
rework input focus management so it's the other way around.

We now have high-level meta_display_(un)set_input_focus functions, which
perform the backend-independent maintenance, and calls into the X11
functions where relevant. These functions are what callers should use.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/420
2019-05-24 15:30:31 +00:00
1d77641f0b x11: Separate X11 focus handling into MetaX11Display method
Updating the MetaWindow focus and the X Window focus is interrelated but
independent. Call one after the other in the places we handle window focus
changes.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/420
2019-05-24 15:30:31 +00:00
2f217109aa core: Relax requirement that MetaWindow shall have icon/mini-icon
We use a GtkIconTheme (thus icon-theme, thus xsettings, thus x11) just to
grab a "missing icon" icon to show in place. Relax this requirement that
surfaces for icon/mini-icon will be set, and just let it have NULL here.

It seems better to have the callers (presumably UI layers) aware of this
and set a proper icon by themselves, but AFAICS there is none in sight,
not even plain mutter seems to use MetaWindow::[mini-]icon. Probably
worth a future cleanup.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/420
2019-05-24 15:30:31 +00:00
5e0523cc8b x11: Move X11 calls to map/unmap a MetaWindow to MetaWindowX11
Add 2 vmethods so that MetaWindowX11 may handle the X11 calls itself.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/420
2019-05-24 15:30:31 +00:00
dbe6e01e12 core: Separate checks for pointer barriers availability
If the check happens on --nested (X11 backend) while there is no X11
display we would get a crash. Since the barriers are non-effective on
nested, just take it out into a separate condition.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/420
2019-05-24 15:30:31 +00:00
103c469cc9 core: Avoid grab transfer shenanigans with non-X11 backend
This explicit ungrab is made to ensure the other X11 display connection
is able to start an active grab immediately on the device without receiving
AlreadyGrabbed.

This is just relevant if there's two X11 display connections to transfer
grabs across, which may just happen on X11 windowing.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/420
2019-05-24 15:30:31 +00:00
ef074ea510 x11: Add MetaX11Stack object
This object takes care of the X11 representation of the window stack,
namely the _NET_CLIENT_LIST and _NET_CLIENT_LIST_STACKING root window
properties.

This code has been lifted from src/core/stack.c into src/x11 as it's
dependent on the X11 display availability. This also leaves MetaStack
squeaky clean of x11 specifics.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/420
2019-05-24 15:30:31 +00:00
39bac6eabd core: Turn MetaStack into a GObject
So we can have it emit signals and whatnot. Those are unused, yet.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/420
2019-05-24 15:30:30 +00:00
0200f4fcd9 x11: Move focus sentinel to MetaX11Display
This focus sentinel is a mechanism to avoid some X11-specific race
conditions in focus-follows-pointer, using X11 mechanisms. Move it to
MetaX11Display altogether.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/420
2019-05-24 15:30:30 +00:00
439afb3f19 window: Move all attached windows with parent
We'd break the loop for moving attached windows at the first window,
meaning we'd only ever move a single attached dialogs or popup if it was
the first window in the list. This doesn't work out well when there are
multiple popups open, so don't break out of the loop at all until all
windows are potentially moved.

This fixes an issue in gtk4 where one or more non-grabbing popups would
end up unattached if there were more than one and the parent window was
moved.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/592
2019-05-24 15:07:03 +00:00
b01edc22f3 backends/x11: Do not reload keymap on new keyboard notifications
XkbNewKeyboardNotify informs the client that there is a new keyboard
driving the VCK. It is essentially meant to notify that the keyboard
possibly has a different range of HW keycodes and/or a different
geometry.

But the translation of those keycodes remain the same, and we don't
do range checks or geometry checks (beyond using KEY_GRAVE as "key
under Esc", but that is hardly one). It seems we can avoid the
busywork that is releasing all our passive grabs, reloading the keymap
and regenerating the keycombos and restoring the passive grabs.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/398
2019-05-24 11:28:07 +02:00
e8bca5052a ci: Make MALLOC_PERTURB_ less random
The point is to not initialize to some non-zero value to find places
incorrectly relying on blocks being zero initialized. Thus, there is no
reason to have a different random number each time, and by having it the
same, we have slightly more reproducable triggers, would we ever trigger
anything due to this.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/591
2019-05-24 10:57:46 +02:00
468882ecec ci: Run dconf update before running tests
Otherwise tests will fail due to the following warning:

(mutter-test-runner:3700): dconf-WARNING **: 06:39:42.124: unable to
open file '/etc/dconf/db/local': Failed to open file
“/etc/dconf/db/local”: open() failed: No such file or directory; expect
degraded performance

https://gitlab.gnome.org/GNOME/mutter/merge_requests/591
2019-05-24 09:23:22 +02:00
be3c89d823 Bump version to 3.33.2
Update NEWS.
2019-05-22 18:15:34 +00:00
7719e33e68 wayland/pointer-constraints: Reject invalid lifetime
https://gitlab.gnome.org/GNOME/mutter/issues/425
2019-05-22 15:06:14 +00:00
46 changed files with 1135 additions and 837 deletions

View File

@ -35,15 +35,17 @@ test-mutter:
variables:
XDG_RUNTIME_DIR: "$CI_PROJECT_DIR/runtime-dir"
GSETTINGS_SCHEMA_DIR: "$CI_PROJECT_DIR/build/data"
G_SLICE: "always-malloc"
MALLOC_CHECK_: "3"
NO_AT_BRIDGE: "1"
MALLOC_PERTURB_: "123"
script:
- dconf update
- mkdir -m 700 $XDG_RUNTIME_DIR
- glib-compile-schemas $GSETTINGS_SCHEMA_DIR
- >
env MALLOC_PERTURB_="$((RANDOM % 256 + 1))"
dbus-run-session -- xvfb-run -s '+iglx -noreset'
meson test -C build --no-rebuild -t 10 --verbose --no-stdsplit --wrap catchsegv
meson test -C build --no-rebuild -t 10 --verbose --no-stdsplit --print-errorlogs --wrap catchsegv
only:
- merge_requests
- /^.*$/

15
NEWS
View File

@ -1,3 +1,18 @@
3.33.2
======
* Fix rendering lag on Xorg [Daniel; !520, !281]
* Misc. bug fixes and cleanups [Carlos, Marco, Jonas D., Florian, Niels,
Daniel, Benjamin, Jonas Å., Ignacio, Vasilis; #598, !576, !547, !578,
!583, !582, !469, !524, !119, !571, !584, !585, !586, #425]
Contributors:
Jonas Ådahl, Benjamin Berg, Jonas Dreßler, Carlos Garnacho, Niels De Graef,
Vasilis Liaskovitis, Florian Müllner, Ignacio Casal Quinteiro,
Marco Trevisan (Treviño), Daniel van Vugt
Translators:
Daniel Mustieles [es]
3.33.1
======
* Remove unused APIs and outdated driver support

View File

@ -1975,6 +1975,7 @@ selection_paint (ClutterText *self,
else
{
/* Paint selection background first */
CoglPipeline *color_pipeline = cogl_pipeline_copy (default_color_pipeline);
PangoLayout *layout = clutter_text_get_layout (self);
CoglPath *selection_path = cogl_path_new ();
CoglColor cogl_color = { 0, };
@ -1987,11 +1988,19 @@ selection_paint (ClutterText *self,
else
color = &priv->text_color;
cogl_color_init_from_4ub (&cogl_color,
color->red,
color->green,
color->blue,
paint_opacity * color->alpha / 255);
cogl_color_premultiply (&cogl_color);
cogl_pipeline_set_color (color_pipeline, &cogl_color);
clutter_text_foreach_selection_rectangle_prescaled (self,
add_selection_rectangle_to_path,
selection_path);
cogl_path_fill (selection_path);
cogl_framebuffer_fill_path (fb, color_pipeline, selection_path);
/* Paint selected text */
cogl_framebuffer_push_path_clip (fb, selection_path);

View File

@ -114,11 +114,12 @@ test_destroy_destroy (ClutterActor *self)
test->tex = NULL;
}
g_list_free_full (test->children, (GDestroyNotify) clutter_actor_destroy);
test->children = NULL;
g_assert_nonnull (test->children);
if (CLUTTER_ACTOR_CLASS (test_destroy_parent_class)->destroy)
CLUTTER_ACTOR_CLASS (test_destroy_parent_class)->destroy (self);
g_assert_null (test->children);
}
static void

View File

@ -460,9 +460,7 @@ cogl_path_fill (CoglPath *path);
* use while filling a path.</note>
*
* Stability: unstable
* Deprecated: 1.16: Use cogl_path_fill() instead
*/
COGL_DEPRECATED_FOR (cogl_path_fill)
void
cogl_framebuffer_fill_path (CoglFramebuffer *framebuffer,
CoglPipeline *pipeline,
@ -492,9 +490,7 @@ cogl_path_stroke (CoglPath *path);
* regardless of the current transformation matrix.
*
* Stability: unstable
* Deprecated: 1.16: Use cogl_path_stroke() instead
*/
COGL_DEPRECATED_FOR (cogl_path_stroke)
void
cogl_framebuffer_stroke_path (CoglFramebuffer *framebuffer,
CoglPipeline *pipeline,
@ -529,9 +525,7 @@ cogl_framebuffer_push_path_clip (CoglFramebuffer *framebuffer,
*
* Since: 1.8
* Stability: Unstable
* Deprecated: 1.16: Use cogl_framebuffer_push_path_clip() instead
*/
COGL_DEPRECATED_FOR (cogl_framebuffer_push_path_clip)
void
cogl_clip_push_from_path (CoglPath *path);

View File

@ -1504,7 +1504,6 @@ cogl_framebuffer_push_path_clip (CoglFramebuffer *framebuffer,
COGL_FRAMEBUFFER_STATE_CLIP;
}
/* XXX: deprecated */
void
cogl_clip_push_from_path (CoglPath *path)
{
@ -1575,7 +1574,6 @@ _cogl_path_build_stroke_attribute_buffer (CoglPath *path)
data->stroke_n_attributes = n_attributes;
}
/* XXX: deprecated */
void
cogl_framebuffer_fill_path (CoglFramebuffer *framebuffer,
CoglPipeline *pipeline,
@ -1588,7 +1586,6 @@ cogl_framebuffer_fill_path (CoglFramebuffer *framebuffer,
_cogl_path_fill_nodes (path, framebuffer, pipeline, 0 /* flags */);
}
/* XXX: deprecated */
void
cogl_framebuffer_stroke_path (CoglFramebuffer *framebuffer,
CoglPipeline *pipeline,

View File

@ -452,9 +452,6 @@ _cogl_pipeline_free (CoglPipeline *pipeline)
_cogl_bitmask_destroy (&uniforms_state->changed_mask);
}
if (pipeline->differences & COGL_PIPELINE_STATE_NEEDS_BIG_STATE)
g_slice_free (CoglPipelineBigState, pipeline->big_state);
if (pipeline->differences & COGL_PIPELINE_STATE_LAYERS)
g_list_free_full (pipeline->layer_differences, cogl_object_unref);
@ -464,6 +461,9 @@ _cogl_pipeline_free (CoglPipeline *pipeline)
if (pipeline->differences & COGL_PIPELINE_STATE_FRAGMENT_SNIPPETS)
_cogl_pipeline_snippet_list_free (&pipeline->big_state->fragment_snippets);
if (pipeline->differences & COGL_PIPELINE_STATE_NEEDS_BIG_STATE)
g_slice_free (CoglPipelineBigState, pipeline->big_state);
g_list_free (pipeline->deprecated_get_layers_list);
recursively_free_layer_caches (pipeline);

View File

@ -29,6 +29,7 @@
*/
#include "cogl-config.h"
#include "cogl-defines.h"
#include <string.h>
#include <math.h>
@ -308,3 +309,66 @@ cogl_pixel_format_to_string (CoglPixelFormat format)
g_assert_not_reached ();
}
#ifdef COGL_HAS_LIBDRM
typedef struct _PixelFormatMap {
uint32_t drm_format;
CoglPixelFormat cogl_format;
CoglTextureComponents cogl_components;
} PixelFormatMap;
static const PixelFormatMap pixel_format_map[] = {
/* DRM formats are defined as little-endian, not machine endian. */
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
{ DRM_FORMAT_RGB565, COGL_PIXEL_FORMAT_RGB_565, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_ABGR8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_XBGR8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_ARGB8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_XRGB8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_BGRA8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_BGRX8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_RGBA8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_RGBX8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
#elif G_BYTE_ORDER == G_BIG_ENDIAN
/* DRM_FORMAT_RGB565 cannot be expressed. */
{ DRM_FORMAT_ABGR8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_XBGR8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_ARGB8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_XRGB8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_BGRA8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_BGRX8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_RGBA8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_RGBX8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
#else
#error "unexpected G_BYTE_ORDER"
#endif
};
gboolean
cogl_pixel_format_from_drm_format (uint32_t drm_format,
CoglPixelFormat *out_format,
CoglTextureComponents *out_components)
{
const size_t n = G_N_ELEMENTS (pixel_format_map);
size_t i;
for (i = 0; i < n; i++)
{
if (pixel_format_map[i].drm_format == drm_format)
break;
}
if (i == n)
return FALSE;
if (out_format)
*out_format = pixel_format_map[i].cogl_format;
if (out_components)
*out_components = pixel_format_map[i].cogl_components;
return TRUE;
}
#endif

View File

@ -38,6 +38,10 @@
#include <stdint.h>
#include <stddef.h>
#ifdef COGL_HAS_LIBDRM
#include <drm_fourcc.h>
#endif
#include <cogl/cogl-defines.h>
#include <glib.h>
@ -58,6 +62,9 @@ G_BEGIN_DECLS
*
* Other examples of factors that can influence the layout in memory are the
* system's endianness.
*
* This file also contains methods to map Linux DRM 4CC codes to
* CoglPixelFormats.
*/
#define COGL_A_BIT (1 << 4)
@ -295,6 +302,34 @@ _cogl_pixel_format_is_endian_dependant (CoglPixelFormat format);
const char *
cogl_pixel_format_to_string (CoglPixelFormat format);
#ifdef COGL_HAS_LIBDRM
/* added in libdrm 2.4.95 */
#ifndef DRM_FORMAT_INVALID
#define DRM_FORMAT_INVALID 0
#endif
/**
* cogl_pixel_format_from_drm_format:
* @drm_format: The DRM 4CC code (as specified in drm_fourcc.h)
* @out_format: (optional): The corresponding #CoglPixelFormat (if successful)
* @out_components: (optional): The corresponding #CoglTextureComponents (if
* sucessful)
*
* Does an internal lookup to find a #CoglPixelFormat that matches the given
* DRM 4CC code. If no such format could be found, this function will return
* %FALSE and the output parameters will stay untouched.
*
* Returns: %TRUE if a #CoglPixelFormat corresponding to the 4CC code exists,
* %FALSE otherwise.
*/
gboolean
cogl_pixel_format_from_drm_format (uint32_t drm_format,
CoglPixelFormat *out_format,
CoglTextureComponents *out_components);
#endif
G_END_DECLS
#endif /* __COGL_PIXEL_FORMAT_H__ */

View File

@ -54,41 +54,27 @@ static char *_cogl_x11_display_name = NULL;
static GList *_cogl_xlib_renderers = NULL;
static void
destroy_xlib_renderer_data (void *user_data)
_xlib_renderer_data_free (CoglXlibRenderer *data)
{
CoglXlibRenderer *data = user_data;
if (data->xvisinfo)
XFree (data->xvisinfo);
g_slice_free (CoglXlibRenderer, user_data);
g_slice_free (CoglXlibRenderer, data);
}
CoglXlibRenderer *
_cogl_xlib_renderer_get_data (CoglRenderer *renderer)
{
static CoglUserDataKey key;
CoglXlibRenderer *data;
/* Constructs a CoglXlibRenderer struct on demand and attaches it to
the object using user data. It's done this way instead of using a
subclassing hierarchy in the winsys data because all EGL winsys's
need the EGL winsys data but only one of them wants the Xlib
data. */
data = cogl_object_get_user_data (COGL_OBJECT (renderer), &key);
if (!renderer->custom_winsys_user_data)
renderer->custom_winsys_user_data = g_slice_new0 (CoglXlibRenderer);
if (data == NULL)
{
data = g_slice_new0 (CoglXlibRenderer);
cogl_object_set_user_data (COGL_OBJECT (renderer),
&key,
data,
destroy_xlib_renderer_data);
}
return data;
return renderer->custom_winsys_user_data;
}
static void
@ -570,6 +556,8 @@ _cogl_xlib_renderer_disconnect (CoglRenderer *renderer)
if (!renderer->foreign_xdpy && xlib_renderer->xdpy)
XCloseDisplay (xlib_renderer->xdpy);
g_clear_pointer (&renderer->custom_winsys_user_data, _xlib_renderer_data_free);
unregister_xlib_renderer (renderer);
}

View File

@ -12,6 +12,9 @@ cdata.set('COGL_HAS_X11', have_x11)
cdata.set('COGL_HAS_X11_SUPPORT', have_x11)
cdata.set('COGL_HAS_XLIB', have_x11)
cdata.set('COGL_HAS_XLIB_SUPPORT', have_x11)
if have_native_backend
cdata.set('COGL_HAS_LIBDRM', libdrm_dep.found())
endif
cogl_defines_h = configure_file(
input: 'cogl-defines.h.meson',

View File

@ -1,5 +1,5 @@
project('mutter', 'c',
version: '3.33.1',
version: '3.33.2',
meson_version: '>= 0.50.0',
license: 'GPLv2+'
)

View File

@ -353,7 +353,7 @@ find_builtin_output (MetaInputMapper *mapper,
return panel != NULL;
}
static gboolean
static void
guess_candidates (MetaInputMapper *mapper,
MetaMapperInputInfo *input,
DeviceCandidates *info)
@ -387,15 +387,7 @@ guess_candidates (MetaInputMapper *mapper,
find_builtin_output (mapper, &info->candidates[META_MATCH_IS_BUILTIN]);
}
if (best < N_OUTPUT_MATCHES)
{
info->best = best;
return TRUE;
}
else
{
return FALSE;
}
info->best = best;
}
static void
@ -408,8 +400,7 @@ mapping_helper_add (MappingHelper *helper,
info.input = input;
if (!guess_candidates (mapper, input, &info))
return;
guess_candidates (mapper, input, &info);
for (i = 0; i < helper->device_maps->len; i++)
{

View File

@ -823,6 +823,7 @@ static void
cursor_priv_free (MetaCursorNativePrivate *cursor_priv)
{
g_hash_table_destroy (cursor_priv->gpu_states);
g_free (cursor_priv);
}
static MetaCursorNativePrivate *

View File

@ -73,11 +73,6 @@
#define EGL_DRM_MASTER_FD_EXT 0x333C
#endif
/* added in libdrm 2.4.95 */
#ifndef DRM_FORMAT_INVALID
#define DRM_FORMAT_INVALID 0
#endif
enum
{
PROP_0,
@ -252,11 +247,6 @@ static void
free_next_secondary_bo (MetaGpuKms *gpu_kms,
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state);
static gboolean
cogl_pixel_format_from_drm_format (uint32_t drm_format,
CoglPixelFormat *out_format,
CoglTextureComponents *out_components);
static MetaBackend *
backend_from_renderer_native (MetaRendererNative *renderer_native)
{
@ -2126,65 +2116,6 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
}
}
typedef struct _PixelFormatMap {
uint32_t drm_format;
CoglPixelFormat cogl_format;
CoglTextureComponents cogl_components;
} PixelFormatMap;
static const PixelFormatMap pixel_format_map[] = {
/* DRM formats are defined as little-endian, not machine endian. */
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
{ DRM_FORMAT_RGB565, COGL_PIXEL_FORMAT_RGB_565, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_ABGR8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_XBGR8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_ARGB8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_XRGB8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_BGRA8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_BGRX8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_RGBA8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_RGBX8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
#elif G_BYTE_ORDER == G_BIG_ENDIAN
/* DRM_FORMAT_RGB565 cannot be expressed. */
{ DRM_FORMAT_ABGR8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_XBGR8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_ARGB8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_XRGB8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_BGRA8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_BGRX8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_RGBA8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_RGBX8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
#else
#error "unexpected G_BYTE_ORDER"
#endif
};
static gboolean
cogl_pixel_format_from_drm_format (uint32_t drm_format,
CoglPixelFormat *out_format,
CoglTextureComponents *out_components)
{
const size_t n = G_N_ELEMENTS (pixel_format_map);
size_t i;
for (i = 0; i < n; i++)
{
if (pixel_format_map[i].drm_format == drm_format)
break;
}
if (i == n)
return FALSE;
if (out_format)
*out_format = pixel_format_map[i].cogl_format;
if (out_components)
*out_components = pixel_format_map[i].cogl_components;
return TRUE;
}
static void
copy_shared_framebuffer_cpu (CoglOnscreen *onscreen,
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state,

View File

@ -357,7 +357,6 @@ handle_host_xevent (MetaBackend *backend,
{
switch (xkb_ev->any.xkb_type)
{
case XkbNewKeyboardNotify:
case XkbMapNotify:
keymap_changed (backend);
break;

View File

@ -203,7 +203,7 @@ meta_renderer_x11_nested_create_view (MetaRenderer *renderer,
height = logical_monitor->rect.height;
}
width = roundf (width * view_scale);
height = roundf (width * view_scale);
height = roundf (height * view_scale);
fake_onscreen = create_offscreen (cogl_context, width, height);

View File

@ -692,11 +692,8 @@ meta_compositor_add_window (MetaCompositor *compositor,
{
MetaWindowActor *window_actor;
ClutterActor *window_group;
MetaDisplay *display = compositor->display;
GType window_actor_type = G_TYPE_INVALID;
meta_x11_error_trap_push (display->x11_display);
switch (window->client_type)
{
case META_WINDOW_CLIENT_TYPE_X11:
@ -724,8 +721,6 @@ meta_compositor_add_window (MetaCompositor *compositor,
*/
compositor->windows = g_list_append (compositor->windows, window_actor);
sync_actor_stacking (compositor);
meta_x11_error_trap_pop (display->x11_display);
}
void

View File

@ -55,17 +55,8 @@ meta_rectangle_free (MetaRectangle *rect)
g_free (rect);
}
GType
meta_rectangle_get_type (void)
{
static GType type_id = 0;
if (!type_id)
type_id = g_boxed_type_register_static (g_intern_static_string ("MetaRectangle"),
(GBoxedCopyFunc) meta_rectangle_copy,
(GBoxedFreeFunc) meta_rectangle_free);
return type_id;
}
G_DEFINE_BOXED_TYPE (MetaRectangle, meta_rectangle,
meta_rectangle_copy, meta_rectangle_free);
char*
meta_rectangle_to_string (const MetaRectangle *rect,

View File

@ -140,14 +140,6 @@ struct _MetaDisplay
*/
guint allow_terminal_deactivation : 1;
/* If true, server->focus_serial refers to us changing the focus; in
* this case, we can ignore focus events that have exactly focus_serial,
* since we take care to make another request immediately afterwards.
* But if focus is being changed by another client, we have to accept
* multiple events with the same serial.
*/
guint focused_by_us : 1;
/*< private-ish >*/
GHashTable *stamps;
GHashTable *wayland_windows;
@ -203,10 +195,6 @@ struct _MetaDisplay
MetaEdgeResistanceData *grab_edge_resistance_data;
unsigned int grab_last_user_action_was_snap;
/* we use property updates as sentinels for certain window focus events
* to avoid some race conditions on EnterNotify events
*/
int sentinel_counter;
int grab_resize_timeout_id;
MetaKeyBindingManager key_binding_manager;
@ -363,10 +351,6 @@ gboolean meta_grab_op_is_resizing (MetaGrabOp op);
gboolean meta_grab_op_is_mouse (MetaGrabOp op);
gboolean meta_grab_op_is_keyboard (MetaGrabOp op);
void meta_display_increment_focus_sentinel (MetaDisplay *display);
void meta_display_decrement_focus_sentinel (MetaDisplay *display);
gboolean meta_display_focus_sentinel_clear (MetaDisplay *display);
void meta_display_queue_autoraise_callback (MetaDisplay *display,
MetaWindow *window);
void meta_display_remove_autoraise_callback (MetaDisplay *display);
@ -379,10 +363,7 @@ gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display);
void meta_display_sync_wayland_input_focus (MetaDisplay *display);
void meta_display_update_focus_window (MetaDisplay *display,
MetaWindow *window,
Window xwindow,
gulong serial,
gboolean focused_by_us);
MetaWindow *window);
void meta_display_sanity_check_timestamps (MetaDisplay *display,
guint32 timestamp);
@ -446,4 +427,8 @@ MetaWindow *meta_display_get_window_from_id (MetaDisplay *display,
uint64_t window_id);
uint64_t meta_display_generate_window_id (MetaDisplay *display);
gboolean meta_display_init_x11 (MetaDisplay *display,
GError **error);
void meta_display_shutdown_x11 (MetaDisplay *display);
#endif

View File

@ -49,6 +49,7 @@
#include "backends/meta-logical-monitor.h"
#include "backends/meta-stage-private.h"
#include "backends/x11/meta-backend-x11.h"
#include "backends/x11/cm/meta-backend-x11-cm.h"
#include "clutter/x11/clutter-x11.h"
#include "core/bell.h"
#include "core/boxes-private.h"
@ -630,6 +631,39 @@ on_ui_scaling_factor_changed (MetaSettings *settings,
meta_display_reload_cursor (display);
}
gboolean
meta_display_init_x11 (MetaDisplay *display,
GError **error)
{
MetaX11Display *x11_display;
g_assert (display->x11_display == NULL);
x11_display = meta_x11_display_new (display, error);
if (!x11_display)
return FALSE;
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);
return TRUE;
}
void
meta_display_shutdown_x11 (MetaDisplay *display)
{
if (!display->x11_display)
return;
g_signal_emit (display, display_signals[X11_DISPLAY_CLOSING], 0);
g_object_run_dispose (G_OBJECT (display->x11_display));
g_clear_object (&display->x11_display);
}
/**
* meta_display_open:
*
@ -645,7 +679,6 @@ meta_display_open (void)
{
GError *error = NULL;
MetaDisplay *display;
MetaX11Display *x11_display;
int i;
guint32 timestamp;
Window old_active_xwindow = None;
@ -683,7 +716,6 @@ meta_display_open (void)
}
display->current_time = META_CURRENT_TIME;
display->sentinel_counter = 0;
display->grab_resize_timeout_id = 0;
display->grab_have_keyboard = FALSE;
@ -693,7 +725,7 @@ meta_display_open (void)
display->grab_tile_mode = META_TILE_NONE;
display->grab_tile_monitor_number = -1;
display->grab_edge_resistance_data = NULL;
meta_display_cleanup_edges (display);
meta_display_init_keys (display);
@ -730,10 +762,8 @@ meta_display_open (void)
if (meta_should_autostart_x11_display ())
{
x11_display = meta_x11_display_new (display, &error);
g_assert (x11_display != NULL); /* Required, for now */
display->x11_display = x11_display;
g_signal_emit (display, display_signals[X11_DISPLAY_OPENED], 0);
if (!meta_display_init_x11 (display, &error))
g_error ("Failed to start Xwayland: %s", error->message);
timestamp = display->x11_display->timestamp;
}
@ -779,10 +809,12 @@ meta_display_open (void)
if (old_active_window)
meta_window_focus (old_active_window, timestamp);
else
meta_x11_display_focus_the_no_focus_window (display->x11_display, timestamp);
meta_display_unset_input_focus (display, timestamp);
}
else
{
meta_display_unset_input_focus (display, timestamp);
}
else if (display->x11_display)
meta_x11_display_focus_the_no_focus_window (display->x11_display, timestamp);
meta_idle_monitor_init_dbus ();
@ -924,7 +956,7 @@ meta_display_close (MetaDisplay *display,
g_clear_object (&display->gesture_tracker);
g_clear_pointer (&display->stack, meta_stack_free);
g_clear_object (&display->stack);
g_clear_pointer (&display->stack_tracker,
meta_stack_tracker_free);
@ -953,12 +985,7 @@ meta_display_close (MetaDisplay *display,
if (display->compositor)
meta_compositor_destroy (display->compositor);
if (display->x11_display)
{
g_signal_emit (display, display_signals[X11_DISPLAY_CLOSING], 0);
g_object_run_dispose (G_OBJECT (display->x11_display));
g_clear_object (&display->x11_display);
}
meta_display_shutdown_x11 (display);
meta_display_shutdown_keys (display);
@ -1238,16 +1265,9 @@ meta_display_sync_wayland_input_focus (MetaDisplay *display)
void
meta_display_update_focus_window (MetaDisplay *display,
MetaWindow *window,
Window xwindow,
gulong serial,
gboolean focused_by_us)
MetaWindow *window)
{
display->x11_display->focus_serial = serial;
display->focused_by_us = focused_by_us;
if (display->x11_display->focus_xwindow == xwindow &&
display->focus_window == window)
if (display->focus_window == window)
return;
if (display->focus_window)
@ -1264,28 +1284,25 @@ meta_display_update_focus_window (MetaDisplay *display,
*/
previous = display->focus_window;
display->focus_window = NULL;
display->x11_display->focus_xwindow = None;
meta_window_set_focused_internal (previous, FALSE);
}
display->focus_window = window;
display->x11_display->focus_xwindow = xwindow;
if (display->focus_window)
{
meta_topic (META_DEBUG_FOCUS, "* Focus --> %s with serial %lu\n",
display->focus_window->desc, serial);
meta_topic (META_DEBUG_FOCUS, "* Focus --> %s\n",
display->focus_window->desc);
meta_window_set_focused_internal (display->focus_window, TRUE);
}
else
meta_topic (META_DEBUG_FOCUS, "* Focus --> NULL with serial %lu\n", serial);
meta_topic (META_DEBUG_FOCUS, "* Focus --> NULL\n");
if (meta_is_wayland_compositor ())
meta_display_sync_wayland_input_focus (display);
g_object_notify (G_OBJECT (display), "focus-window");
meta_x11_display_update_active_window_hint (display->x11_display);
}
gboolean
@ -1317,6 +1334,51 @@ meta_display_timestamp_too_old (MetaDisplay *display,
return FALSE;
}
void
meta_display_set_input_focus (MetaDisplay *display,
MetaWindow *window,
gboolean focus_frame,
guint32 timestamp)
{
if (meta_display_timestamp_too_old (display, &timestamp))
return;
if (display->x11_display)
{
MetaX11Display *x11_display = display->x11_display;
Window xwindow;
gulong serial;
meta_x11_error_trap_push (x11_display);
if (window)
xwindow = focus_frame ? window->frame->xwindow : window->xwindow;
else
xwindow = x11_display->no_focus_window;
meta_x11_display_set_input_focus (x11_display, xwindow, timestamp);
serial = XNextRequest (x11_display->xdisplay);
meta_x11_display_update_focus_window (x11_display, xwindow, serial, TRUE);
meta_x11_error_trap_pop (display->x11_display);
}
meta_display_update_focus_window (display, window);
display->last_focus_time = timestamp;
if (window == NULL || window != display->autoraise_window)
meta_display_remove_autoraise_callback (display);
}
void
meta_display_unset_input_focus (MetaDisplay *display,
guint32 timestamp)
{
meta_display_set_input_focus (display, NULL, FALSE, timestamp);
}
void
meta_display_register_wayland_window (MetaDisplay *display,
MetaWindow *window)
@ -1678,14 +1740,17 @@ meta_display_begin_grab_op (MetaDisplay *display,
if (pointer_already_grabbed)
display->grab_have_pointer = TRUE;
/* Since grab operations often happen as a result of implicit
* pointer operations on the display X11 connection, we need
* to ungrab here to ensure that the backend's X11 can take
* the device grab. */
XIUngrabDevice (display->x11_display->xdisplay,
META_VIRTUAL_CORE_POINTER_ID,
timestamp);
XSync (display->x11_display->xdisplay, False);
if (META_IS_BACKEND_X11 (meta_get_backend ()) && display->x11_display)
{
/* Since grab operations often happen as a result of implicit
* pointer operations on the display X11 connection, we need
* to ungrab here to ensure that the backend's X11 can take
* the device grab. */
XIUngrabDevice (display->x11_display->xdisplay,
META_VIRTUAL_CORE_POINTER_ID,
timestamp);
XSync (display->x11_display->xdisplay, False);
}
if (meta_backend_grab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp))
display->grab_have_pointer = TRUE;
@ -2490,37 +2555,6 @@ prefs_changed_callback (MetaPreference pref,
}
}
void
meta_display_increment_focus_sentinel (MetaDisplay *display)
{
unsigned long data[1];
data[0] = meta_display_get_current_time (display);
XChangeProperty (display->x11_display->xdisplay,
display->x11_display->xroot,
display->x11_display->atom__MUTTER_SENTINEL,
XA_CARDINAL,
32, PropModeReplace, (guchar*) data, 1);
display->sentinel_counter += 1;
}
void
meta_display_decrement_focus_sentinel (MetaDisplay *display)
{
display->sentinel_counter -= 1;
if (display->sentinel_counter < 0)
display->sentinel_counter = 0;
}
gboolean
meta_display_focus_sentinel_clear (MetaDisplay *display)
{
return (display->sentinel_counter == 0);
}
void
meta_display_sanity_check_timestamps (MetaDisplay *display,
guint32 timestamp)
@ -2626,13 +2660,14 @@ meta_display_supports_extended_barriers (MetaDisplay *display)
return TRUE;
#endif
if (META_IS_BACKEND_X11 (meta_get_backend ()))
if (META_IS_BACKEND_X11_CM (meta_get_backend ()))
{
return (META_X11_DISPLAY_HAS_XINPUT_23 (display->x11_display) &&
!meta_is_wayland_compositor());
if (meta_is_wayland_compositor())
return FALSE;
return META_X11_DISPLAY_HAS_XINPUT_23 (display->x11_display);
}
g_assert_not_reached ();
return FALSE;
}

View File

@ -606,22 +606,6 @@ meta_init (void)
meta_fatal ("Can't specify both SM save file and SM client id\n");
meta_main_loop = g_main_loop_new (NULL, FALSE);
/*
* We need to make sure the first client connecting to the X server
* (e.g. Xwayland started from meta_wayland_init() above) is a permanent one,
* so prepare the GDK X11 connection now already. Without doing this, if
* there are any functionality that relies on X11 after here before
* meta_display_open(), the X server will terminate itself when such a client
* disconnects before the permanent GDK client connects.
*/
if (meta_should_autostart_x11_display ())
{
GError *error = NULL;
if (!meta_x11_init_gdk_display (&error))
g_error ("Failed to open X11 display: %s", error->message);
}
}
/**

View File

@ -600,8 +600,6 @@ meta_workspace_manager_calc_workspace_layout (MetaWorkspaceManager *workspace_ma
grid = g_new (int, grid_area);
current_row = -1;
current_col = -1;
i = 0;
switch (workspace_manager->starting_corner)

View File

@ -29,18 +29,13 @@
#include "core/stack.h"
#include <X11/Xatom.h>
#include "backends/meta-logical-monitor.h"
#include "core/frame.h"
#include "core/meta-workspace-manager-private.h"
#include "core/window-private.h"
#include "meta/group.h"
#include "meta/meta-x11-errors.h"
#include "meta/prefs.h"
#include "meta/workspace.h"
#include "x11/group-private.h"
#include "x11/meta-x11-display-private.h"
#define WINDOW_HAS_TRANSIENT_TYPE(w) \
(w->type == META_WINDOW_DIALOG || \
@ -52,51 +47,141 @@
#define WINDOW_TRANSIENT_FOR_WHOLE_GROUP(w) \
(WINDOW_HAS_TRANSIENT_TYPE (w) && w->transient_for == NULL)
static void stack_sync_to_xserver (MetaStack *stack);
static void meta_window_set_stack_position_no_sync (MetaWindow *window,
int position);
static void stack_do_window_deletions (MetaStack *stack);
static void stack_do_window_additions (MetaStack *stack);
static void stack_do_relayer (MetaStack *stack);
static void stack_do_constrain (MetaStack *stack);
static void stack_do_resort (MetaStack *stack);
static void stack_ensure_sorted (MetaStack *stack);
enum
{
PROP_DISPLAY = 1,
N_PROPS
};
enum
{
CHANGED,
WINDOW_ADDED,
WINDOW_REMOVED,
N_SIGNALS
};
static GParamSpec *pspecs[N_PROPS] = { 0 };
static guint signals[N_SIGNALS] = { 0 };
G_DEFINE_TYPE (MetaStack, meta_stack, G_TYPE_OBJECT)
static void
meta_stack_init (MetaStack *stack)
{
}
static void
meta_stack_finalize (GObject *object)
{
MetaStack *stack = META_STACK (object);
g_list_free (stack->sorted);
G_OBJECT_CLASS (meta_stack_parent_class)->finalize (object);
}
static void
meta_stack_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaStack *stack = META_STACK (object);
switch (prop_id)
{
case PROP_DISPLAY:
stack->display = g_value_get_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
meta_stack_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaStack *stack = META_STACK (object);
switch (prop_id)
{
case PROP_DISPLAY:
g_value_set_object (value, stack->display);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
meta_stack_class_init (MetaStackClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->set_property = meta_stack_set_property;
object_class->get_property = meta_stack_get_property;
object_class->finalize = meta_stack_finalize;
signals[CHANGED] =
g_signal_new ("changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL, NULL,
G_TYPE_NONE, 0);
signals[WINDOW_ADDED] =
g_signal_new ("window-added",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, META_TYPE_WINDOW);
signals[WINDOW_REMOVED] =
g_signal_new ("window-removed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, META_TYPE_WINDOW);
pspecs[PROP_DISPLAY] =
g_param_spec_object ("display",
"Display",
"Display",
META_TYPE_DISPLAY,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_properties (object_class, N_PROPS, pspecs);
}
MetaStack *
meta_stack_new (MetaDisplay *display)
{
MetaStack *stack;
stack = g_new (MetaStack, 1);
stack->display = display;
stack->xwindows = g_array_new (FALSE, FALSE, sizeof (Window));
stack->sorted = NULL;
stack->added = NULL;
stack->removed = NULL;
stack->freeze_count = 0;
stack->n_positions = 0;
stack->need_resort = FALSE;
stack->need_relayer = FALSE;
stack->need_constrain = FALSE;
return stack;
return g_object_new (META_TYPE_STACK,
"display", display,
NULL);
}
void
meta_stack_free (MetaStack *stack)
static void
meta_stack_changed (MetaStack *stack)
{
g_array_free (stack->xwindows, TRUE);
/* Bail out if frozen */
if (stack->freeze_count > 0)
return;
g_list_free (stack->sorted);
g_list_free (stack->added);
g_list_free (stack->removed);
g_free (stack);
stack_ensure_sorted (stack);
g_signal_emit (stack, signals[CHANGED], 0);
}
void
@ -112,7 +197,12 @@ meta_stack_add (MetaStack *stack,
if (meta_window_is_in_stack (window))
meta_bug ("Window %s had stack position already\n", window->desc);
stack->added = g_list_prepend (stack->added, window);
stack->sorted = g_list_prepend (stack->sorted, window);
stack->need_resort = TRUE; /* may not be needed as we add to top */
stack->need_constrain = TRUE;
stack->need_relayer = TRUE;
g_signal_emit (stack, signals[WINDOW_ADDED], 0, window);
window->stack_position = stack->n_positions;
stack->n_positions += 1;
@ -120,7 +210,7 @@ meta_stack_add (MetaStack *stack,
"Window %s has stack_position initialized to %d\n",
window->desc, window->stack_position);
stack_sync_to_xserver (stack);
meta_stack_changed (stack);
meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
}
@ -140,25 +230,11 @@ meta_stack_remove (MetaStack *stack,
window->stack_position = -1;
stack->n_positions -= 1;
/* We don't know if it's been moved from "added" to "stack" yet */
stack->added = g_list_remove (stack->added, window);
stack->sorted = g_list_remove (stack->sorted, window);
/* stack->removed is only used to update stack->xwindows */
if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
{
/* Remember the window ID to remove it from the stack array.
* The macro is safe to use: Window is guaranteed to be 32 bits, and
* GUINT_TO_POINTER says it only works on 32 bits.
*/
stack->removed = g_list_prepend (stack->removed,
GUINT_TO_POINTER (window->xwindow));
if (window->frame)
stack->removed = g_list_prepend (stack->removed,
GUINT_TO_POINTER (window->frame->xwindow));
}
g_signal_emit (stack, signals[WINDOW_REMOVED], 0, window);
stack_sync_to_xserver (stack);
meta_stack_changed (stack);
meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
}
@ -169,7 +245,7 @@ meta_stack_update_layer (MetaStack *stack,
MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
stack->need_relayer = TRUE;
stack_sync_to_xserver (stack);
meta_stack_changed (stack);
meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
}
@ -180,7 +256,7 @@ meta_stack_update_transient (MetaStack *stack,
MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
stack->need_constrain = TRUE;
stack_sync_to_xserver (stack);
meta_stack_changed (stack);
meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
}
@ -210,7 +286,7 @@ meta_stack_raise (MetaStack *stack,
meta_window_set_stack_position_no_sync (window, max_stack_position);
stack_sync_to_xserver (stack);
meta_stack_changed (stack);
meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
}
@ -239,7 +315,7 @@ meta_stack_lower (MetaStack *stack,
meta_window_set_stack_position_no_sync (window, min_stack_position);
stack_sync_to_xserver (stack);
meta_stack_changed (stack);
meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
}
@ -255,7 +331,7 @@ meta_stack_thaw (MetaStack *stack)
g_return_if_fail (stack->freeze_count > 0);
stack->freeze_count -= 1;
stack_sync_to_xserver (stack);
meta_stack_changed (stack);
meta_stack_update_window_tile_matches (stack, NULL);
}
@ -771,99 +847,6 @@ apply_constraints (Constraint **constraints,
g_slist_free (heads);
}
/**
* stack_do_window_deletions:
*
* Go through "deleted" and take the matching windows
* out of "windows".
*/
static void
stack_do_window_deletions (MetaStack *stack)
{
/* Do removals before adds, with paranoid idea that we might re-add
* the same window IDs.
*/
GList *tmp;
int i;
tmp = stack->removed;
while (tmp != NULL)
{
Window xwindow;
xwindow = GPOINTER_TO_UINT (tmp->data);
/* We go from the end figuring removals are more
* likely to be recent.
*/
i = stack->xwindows->len;
while (i > 0)
{
--i;
/* there's no guarantee we'll actually find windows to
* remove, e.g. the same xwindow could have been
* added/removed before we ever synced, and we put
* both the window->xwindow and window->frame->xwindow
* in the removal list.
*/
if (xwindow == g_array_index (stack->xwindows, Window, i))
{
g_array_remove_index (stack->xwindows, i);
goto next;
}
}
next:
tmp = tmp->next;
}
g_list_free (stack->removed);
stack->removed = NULL;
}
static void
stack_do_window_additions (MetaStack *stack)
{
GList *tmp;
gint n_added;
n_added = g_list_length (stack->added);
if (n_added > 0)
{
meta_topic (META_DEBUG_STACK,
"Adding %d windows to sorted list\n",
n_added);
/* stack->added has the most recent additions at the
* front of the list, so we need to reverse it
*/
stack->added = g_list_reverse (stack->added);
tmp = stack->added;
while (tmp != NULL)
{
MetaWindow *w;
w = tmp->data;
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
g_array_append_val (stack->xwindows, w->xwindow);
/* add to the main list */
stack->sorted = g_list_prepend (stack->sorted, w);
tmp = tmp->next;
}
stack->need_resort = TRUE; /* may not be needed as we add to top */
stack->need_constrain = TRUE;
stack->need_relayer = TRUE;
}
g_list_free (stack->added);
stack->added = NULL;
}
/**
* stack_do_relayer:
*
@ -981,131 +964,11 @@ stack_do_resort (MetaStack *stack)
static void
stack_ensure_sorted (MetaStack *stack)
{
stack_do_window_deletions (stack);
stack_do_window_additions (stack);
stack_do_relayer (stack);
stack_do_constrain (stack);
stack_do_resort (stack);
}
/**
* stack_sync_to_server:
*
* Order the windows on the X server to be the same as in our structure.
* We do this using XRestackWindows if we don't know the previous order,
* or XConfigureWindow on a few particular windows if we do and can figure
* out the minimum set of changes. After that, we set __NET_CLIENT_LIST
* and __NET_CLIENT_LIST_STACKING.
*
* FIXME: Now that we have a good view of the stacking order on the server
* with MetaStackTracker it should be possible to do a simpler and better
* job of computing the minimal set of stacking requests needed.
*/
static void
stack_sync_to_xserver (MetaStack *stack)
{
GArray *x11_stacked;
GArray *all_root_children_stacked; /* wayland OR x11 */
GList *tmp;
GArray *hidden_stack_ids;
/* Bail out if frozen */
if (stack->freeze_count > 0)
return;
meta_topic (META_DEBUG_STACK, "Syncing window stack to server\n");
stack_ensure_sorted (stack);
/* Create stacked xwindow arrays, in bottom-to-top order
*/
x11_stacked = g_array_new (FALSE, FALSE, sizeof (Window));
all_root_children_stacked = g_array_new (FALSE, FALSE, sizeof (guint64));
hidden_stack_ids = g_array_new (FALSE, FALSE, sizeof (guint64));
meta_topic (META_DEBUG_STACK, "Bottom to top: ");
meta_push_no_msg_prefix ();
for (tmp = g_list_last(stack->sorted); tmp != NULL; tmp = tmp->prev)
{
MetaWindow *w = tmp->data;
guint64 top_level_window;
guint64 stack_id;
if (w->unmanaging)
continue;
meta_topic (META_DEBUG_STACK, "%u:%d - %s ",
w->layer, w->stack_position, w->desc);
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
g_array_append_val (x11_stacked, w->xwindow);
if (w->frame)
top_level_window = w->frame->xwindow;
else
top_level_window = w->xwindow;
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
stack_id = top_level_window;
else
stack_id = w->stamp;
/* We don't restack hidden windows along with the rest, though they are
* reflected in the _NET hints. Hidden windows all get pushed below
* the screens fullscreen guard_window. */
if (w->hidden)
{
g_array_append_val (hidden_stack_ids, stack_id);
continue;
}
g_array_append_val (all_root_children_stacked, stack_id);
}
meta_topic (META_DEBUG_STACK, "\n");
meta_pop_no_msg_prefix ();
/* The screen guard window sits above all hidden windows and acts as
* a barrier to input reaching these windows. */
guint64 guard_window_id = stack->display->x11_display->guard_window;
g_array_append_val (hidden_stack_ids, guard_window_id);
/* Sync to server */
meta_topic (META_DEBUG_STACK, "Restacking %u windows\n",
all_root_children_stacked->len);
meta_stack_tracker_restack_managed (stack->display->stack_tracker,
(guint64 *)all_root_children_stacked->data,
all_root_children_stacked->len);
meta_stack_tracker_restack_at_bottom (stack->display->stack_tracker,
(guint64 *)hidden_stack_ids->data,
hidden_stack_ids->len);
/* Sync _NET_CLIENT_LIST and _NET_CLIENT_LIST_STACKING */
XChangeProperty (stack->display->x11_display->xdisplay,
stack->display->x11_display->xroot,
stack->display->x11_display->atom__NET_CLIENT_LIST,
XA_WINDOW,
32, PropModeReplace,
(unsigned char *)stack->xwindows->data,
stack->xwindows->len);
XChangeProperty (stack->display->x11_display->xdisplay,
stack->display->x11_display->xroot,
stack->display->x11_display->atom__NET_CLIENT_LIST_STACKING,
XA_WINDOW,
32, PropModeReplace,
(unsigned char *)x11_stacked->data,
x11_stacked->len);
g_array_free (x11_stacked, TRUE);
g_array_free (hidden_stack_ids, TRUE);
g_array_free (all_root_children_stacked, TRUE);
}
MetaWindow*
meta_stack_get_top (MetaStack *stack)
{
@ -1415,7 +1278,7 @@ meta_stack_set_positions (MetaStack *stack,
meta_topic (META_DEBUG_STACK,
"Reset the stack positions of (nearly) all windows\n");
stack_sync_to_xserver (stack);
meta_stack_changed (stack);
meta_stack_update_window_tile_matches (stack, NULL);
}
@ -1480,7 +1343,7 @@ meta_window_set_stack_position (MetaWindow *window,
MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
meta_window_set_stack_position_no_sync (window, position);
stack_sync_to_xserver (window->display->stack);
meta_stack_changed (window->display->stack);
meta_stack_update_window_tile_matches (window->display->stack,
workspace_manager->active_workspace);
}

View File

@ -51,38 +51,14 @@
*/
struct _MetaStack
{
GObject parent;
/** The MetaDisplay containing this stack. */
MetaDisplay *display;
/**
* A sequence of all the Windows (X handles, not MetaWindows) of the windows
* we manage, sorted in order. Suitable to be passed into _NET_CLIENT_LIST.
*/
GArray *xwindows;
/** The MetaWindows of the windows we manage, sorted in order. */
GList *sorted;
/**
* MetaWindows waiting to be added to the "sorted" and "windows" list, after
* being added by meta_stack_add() and before being assimilated by
* stack_ensure_sorted().
*
* The order of the elements in this list is not important; what is important
* is the stack_position element of each window.
*/
GList *added;
/**
* Windows (X handles, not MetaWindows) waiting to be removed from the
* "windows" list, after being removed by meta_stack_remove() and before
* being assimilated by stack_ensure_sorted(). (We already removed them
* from the "sorted" list.)
*
* The order of the elements in this list is not important.
*/
GList *removed;
/**
* If this is zero, the local stack oughtn't to be brought up to date with
* the X server's stack, because it is in the middle of being updated.
@ -121,6 +97,9 @@ struct _MetaStack
unsigned int need_constrain : 1;
};
#define META_TYPE_STACK (meta_stack_get_type ())
G_DECLARE_FINAL_TYPE (MetaStack, meta_stack, META, STACK, GObject)
/**
* meta_stack_new:
* @display: The MetaDisplay which will be the parent of this stack.
@ -131,14 +110,6 @@ struct _MetaStack
*/
MetaStack *meta_stack_new (MetaDisplay *display);
/**
* meta_stack_free:
* @stack: The stack to destroy.
*
* Destroys and frees a MetaStack.
*/
void meta_stack_free (MetaStack *stack);
/**
* meta_stack_add:
* @stack: The stack to add it to

View File

@ -581,6 +581,9 @@ struct _MetaWindowClass
gboolean (*is_stackable) (MetaWindow *window);
gboolean (*can_ping) (MetaWindow *window);
gboolean (*are_updates_frozen) (MetaWindow *window);
void (* map) (MetaWindow *window);
void (* unmap) (MetaWindow *window);
};
/* These differ from window->has_foo_func in that they consider

View File

@ -809,17 +809,10 @@ sync_client_window_mapped (MetaWindow *window)
window->mapped = should_be_mapped;
meta_x11_error_trap_push (window->display->x11_display);
if (should_be_mapped)
{
XMapWindow (window->display->x11_display->xdisplay, window->xwindow);
}
if (window->mapped)
META_WINDOW_GET_CLASS (window)->map (window);
else
{
XUnmapWindow (window->display->x11_display->xdisplay, window->xwindow);
window->unmaps_pending ++;
}
meta_x11_error_trap_pop (window->display->x11_display);
META_WINDOW_GET_CLASS (window)->unmap (window);
}
static gboolean
@ -1939,9 +1932,10 @@ idle_calc_showing (gpointer data)
while (tmp != NULL)
{
MetaWindow *window = tmp->data;
MetaDisplay *display = window->display;
if (!window->display->mouse_mode)
meta_display_increment_focus_sentinel (window->display);
if (display->x11_display && !display->mouse_mode)
meta_x11_display_increment_focus_sentinel (display->x11_display);
tmp = tmp->next;
}
@ -2411,6 +2405,7 @@ meta_window_show (MetaWindow *window)
gboolean needs_stacking_adjustment;
MetaWindow *focus_window;
gboolean notify_demands_attention = FALSE;
MetaDisplay *display = window->display;
meta_topic (META_DEBUG_WINDOW_STATE,
"Showing window %s, shaded: %d iconic: %d placed: %d\n",
@ -2577,7 +2572,7 @@ meta_window_show (MetaWindow *window)
meta_window_focus (window, timestamp);
}
else
else if (display->x11_display)
{
/* Prevent EnterNotify events in sloppy/mouse focus from
* erroneously focusing the window that had been denied
@ -2585,7 +2580,7 @@ meta_window_show (MetaWindow *window)
* ideas for a better way to accomplish the same thing, but
* they're more involved so do it this way for now.
*/
meta_display_increment_focus_sentinel (window->display);
meta_x11_display_increment_focus_sentinel (display->x11_display);
}
}
@ -3812,13 +3807,13 @@ maybe_move_attached_window (MetaWindow *window,
void *data)
{
if (window->hidden)
return FALSE;
return G_SOURCE_CONTINUE;
if (meta_window_is_attached_dialog (window) ||
meta_window_get_placement_rule (window))
meta_window_reposition (window);
return FALSE;
return G_SOURCE_CONTINUE;
}
/**
@ -5378,50 +5373,6 @@ redraw_icon (MetaWindow *window)
meta_frame_queue_draw (window->frame);
}
static cairo_surface_t *
load_default_window_icon (int size)
{
GtkIconTheme *theme = gtk_icon_theme_get_default ();
g_autoptr (GdkPixbuf) pixbuf = NULL;
const char *icon_name;
if (gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME))
icon_name = META_DEFAULT_ICON_NAME;
else
icon_name = "image-missing";
pixbuf = gtk_icon_theme_load_icon (theme, icon_name, size, 0, NULL);
return gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, NULL);
}
static cairo_surface_t *
get_default_window_icon (void)
{
static cairo_surface_t *default_icon = NULL;
if (default_icon == NULL)
{
default_icon = load_default_window_icon (META_ICON_WIDTH);
g_assert (default_icon);
}
return cairo_surface_reference (default_icon);
}
static cairo_surface_t *
get_default_mini_icon (void)
{
static cairo_surface_t *default_icon = NULL;
if (default_icon == NULL)
{
default_icon = load_default_window_icon (META_MINI_ICON_WIDTH);
g_assert (default_icon);
}
return cairo_surface_reference (default_icon);
}
static void
meta_window_update_icon_now (MetaWindow *window,
gboolean force)
@ -5438,17 +5389,11 @@ meta_window_update_icon_now (MetaWindow *window,
{
if (window->icon)
cairo_surface_destroy (window->icon);
if (icon)
window->icon = icon;
else
window->icon = get_default_window_icon ();
window->icon = icon;
if (window->mini_icon)
cairo_surface_destroy (window->mini_icon);
if (mini_icon)
window->mini_icon = mini_icon;
else
window->mini_icon = get_default_mini_icon ();
window->mini_icon = mini_icon;
g_object_freeze_notify (G_OBJECT (window));
g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_ICON]);
@ -5457,9 +5402,6 @@ meta_window_update_icon_now (MetaWindow *window,
redraw_icon (window);
}
g_assert (window->icon);
g_assert (window->mini_icon);
}
static gboolean
@ -8146,8 +8088,7 @@ mouse_mode_focus (MetaWindow *window,
"Unsetting focus from %s due to mouse entering "
"the DESKTOP window\n",
display->focus_window->desc);
meta_x11_display_focus_the_no_focus_window (display->x11_display,
timestamp);
meta_display_unset_input_focus (display, timestamp);
}
}
}

View File

@ -1308,8 +1308,7 @@ meta_workspace_focus_default_window (MetaWorkspace *workspace,
meta_topic (META_DEBUG_FOCUS,
"Setting focus to no_focus_window, since no valid "
"window to focus found.\n");
meta_x11_display_focus_the_no_focus_window (workspace->display->x11_display,
timestamp);
meta_display_unset_input_focus (workspace->display, timestamp);
}
}
}
@ -1381,8 +1380,7 @@ focus_ancestor_or_top_window (MetaWorkspace *workspace,
else
{
meta_topic (META_DEBUG_FOCUS, "No MRU window to focus found; focusing no_focus_window.\n");
meta_x11_display_focus_the_no_focus_window (workspace->display->x11_display,
timestamp);
meta_display_unset_input_focus (workspace->display, timestamp);
}
}

View File

@ -392,6 +392,8 @@ mutter_sources = [
'x11/meta-x11-selection-input-stream-private.h',
'x11/meta-x11-selection-output-stream.c',
'x11/meta-x11-selection-output-stream-private.h',
'x11/meta-x11-stack.c',
'x11/meta-x11-stack-private.h',
'x11/mutter-Xatomtype.h',
'x11/session.c',
'x11/session.h',

View File

@ -297,4 +297,13 @@ MetaSoundPlayer * meta_display_get_sound_player (MetaDisplay *display);
META_EXPORT
MetaSelection * meta_display_get_selection (MetaDisplay *display);
META_EXPORT
void meta_display_set_input_focus (MetaDisplay *display,
MetaWindow *window,
gboolean focus_frame,
guint32 timestamp);
META_EXPORT
void meta_display_unset_input_focus (MetaDisplay *display,
guint32 timestamp);
#endif

View File

@ -63,27 +63,4 @@ META_EXPORT
gboolean meta_x11_display_xwindow_is_a_no_focus_window (MetaX11Display *x11_display,
Window xwindow);
/* meta_x11_display_set_input_focus_window is like XSetInputFocus, except
* that (a) it can't detect timestamps later than the current time,
* since Mutter isn't part of the XServer, and thus gives erroneous
* behavior in this circumstance (so don't do it), (b) it uses
* display->last_focus_time since we don't have access to the true
* Xserver one, (c) it makes use of display->user_time since checking
* whether a window should be allowed to be focused should depend
* on user_time events (see bug 167358, comment 15 in particular)
*/
META_EXPORT
void meta_x11_display_set_input_focus_window (MetaX11Display *x11_display,
MetaWindow *window,
gboolean focus_frame,
guint32 timestamp);
/* meta_x11_display_focus_the_no_focus_window is called when the
* designated no_focus_window should be focused, but is otherwise the
* same as meta_display_set_input_focus_window
*/
META_EXPORT
void meta_x11_display_focus_the_no_focus_window (MetaX11Display *x11_display,
guint32 timestamp);
#endif /* META_X11_DISPLAY_H */

View File

@ -32,6 +32,7 @@
#include "wayland/meta-wayland.h"
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
#define FRAME_WARNING "Frame has assigned frame counter but no frame drawn time"
static gboolean
run_tests (gpointer data)
@ -40,6 +41,8 @@ run_tests (gpointer data)
MetaSettings *settings = meta_backend_get_settings (backend);
gboolean ret;
g_test_log_set_fatal_handler (NULL, NULL);
meta_settings_override_experimental_features (settings);
meta_settings_enable_experimental_feature (
@ -53,6 +56,20 @@ run_tests (gpointer data)
return FALSE;
}
static gboolean
ignore_frame_counter_warning (const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message,
gpointer user_data)
{
if ((log_level & G_LOG_LEVEL_WARNING) &&
g_strcmp0 (log_domain, "mutter") == 0 &&
g_str_has_suffix (message, FRAME_WARNING))
return FALSE;
return TRUE;
}
static void
meta_test_headless_start (void)
{
@ -193,6 +210,8 @@ main (int argc, char *argv[])
meta_init ();
meta_register_with_session ();
g_test_log_set_fatal_handler (ignore_frame_counter_warning, NULL);
g_idle_add (run_tests, NULL);
return meta_run ();

View File

@ -385,6 +385,9 @@ test_case_do (TestCase *test,
argc == 3 ? argv[2] : NULL,
NULL))
return FALSE;
if (!test_client_wait (client, error))
return FALSE;
}
else if (strcmp (argv[0], "set_parent") == 0 ||
strcmp (argv[0], "set_parent_exported") == 0)

View File

@ -31,8 +31,6 @@
#include "meta/prefs.h"
#include "ui/frames.h"
#define DEBUG_FILL_STRUCT(s) memset ((s), 0xef, sizeof (*(s)))
static void scale_border (GtkBorder *border, double factor);
static MetaFrameLayout *
@ -58,7 +56,6 @@ meta_frame_layout_free (MetaFrameLayout *layout)
{
g_return_if_fail (layout != NULL);
DEBUG_FILL_STRUCT (layout);
g_free (layout);
}
@ -967,7 +964,6 @@ meta_theme_free (MetaTheme *theme)
if (theme->layouts[i])
meta_frame_layout_free (theme->layouts[i]);
DEBUG_FILL_STRUCT (theme);
g_free (theme);
}

View File

@ -43,10 +43,6 @@
#include "linux-dmabuf-unstable-v1-server-protocol.h"
#ifndef DRM_FORMAT_MOD_INVALID
#define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1)
#endif
#define META_WAYLAND_DMA_BUF_MAX_FDS 4
struct _MetaWaylandDmaBufBuffer
@ -84,28 +80,15 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer,
if (buffer->dma_buf.texture)
return TRUE;
switch (dma_buf->drm_format)
/*
* NOTE: The cogl_format here is only used for texture color channel
* swizzling as compared to COGL_PIXEL_FORMAT_ARGB. It is *not* used
* for accessing the buffer memory. EGL will access the buffer
* memory according to the DRM fourcc code. Cogl will not mmap
* and access the buffer memory at all.
*/
if (!cogl_pixel_format_from_drm_format (dma_buf->drm_format, &cogl_format, NULL))
{
/*
* NOTE: The cogl_format here is only used for texture color channel
* swizzling as compared to COGL_PIXEL_FORMAT_ARGB. It is *not* used
* for accessing the buffer memory. EGL will access the buffer
* memory according to the DRM fourcc code. Cogl will not mmap
* and access the buffer memory at all.
*/
case DRM_FORMAT_XRGB8888:
cogl_format = COGL_PIXEL_FORMAT_RGB_888;
break;
case DRM_FORMAT_ARGB8888:
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
break;
case DRM_FORMAT_ARGB2101010:
cogl_format = COGL_PIXEL_FORMAT_ARGB_2101010_PRE;
break;
case DRM_FORMAT_RGB565:
cogl_format = COGL_PIXEL_FORMAT_RGB_565;
break;
default:
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_FAILED,
"Unsupported buffer format %d", dma_buf->drm_format);

View File

@ -862,6 +862,19 @@ init_pointer_constraint (struct wl_resource *resource,
return;
}
switch (lifetime)
{
case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT:
case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT:
break;
default:
wl_resource_post_error (resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"Invalid constraint lifetime");
return;
}
constraint = meta_wayland_pointer_constraint_new (surface, seat,
region,
lifetime,

View File

@ -48,6 +48,7 @@ typedef struct
char *lock_file;
int abstract_fd;
int unix_fd;
struct wl_display *wayland_display;
struct wl_client *client;
struct wl_resource *xserver_resource;
char *display_name;

View File

@ -266,7 +266,7 @@ meta_wayland_seat_free (MetaWaylandSeat *seat)
meta_wayland_gtk_text_input_destroy (seat->gtk_text_input);
meta_wayland_text_input_destroy (seat->text_input);
g_slice_free (MetaWaylandSeat, seat);
g_free (seat);
}
static gboolean

View File

@ -142,10 +142,12 @@ meta_window_wayland_focus (MetaWindow *window,
guint32 timestamp)
{
if (meta_window_is_focusable (window))
meta_x11_display_set_input_focus_window (window->display->x11_display,
window,
FALSE,
timestamp);
{
meta_display_set_input_focus (window->display,
window,
FALSE,
timestamp);
}
}
static void
@ -611,6 +613,16 @@ meta_window_wayland_are_updates_frozen (MetaWindow *window)
return !wl_window->has_been_shown;
}
static void
meta_window_wayland_map (MetaWindow *window)
{
}
static void
meta_window_wayland_unmap (MetaWindow *window)
{
}
static void
meta_window_wayland_class_init (MetaWindowWaylandClass *klass)
{
@ -634,6 +646,8 @@ meta_window_wayland_class_init (MetaWindowWaylandClass *klass)
window_class->is_stackable = meta_window_wayland_is_stackable;
window_class->can_ping = meta_window_wayland_can_ping;
window_class->are_updates_frozen = meta_window_wayland_are_updates_frozen;
window_class->map = meta_window_wayland_map;
window_class->unmap = meta_window_wayland_unmap;
}
MetaWindow *
@ -641,7 +655,6 @@ meta_window_wayland_new (MetaDisplay *display,
MetaWaylandSurface *surface)
{
XWindowAttributes attrs = { 0 };
MetaWindow *window;
/*
* Set attributes used by _meta_window_shared_new, don't bother trying to fake
@ -656,26 +669,13 @@ meta_window_wayland_new (MetaDisplay *display,
attrs.map_state = IsUnmapped;
attrs.override_redirect = False;
/* XXX: Note: In the Wayland case we currently still trap X errors while
* creating a MetaWindow because we will still be making various redundant
* X requests (passing a window xid of None) until we thoroughly audit all
* the code to make sure it knows about non X based clients...
*/
meta_x11_error_trap_push (display->x11_display); /* Push a trap over all of window
* creation, to reduce XSync() calls
*/
window = _meta_window_shared_new (display,
META_WINDOW_CLIENT_TYPE_WAYLAND,
surface,
None,
WithdrawnState,
META_COMP_EFFECT_CREATE,
&attrs);
meta_x11_error_trap_pop (display->x11_display); /* pop the XSync()-reducing trap */
return window;
return _meta_window_shared_new (display,
META_WINDOW_CLIENT_TYPE_WAYLAND,
surface,
None,
WithdrawnState,
META_COMP_EFFECT_CREATE,
&attrs);
}
static gboolean

View File

@ -465,32 +465,27 @@ on_displayfd_ready (int fd,
return G_SOURCE_REMOVE;
}
gboolean
meta_xwayland_start (MetaXWaylandManager *manager,
struct wl_display *wl_display)
static gboolean
meta_xwayland_init_xserver (MetaXWaylandManager *manager)
{
int xwayland_client_fd[2];
int displayfd[2];
gboolean started = FALSE;
g_autoptr(GSubprocessLauncher) launcher = NULL;
GSubprocessFlags flags;
GError *error = NULL;
if (!choose_xdisplay (manager))
goto out;
/* We want xwayland to be a wayland client so we make a socketpair to setup a
* wayland protocol connection. */
if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, xwayland_client_fd) < 0)
{
g_warning ("xwayland_client_fd socketpair failed\n");
goto out;
return FALSE;
}
if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, displayfd) < 0)
{
g_warning ("displayfd socketpair failed\n");
goto out;
return FALSE;
}
/* xwayland, please. */
@ -511,16 +506,10 @@ meta_xwayland_start (MetaXWaylandManager *manager,
g_subprocess_launcher_setenv (launcher, "WAYLAND_SOCKET", "3", TRUE);
/* Use the -terminate parameter to ensure that Xwayland exits cleanly
* after the last client disconnects. Fortunately that includes the window
* manager so it won't exit prematurely either. This ensures that Xwayland
* won't try to reconnect and crash, leaving uninteresting core dumps. We do
* want core dumps from Xwayland but only if a real bug occurs...
*/
manager->proc = g_subprocess_launcher_spawn (launcher, &error,
XWAYLAND_PATH, manager->display_name,
"-rootless",
"-terminate",
"-noreset",
"-accessx",
"-core",
"-listen", "4",
@ -530,14 +519,15 @@ meta_xwayland_start (MetaXWaylandManager *manager,
if (!manager->proc)
{
g_error ("Failed to spawn Xwayland: %s", error->message);
goto out;
return FALSE;
}
manager->xserver_died_cancellable = g_cancellable_new ();
g_subprocess_wait_async (manager->proc, manager->xserver_died_cancellable,
xserver_died, NULL);
g_unix_fd_add (displayfd[0], G_IO_IN, on_displayfd_ready, manager);
manager->client = wl_client_create (wl_display, xwayland_client_fd[0]);
manager->client = wl_client_create (manager->wayland_display,
xwayland_client_fd[0]);
/* We need to run a mainloop until we know xwayland has a binding
* for our xserver interface at which point we can assume it's
@ -545,15 +535,18 @@ meta_xwayland_start (MetaXWaylandManager *manager,
manager->init_loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (manager->init_loop);
started = TRUE;
return TRUE;
}
out:
if (!started)
{
unlink (manager->lock_file);
g_clear_pointer (&manager->lock_file, g_free);
}
return started;
gboolean
meta_xwayland_start (MetaXWaylandManager *manager,
struct wl_display *wl_display)
{
if (!choose_xdisplay (manager))
return FALSE;
manager->wayland_display = wl_display;
return meta_xwayland_init_xserver (manager);
}
static void

View File

@ -803,14 +803,15 @@ handle_window_focus_event (MetaX11Display *x11_display,
* multiple focus events with the same serial.
*/
if (x11_display->server_focus_serial > x11_display->focus_serial ||
(!display->focused_by_us &&
(!x11_display->focused_by_us &&
x11_display->server_focus_serial == x11_display->focus_serial))
{
meta_display_update_focus_window (display,
focus_window,
focus_window ? focus_window->xwindow : None,
x11_display->server_focus_serial,
FALSE);
meta_display_update_focus_window (display, focus_window);
meta_x11_display_update_focus_window (x11_display,
focus_window ?
focus_window->xwindow : None,
x11_display->server_focus_serial,
FALSE);
return TRUE;
}
else
@ -882,7 +883,7 @@ handle_input_xevent (MetaX11Display *x11_display,
enter_event->mode != XINotifyGrab &&
enter_event->mode != XINotifyUngrab &&
enter_event->detail != XINotifyInferior &&
meta_display_focus_sentinel_clear (display))
meta_x11_display_focus_sentinel_clear (x11_display))
{
meta_window_handle_enter (window,
enter_event->time,
@ -1525,7 +1526,7 @@ handle_other_xevent (MetaX11Display *x11_display,
if (event->xproperty.atom ==
x11_display->atom__MUTTER_SENTINEL)
{
meta_display_decrement_focus_sentinel (display);
meta_x11_display_decrement_focus_sentinel (x11_display);
}
}
}
@ -1792,7 +1793,7 @@ meta_x11_display_handle_xevent (MetaX11Display *x11_display,
if (META_IS_BACKEND_X11 (backend))
meta_backend_x11_handle_event (META_BACKEND_X11 (backend), event);
if (display->focused_by_us &&
if (x11_display->focused_by_us &&
event->xany.serial > x11_display->focus_serial &&
display->focus_window &&
!window_has_xwindow (display->focus_window, x11_display->server_focus_window))
@ -1801,10 +1802,11 @@ meta_x11_display_handle_xevent (MetaX11Display *x11_display,
display->focus_window->desc);
meta_display_update_focus_window (display,
meta_x11_display_lookup_x_window (x11_display,
x11_display->server_focus_window),
x11_display->server_focus_window,
x11_display->server_focus_serial,
FALSE);
x11_display->server_focus_window));
meta_x11_display_update_focus_window (x11_display,
x11_display->server_focus_window,
x11_display->server_focus_serial,
FALSE);
}
if (event->xany.window == x11_display->xroot)

View File

@ -35,6 +35,7 @@
#include "meta/types.h"
#include "meta/meta-x11-display.h"
#include "meta-startup-notification-x11.h"
#include "meta-x11-stack-private.h"
#include "ui/ui.h"
typedef struct _MetaGroupPropHooks MetaGroupPropHooks;
@ -133,8 +134,21 @@ struct _MetaX11Display
GList *output_streams;
} selection;
/* If true, server->focus_serial refers to us changing the focus; in
* this case, we can ignore focus events that have exactly focus_serial,
* since we take care to make another request immediately afterwards.
* But if focus is being changed by another client, we have to accept
* multiple events with the same serial.
*/
guint focused_by_us : 1;
guint keys_grabbed : 1;
/* we use property updates as sentinels for certain window focus events
* to avoid some race conditions on EnterNotify events
*/
int sentinel_counter;
int composite_event_base;
int composite_error_base;
int composite_major_version;
@ -162,6 +176,7 @@ struct _MetaX11Display
#define META_X11_DISPLAY_HAS_XINPUT_23(x11_display) ((x11_display)->have_xinput_23)
MetaX11StartupNotification *startup_notification;
MetaX11Stack *x11_stack;
};
MetaX11Display *meta_x11_display_new (MetaDisplay *display, GError **error);
@ -222,4 +237,16 @@ MetaLogicalMonitor *meta_x11_display_xinerama_index_to_logical_monitor (MetaX11D
void meta_x11_display_update_workspace_layout (MetaX11Display *x11_display);
void meta_x11_display_update_workspace_names (MetaX11Display *x11_display);
void meta_x11_display_increment_focus_sentinel (MetaX11Display *x11_display);
void meta_x11_display_decrement_focus_sentinel (MetaX11Display *x11_display);
gboolean meta_x11_display_focus_sentinel_clear (MetaX11Display *x11_display);
void meta_x11_display_update_focus_window (MetaX11Display *x11_display,
Window xwindow,
gulong serial,
gboolean focused_by_us);
void meta_x11_display_set_input_focus (MetaX11Display *x11_display,
Window xwindow,
guint32 timestamp);
#endif /* META_X11_DISPLAY_PRIVATE_H */

View File

@ -95,6 +95,27 @@ static void unset_wm_check_hint (MetaX11Display *x11_display);
static void prefs_changed_callback (MetaPreference pref,
void *data);
static void
meta_x11_display_unmanage_windows (MetaX11Display *x11_display)
{
GList *windows, *l;
MetaWindow *window;
if (!x11_display->xids)
return;
windows = g_hash_table_get_values (x11_display->xids);
g_list_foreach (windows, (GFunc) g_object_ref, NULL);
for (l = windows; l; l = l->next)
{
window = l->data;
if (!window->unmanaging)
meta_window_unmanage (window, META_CURRENT_TIME);
}
g_list_free_full (windows, g_object_unref);
}
static void
meta_x11_display_dispose (GObject *object)
{
@ -107,6 +128,9 @@ meta_x11_display_dispose (GObject *object)
meta_x11_display_ungrab_keys (x11_display);
meta_x11_selection_shutdown (x11_display);
meta_x11_display_unmanage_windows (x11_display);
g_clear_object (&x11_display->x11_stack);
if (x11_display->ui)
{
@ -466,6 +490,13 @@ init_x11_bell (MetaX11Display *x11_display)
&mask);
}
}
/* We are playing sounds using libcanberra support, we handle the
* bell whether its an audible bell or a visible bell */
XkbChangeEnabledControls (x11_display->xdisplay,
XkbUseCoreKbd,
XkbAudibleBellMask,
0);
}
/*
@ -483,32 +514,6 @@ shutdown_x11_bell (MetaX11Display *x11_display)
XkbAudibleBellMask);
}
/*
* Turns the bell to audible or visual. This tells X what to do, but
* not Mutter; you will need to set the "visual bell" pref for that.
*/
static void
set_x11_bell_is_audible (MetaX11Display *x11_display,
gboolean is_audible)
{
/* When we are playing sounds using libcanberra support, we handle the
* bell whether its an audible bell or a visible bell */
gboolean enable_system_bell = FALSE;
XkbChangeEnabledControls (x11_display->xdisplay,
XkbUseCoreKbd,
XkbAudibleBellMask,
enable_system_bell ? XkbAudibleBellMask : 0);
}
static void
on_is_audible_changed (MetaBell *bell,
gboolean is_audible,
MetaX11Display *x11_display)
{
set_x11_bell_is_audible (x11_display, is_audible);
}
static void
set_desktop_geometry_hint (MetaX11Display *x11_display)
{
@ -1086,6 +1091,9 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
};
Atom atoms[G_N_ELEMENTS(atom_names)];
if (!meta_x11_init_gdk_display (error))
return NULL;
g_assert (prepared_gdk_display);
gdk_display = g_steal_pointer (&prepared_gdk_display);
@ -1270,6 +1278,7 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
set_desktop_geometry_hint (x11_display);
x11_display->ui = meta_ui_new (x11_display);
x11_display->x11_stack = meta_x11_stack_new (x11_display);
x11_display->keys_grabbed = FALSE;
meta_x11_display_grab_keys (x11_display);
@ -1323,12 +1332,6 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
init_x11_bell (x11_display);
g_signal_connect_object (display->bell, "is-audible-changed",
G_CALLBACK (on_is_audible_changed),
x11_display, 0);
set_x11_bell_is_audible (x11_display, meta_prefs_bell_is_audible ());
meta_x11_startup_notification_init (x11_display);
meta_x11_selection_init (x11_display);
@ -1819,17 +1822,27 @@ meta_x11_display_update_active_window_hint (MetaX11Display *x11_display)
meta_x11_error_trap_pop (x11_display);
}
static void
request_xserver_input_focus_change (MetaX11Display *x11_display,
MetaWindow *meta_window,
Window xwindow,
guint32 timestamp)
void
meta_x11_display_update_focus_window (MetaX11Display *x11_display,
Window xwindow,
gulong serial,
gboolean focused_by_us)
{
gulong serial;
x11_display->focus_serial = serial;
x11_display->focused_by_us = !!focused_by_us;
if (meta_display_timestamp_too_old (x11_display->display, &timestamp))
if (x11_display->focus_xwindow == xwindow)
return;
x11_display->focus_xwindow = xwindow;
meta_x11_display_update_active_window_hint (x11_display);
}
void
meta_x11_display_set_input_focus (MetaX11Display *x11_display,
Window xwindow,
guint32 timestamp)
{
meta_x11_error_trap_push (x11_display);
/* In order for mutter to know that the focus request succeeded, we track
@ -1842,8 +1855,6 @@ request_xserver_input_focus_change (MetaX11Display *x11_display,
*/
XGrabServer (x11_display->xdisplay);
serial = XNextRequest (x11_display->xdisplay);
XSetInputFocus (x11_display->xdisplay,
xwindow,
RevertToPointerRoot,
@ -1857,30 +1868,7 @@ request_xserver_input_focus_change (MetaX11Display *x11_display,
XUngrabServer (x11_display->xdisplay);
XFlush (x11_display->xdisplay);
meta_display_update_focus_window (x11_display->display,
meta_window,
xwindow,
serial,
TRUE);
meta_x11_error_trap_pop (x11_display);
x11_display->display->last_focus_time = timestamp;
if (meta_window == NULL || meta_window != x11_display->display->autoraise_window)
meta_display_remove_autoraise_callback (x11_display->display);
}
void
meta_x11_display_set_input_focus_window (MetaX11Display *x11_display,
MetaWindow *window,
gboolean focus_frame,
guint32 timestamp)
{
request_xserver_input_focus_change (x11_display,
window,
focus_frame ? window->frame->xwindow : window->xwindow,
timestamp);
}
void
@ -1888,20 +1876,12 @@ meta_x11_display_set_input_focus_xwindow (MetaX11Display *x11_display,
Window window,
guint32 timestamp)
{
request_xserver_input_focus_change (x11_display,
NULL,
window,
timestamp);
}
gulong serial;
void
meta_x11_display_focus_the_no_focus_window (MetaX11Display *x11_display,
guint32 timestamp)
{
request_xserver_input_focus_change (x11_display,
NULL,
x11_display->no_focus_window,
timestamp);
meta_display_unset_input_focus (x11_display->display, timestamp);
serial = XNextRequest (x11_display->xdisplay);
meta_x11_display_set_input_focus (x11_display, window, timestamp);
meta_x11_display_update_focus_window (x11_display, window, serial, TRUE);
}
static MetaX11DisplayLogicalMonitorData *
@ -2177,3 +2157,34 @@ prefs_changed_callback (MetaPreference pref,
set_workspace_names (x11_display);
}
}
void
meta_x11_display_increment_focus_sentinel (MetaX11Display *x11_display)
{
unsigned long data[1];
data[0] = meta_display_get_current_time (x11_display->display);
XChangeProperty (x11_display->xdisplay,
x11_display->xroot,
x11_display->atom__MUTTER_SENTINEL,
XA_CARDINAL,
32, PropModeReplace, (guchar*) data, 1);
x11_display->sentinel_counter += 1;
}
void
meta_x11_display_decrement_focus_sentinel (MetaX11Display *x11_display)
{
x11_display->sentinel_counter -= 1;
if (x11_display->sentinel_counter < 0)
x11_display->sentinel_counter = 0;
}
gboolean
meta_x11_display_focus_sentinel_clear (MetaX11Display *x11_display)
{
return (x11_display->sentinel_counter == 0);
}

View File

@ -0,0 +1,33 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2019 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_X11_STACK_H
#define META_X11_STACK_H
#include <glib-object.h>
#include "meta/types.h"
#define META_TYPE_X11_STACK (meta_x11_stack_get_type ())
G_DECLARE_FINAL_TYPE (MetaX11Stack, meta_x11_stack, META, X11_STACK, GObject)
typedef struct _MetaX11Stack MetaX11Stack;
MetaX11Stack * meta_x11_stack_new (MetaX11Display *x11_display);
#endif /* META_X11_STACK_H */

413
src/x11/meta-x11-stack.c Normal file
View File

@ -0,0 +1,413 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2019 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "core/frame.h"
#include "core/stack.h"
#include "core/window-private.h"
#include "x11/meta-x11-display-private.h"
#include "x11/meta-x11-stack-private.h"
struct _MetaX11Stack
{
GObject parent;
MetaX11Display *x11_display;
/*
* A sequence of all the Windows (X handles, not MetaWindows) of the windows
* we manage, sorted in order. Suitable to be passed into _NET_CLIENT_LIST.
*/
GArray *xwindows;
/*
* MetaWindows waiting to be added to the xwindows list, after
* being added to the MetaStack.
*
* The order of the elements in this list is not important; what is important
* is the stack_position element of each window.
*/
GList *added;
/*
* Windows (X handles, not MetaWindows) waiting to be removed from the
* xwindows list, after being removed from the MetaStack.
*
* The order of the elements in this list is not important.
*/
GList *removed;
};
enum
{
PROP_DISPLAY = 1,
N_PROPS
};
static GParamSpec *pspecs[N_PROPS] = { 0 };
G_DEFINE_TYPE (MetaX11Stack, meta_x11_stack, G_TYPE_OBJECT)
static void
meta_x11_stack_init (MetaX11Stack *x11_stack)
{
x11_stack->xwindows = g_array_new (FALSE, FALSE, sizeof (Window));
}
static void
meta_x11_stack_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaX11Stack *x11_stack = META_X11_STACK (object);
switch (prop_id)
{
case PROP_DISPLAY:
x11_stack->x11_display = g_value_get_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
meta_x11_stack_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaX11Stack *x11_stack = META_X11_STACK (object);
switch (prop_id)
{
case PROP_DISPLAY:
g_value_set_object (value, x11_stack->x11_display);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
stack_window_added_cb (MetaStack *stack,
MetaWindow *window,
MetaX11Stack *x11_stack)
{
if (window->client_type != META_WINDOW_CLIENT_TYPE_X11)
return;
x11_stack->added = g_list_prepend (x11_stack->added, window);
}
static void
stack_window_removed_cb (MetaStack *stack,
MetaWindow *window,
MetaX11Stack *x11_stack)
{
if (window->client_type != META_WINDOW_CLIENT_TYPE_X11)
return;
x11_stack->added = g_list_remove (x11_stack->added, window);
x11_stack->removed = g_list_prepend (x11_stack->removed,
GUINT_TO_POINTER (window->xwindow));
if (window->frame)
{
x11_stack->removed = g_list_prepend (x11_stack->removed,
GUINT_TO_POINTER (window->frame->xwindow));
}
}
/**
* stack_do_window_deletions:
*
* Go through "deleted" and take the matching windows
* out of "windows".
*/
static void
x11_stack_do_window_deletions (MetaX11Stack *x11_stack)
{
GList *tmp;
int i;
tmp = x11_stack->removed;
while (tmp != NULL)
{
Window xwindow;
xwindow = GPOINTER_TO_UINT (tmp->data);
/* We go from the end figuring removals are more
* likely to be recent.
*/
i = x11_stack->xwindows->len;
while (i > 0)
{
--i;
/* there's no guarantee we'll actually find windows to
* remove, e.g. the same xwindow could have been
* added/removed before we ever synced, and we put
* both the window->xwindow and window->frame->xwindow
* in the removal list.
*/
if (xwindow == g_array_index (x11_stack->xwindows, Window, i))
{
g_array_remove_index (x11_stack->xwindows, i);
goto next;
}
}
next:
tmp = tmp->next;
}
g_clear_pointer (&x11_stack->removed, g_list_free);
}
static void
x11_stack_do_window_additions (MetaX11Stack *x11_stack)
{
GList *tmp;
gint n_added;
n_added = g_list_length (x11_stack->added);
if (n_added > 0)
{
meta_topic (META_DEBUG_STACK,
"Adding %d windows to sorted list\n",
n_added);
/* stack->added has the most recent additions at the
* front of the list, so we need to reverse it
*/
x11_stack->added = g_list_reverse (x11_stack->added);
tmp = x11_stack->added;
while (tmp != NULL)
{
MetaWindow *w;
w = tmp->data;
g_array_append_val (x11_stack->xwindows, w->xwindow);
tmp = tmp->next;
}
}
g_clear_pointer (&x11_stack->added, g_list_free);
}
/**
* x11_stack_sync_to_server:
*
* Order the windows on the X server to be the same as in our structure.
* We do this using XRestackWindows if we don't know the previous order,
* or XConfigureWindow on a few particular windows if we do and can figure
* out the minimum set of changes. After that, we set __NET_CLIENT_LIST
* and __NET_CLIENT_LIST_STACKING.
*
* FIXME: Now that we have a good view of the stacking order on the server
* with MetaStackTracker it should be possible to do a simpler and better
* job of computing the minimal set of stacking requests needed.
*/
static void
x11_stack_sync_to_xserver (MetaX11Stack *x11_stack)
{
MetaX11Display *x11_display = x11_stack->x11_display;
MetaStack *stack = x11_display->display->stack;
GArray *x11_stacked;
GArray *all_root_children_stacked; /* wayland OR x11 */
GList *tmp;
GArray *hidden_stack_ids;
uint64_t guard_window_id;
GList *sorted;
meta_topic (META_DEBUG_STACK, "Syncing window stack to server\n");
/* Create stacked xwindow arrays, in bottom-to-top order
*/
x11_stacked = g_array_new (FALSE, FALSE, sizeof (Window));
all_root_children_stacked = g_array_new (FALSE, FALSE, sizeof (guint64));
hidden_stack_ids = g_array_new (FALSE, FALSE, sizeof (guint64));
meta_topic (META_DEBUG_STACK, "Bottom to top: ");
meta_push_no_msg_prefix ();
sorted = meta_stack_list_windows (stack, NULL);
for (tmp = sorted; tmp; tmp = tmp->next)
{
MetaWindow *w = tmp->data;
guint64 top_level_window;
guint64 stack_id;
if (w->unmanaging)
continue;
meta_topic (META_DEBUG_STACK, "%u:%d - %s ",
w->layer, w->stack_position, w->desc);
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
g_array_append_val (x11_stacked, w->xwindow);
if (w->frame)
top_level_window = w->frame->xwindow;
else
top_level_window = w->xwindow;
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
stack_id = top_level_window;
else
stack_id = w->stamp;
/* We don't restack hidden windows along with the rest, though they are
* reflected in the _NET hints. Hidden windows all get pushed below
* the screens fullscreen guard_window. */
if (w->hidden)
{
g_array_append_val (hidden_stack_ids, stack_id);
continue;
}
g_array_append_val (all_root_children_stacked, stack_id);
}
meta_topic (META_DEBUG_STACK, "\n");
meta_pop_no_msg_prefix ();
/* The screen guard window sits above all hidden windows and acts as
* a barrier to input reaching these windows. */
guard_window_id = x11_stack->x11_display->guard_window;
g_array_append_val (hidden_stack_ids, guard_window_id);
/* Sync to server */
meta_topic (META_DEBUG_STACK, "Restacking %u windows\n",
all_root_children_stacked->len);
meta_stack_tracker_restack_managed (x11_display->display->stack_tracker,
(guint64 *)all_root_children_stacked->data,
all_root_children_stacked->len);
meta_stack_tracker_restack_at_bottom (x11_display->display->stack_tracker,
(guint64 *)hidden_stack_ids->data,
hidden_stack_ids->len);
/* Sync _NET_CLIENT_LIST and _NET_CLIENT_LIST_STACKING */
XChangeProperty (x11_stack->x11_display->xdisplay,
x11_stack->x11_display->xroot,
x11_stack->x11_display->atom__NET_CLIENT_LIST,
XA_WINDOW,
32, PropModeReplace,
(unsigned char *) x11_stack->xwindows->data,
x11_stack->xwindows->len);
XChangeProperty (x11_stack->x11_display->xdisplay,
x11_stack->x11_display->xroot,
x11_stack->x11_display->atom__NET_CLIENT_LIST_STACKING,
XA_WINDOW,
32, PropModeReplace,
(unsigned char *) x11_stacked->data,
x11_stacked->len);
g_array_free (x11_stacked, TRUE);
g_array_free (hidden_stack_ids, TRUE);
g_array_free (all_root_children_stacked, TRUE);
g_list_free (sorted);
}
static void
stack_changed_cb (MetaX11Stack *x11_stack)
{
/* Do removals before adds, with paranoid idea that we might re-add
* the same window IDs.
*/
x11_stack_do_window_deletions (x11_stack);
x11_stack_do_window_additions (x11_stack);
x11_stack_sync_to_xserver (x11_stack);
}
static void
meta_x11_stack_constructed (GObject *object)
{
MetaX11Stack *x11_stack = META_X11_STACK (object);
MetaX11Display *x11_display = x11_stack->x11_display;
G_OBJECT_CLASS (meta_x11_stack_parent_class)->constructed (object);
g_signal_connect (x11_display->display->stack,
"window-added",
G_CALLBACK (stack_window_added_cb),
x11_stack);
g_signal_connect (x11_display->display->stack,
"window-removed",
G_CALLBACK (stack_window_removed_cb),
x11_stack);
g_signal_connect_swapped (x11_display->display->stack,
"changed",
G_CALLBACK (stack_changed_cb),
x11_stack);
}
static void
meta_x11_stack_finalize (GObject *object)
{
MetaX11Stack *x11_stack = META_X11_STACK (object);
MetaX11Display *x11_display = x11_stack->x11_display;
if (x11_display->display && x11_display->display->stack)
{
g_signal_handlers_disconnect_by_data (x11_display->display->stack,
x11_stack);
}
g_array_free (x11_stack->xwindows, TRUE);
g_list_free (x11_stack->added);
g_list_free (x11_stack->removed);
G_OBJECT_CLASS (meta_x11_stack_parent_class)->finalize (object);
}
static void
meta_x11_stack_class_init (MetaX11StackClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->set_property = meta_x11_stack_set_property;
object_class->get_property = meta_x11_stack_get_property;
object_class->constructed = meta_x11_stack_constructed;
object_class->finalize = meta_x11_stack_finalize;
pspecs[PROP_DISPLAY] =
g_param_spec_object ("display",
"Display",
"Display",
META_TYPE_X11_DISPLAY,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_properties (object_class, N_PROPS, pspecs);
}
MetaX11Stack *
meta_x11_stack_new (MetaX11Display *x11_display)
{
return g_object_new (META_TYPE_X11_STACK,
"display", x11_display,
NULL);
}

View File

@ -794,10 +794,10 @@ meta_window_x11_focus (MetaWindow *window,
{
meta_topic (META_DEBUG_FOCUS,
"Focusing frame of %s\n", window->desc);
meta_x11_display_set_input_focus_window (window->display->x11_display,
window,
TRUE,
timestamp);
meta_display_set_input_focus (window->display,
window,
TRUE,
timestamp);
}
else
{
@ -806,10 +806,10 @@ meta_window_x11_focus (MetaWindow *window,
meta_topic (META_DEBUG_FOCUS,
"Setting input focus on %s since input = true\n",
window->desc);
meta_x11_display_set_input_focus_window (window->display->x11_display,
window,
FALSE,
timestamp);
meta_display_set_input_focus (window->display,
window,
FALSE,
timestamp);
}
if (priv->wm_take_focus)
@ -832,8 +832,7 @@ meta_window_x11_focus (MetaWindow *window,
*/
if (window->display->focus_window != NULL &&
window->display->focus_window->unmanaging)
meta_x11_display_focus_the_no_focus_window (window->display->x11_display,
timestamp);
meta_display_unset_input_focus (window->display, timestamp);
}
request_take_focus (window, timestamp);
@ -1706,6 +1705,27 @@ meta_window_x11_are_updates_frozen (MetaWindow *window)
return FALSE;
}
static void
meta_window_x11_map (MetaWindow *window)
{
MetaX11Display *x11_display = window->display->x11_display;
meta_x11_error_trap_push (x11_display);
XMapWindow (x11_display->xdisplay, window->xwindow);
meta_x11_error_trap_pop (x11_display);
}
static void
meta_window_x11_unmap (MetaWindow *window)
{
MetaX11Display *x11_display = window->display->x11_display;
meta_x11_error_trap_push (x11_display);
XUnmapWindow (x11_display->xdisplay, window->xwindow);
meta_x11_error_trap_pop (x11_display);
window->unmaps_pending ++;
}
static void
meta_window_x11_class_init (MetaWindowX11Class *klass)
{
@ -1733,6 +1753,8 @@ meta_window_x11_class_init (MetaWindowX11Class *klass)
window_class->is_stackable = meta_window_x11_is_stackable;
window_class->can_ping = meta_window_x11_can_ping;
window_class->are_updates_frozen = meta_window_x11_are_updates_frozen;
window_class->map = meta_window_x11_map;
window_class->unmap = meta_window_x11_unmap;
}
void