Compare commits

...

50 Commits

Author SHA1 Message Date
7a7e711b86 x11: Limit touch replay pointer events to when replaying
When a touch sequence was rejected, the emulated pointer events would be
replayed with old timestamps. This caused issues with grabs as they
would be ignored due to being too old. This was mitigated by making sure
device event timestamps never travelled back in time by tampering with
any event that had a timestamp seemingly in the past.

This failed when the most recent timestamp that had been received were
much older than the timestamp of the new event. This could for example
happen when a session was left not interacted with for 40+ days or so;
when interacted with again, as any new timestamp would according to
XSERVER_TIME_IS_BEFORE() still be in the past compared to the "most
recent" one. The effect is that we'd always use the `latest_evtime` for
all new device events without ever updating it.

The end result of this was that passive grabs would become active when
interacted with, but would then newer be released, as the timestamps to
XIAllowEvents() would out of date, resulting in the desktop effectively
freezing, as the Shell would have an active pointer grab.

To avoid the situation where we get stuck with an old `latest_evtime`
timestamp, limit the tampering with device event timestamp to 1) only
pointer events, and 2) only during the replay sequence. The second part
is implemented by sending an asynchronous message via the X server after
rejecting a touch sequence, only potentially tampering with the device
event timestamps until the reply. This should avoid the stuck timestamp
as in those situations, we'll always have a relatively up to date
`latest_evtime` meaning XSERVER_TIME_IS_BEFORE() will not get confused.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/886
2020-04-24 21:28:15 +02:00
fa3f227236 display: Move finishing of touch sequence to the backend
We need to manipulate an X11 grab when a touch sequence ends; move that
logic to where it belongs - in the X11 backend.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/886
2020-04-24 21:28:15 +02:00
5cb3b4643d Update German translation (Launchpad bug 1786977) 2019-09-05 23:50:38 +02:00
2a81dc45e7 window-x11: Remove double definition of MetaStack
In commit c05fe4ae9 we introduced a double definition of MetaStack due to a
wrong cherry-pick conflict resolution.

Fix this by removing the invalid duplicated line.

Related to https://gitlab.gnome.org/GNOME/mutter/merge_requests/688
2019-07-18 11:43:13 +02:00
c05fe4ae98 window-x11: Focus a window in the active workspace as take-focus fallback
Starting with commit 2db94e2e we try to focus a fallback default focus window
if no take-focus window candidate gets the input focus when we request it and
we limit the focus candidates to the current window's workspace.

However, if the window is unmanaging, the workspace might be unset, and we could
end up in deferencing a NULL pointer causing a crash.

So, in case the window's workspace is unset, just use the currently active
workspace for the display.

Closes https://gitlab.gnome.org/GNOME/mutter/issues/687

https://gitlab.gnome.org/GNOME/mutter/merge_requests/688

(cherry picked from commit 5ca0ef078d)
2019-07-18 10:46:35 +02:00
2a692a0328 window-x11: Use any focusable window as fallback delayed focus window
As per commit f71151a5 we focus an input window if no take-focus-window accepts
it. This might lead to an infinite loop if there are various focusable but
non-input windows in the stack.

When the current focus window is unmanaging and we're trying to focus a
WM_TAKE_FOCUS window, we intent to give the focus to the first focusable input
window in the stack.

However, if an application (such as the Java ones) only uses non-input
WM_TAKE_FOCUS windows, are not requesting these ones to get the focus. This
might lead to a state where no window is focused, or a wrong one is.

So, instead of only focus the first eventually input window available, try to
request to all the take-focus windows that are in the stack between the
destroyed one and the first input one to acquire the input focus.
Use a queue to keep track of those windows, that is passed around stealing
ownership, while we protect for unmanaged queued windows.

Also, reduce the default timeout value, as the previous one might lead to an
excessive long wait.

Added metatests verifying these situations.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/660
https://gitlab.gnome.org/GNOME/mutter/merge_requests/669

(cherry picked from commit 6d8293a422)
2019-07-08 17:30:10 +02:00
288ab54ccf tests: Add "accept_take_focus" command
When used it setups an X11 event monitor that replies to WM_TAKE_FOCUS
ClientMessage's with a XSetInputFocus request.

It can only be used by x11 clients on windows that have WM_TAKE_FOCUS atom set
and that does not accept input.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/669

(cherry picked from commit b80250e483)
2019-07-08 17:30:10 +02:00
0733f22b81 test-client: Add x11 events GSource handler
When using gtk under X11 some WM related events are always filtered and not
delivered when using the gdk Window filters.

So, add a new one with higher priority than the GTK events one so that we can
pick those events before than Gtk itself.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/669


(cherry picked from commit bd0f1bd338)
2019-07-08 17:13:21 +02:00
60ea32330a stack: Add a function to get a sorted list of focus candidates
Use a static function if a window can be the default focus window, and use such
function to return a filtered list of the stack.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/669

(cherry picked from commit 2439255f32)
2019-07-08 17:13:21 +02:00
03d880ad2b window-x11: Accept any focusable window as fallback focus
As per commit f71151a5 we were ignoring WM_TAKE_FOCUS-only windows as focus
targets, however this might end-up in an infinite loop if there are multiple
non-input windows stacked.

So, accept any focusable window as fallback focus target even if it's a
take-focus one (that might not reply to the request).

Added a stacking test to verify this.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/660
https://gitlab.gnome.org/GNOME/mutter/merge_requests/669

(cherry picked from commit c327b2df95)
2019-07-08 17:13:20 +02:00
bee55a27f4 window-x11: Don't double-check for unmanaging windows
When looking for the best fallback focus window, we ignore it if it is in the
unmanaging state, but meta_stack_get_default_focus_window() does this is check
for us already.

So, ignore the redundant test.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/669


(cherry picked from commit 9aee47daa9)
2019-07-08 17:12:29 +02:00
4349e682f8 Makefile-tests: Fix paths for stacking metatests
In commit 29ffaa6f8 and commit 8abd1b009 were added stacking tests with wrong
paths.

Fix them.

Realated to: https://gitlab.gnome.org/GNOME/mutter/merge_requests/307

# Conflicts:
#	src/Makefile-tests.am
2019-07-08 17:12:25 +02:00
9f98743cfc surface-actor-x11: Bind the surface actor resources to window actor life
X11 actors need to release the server data (pixmap and damage) before the
display is closed.
During the close phase all the windows are unmanaged and this causes the window
actors to be removed from the compositor, unsetting their actor surface.

However, in case a window is animating the surface might not be destroyed until
the animation is completed and a reference to it kept around by gjs in the shell
case. By the way, per commit 7718e67f all window actors (even the animating
ones) are destroyed before the display is closed, but this is not true for the
child surface, because the parent window will just unref it, leaving it around
if reffed somewhere else. This is fine for wayland surfaces, but not for X11
ones which are bound to server-side pixmaps.

So, connect to the parent MetaWindowActor "destroy" signal, releasing the x11
resources that implies detaching the pixmap (unsetting the texture) and removing
the damages.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/629
https://gitlab.gnome.org/GNOME/mutter/merge_requests/660

(cherry picked from commit de97b54595)
2019-06-28 20:15:05 +02:00
d4759df5bb surface-actor-x11: Assign X11 Display only if we have resources
free_damage and detach_pixmap functions are called inside dispose and an object
can be disposed multiple times, even when the display is already closed.

So, don't try to deference a possibly null-pointer, assigning the xdisplay too
early, as if the X11 related resources have been unset, the server might not be
open anymore. In fact, we assume that if we have a damage or a pixmap set,
the display is still open.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/660

(cherry picked from commit d7d97f2477)
2019-06-28 20:15:05 +02:00
ffa4279a96 window-actor: Set actor as compositor private in window before the surface
In MetaWindowActor creation we're setting the compositor private (i.e. the
window actor itself) of a window before creating the surface actor, and so
passing to the it a window without its compositor side set.

Since the surface actor might use the parent actor, set this before updating
the surface.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/660

(cherry picked from commit 7776941b89)
2019-06-28 20:15:04 +02:00
a51188f8d7 window-x11: Add lost definition for TAKE_FOCUS_FALLBACK_DELAY_MS
In commit 8abd1b009 (cherry-pick to gnome-3-30 of commit f71151a5d) the
definition of TAKE_FOCUS_FALLBACK_DELAY_MS was not properly merged.

Include this back to fix the build failure.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
2019-06-28 20:15:04 +02:00
a9322c81af window: Emit an error and return when trying to activate an unmanaged
If something (i.e. gnome-shell or an extension) tries to activate an unmanaged
window, we should warn about this and avoid to perform further actions as this
could lead to a crash of mutter, since the window has not valid flags (like
workspace) set anymore at this stage.

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/580

https://gitlab.gnome.org/GNOME/mutter/merge_requests/564


(cherry picked from commit a6fc656e91)
2019-06-28 12:13:09 +00:00
8abd1b0092 window-x11: Focus the default window with delay while waiting for take-focus
When requesting to a take-focus window to acquire the input, the client may or
may not respond with a SetInputFocus (this doesn't happen for no-input gtk
windows in fact [to be fixed there too]), in such case we were unsetting the
focus while waiting the reply.

In case the client won't respond, we wait for a small delay (set to 250 ms) for
the take-focus window to grab the input focus before setting it to the default
window.

Added a test for this behavior and for the case in which a window takes the
focus meanwhile we're waiting to focus the default window.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
(cherry picked from commit f71151a5dd)
2019-06-24 16:12:35 +02:00
7d936018d2 test-runner: Add 'dispatch' command
This will only wait for events to be dispatched and processed by the server
without waiting for client processing.

Reuse the code for the wait command too.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
(cherry picked from commit 6022b23923)
2019-06-24 16:12:35 +02:00
b1dbdd41ab test-runner: Add 'sleep' command
This allows to sleep for a given timeout in milliseconds.

Rename test_case_before_redraw to test_case_loop_quit since it's a generic
function and use it for the timeout too.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
(cherry picked from commit d08763c18c)
2019-06-24 16:12:35 +02:00
7927415e5b tests: Verify focused window in closed-transient tests
Ensure that we have a focused window when closing transient windows with
no-focus or no-take-focus atoms

https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
(cherry picked from commit fcb408ad5d)
2019-06-24 16:12:35 +02:00
2021a7206c test-runner: Add 'assert_focused' command
This allows to verify which window should have the focus, which might not
be the same as the top of the stack.

It's possible to assert the case where there's no focused window using
"NONE" as parameter.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
(cherry picked from commit 51f9e04ef1)
2019-06-24 16:12:35 +02:00
29ffaa6f89 tests, stacking: Add tests with no-input and no-take-focus windows
When a window with no frame, that doesn't accept focus and that has no
take-focus atom set is destroyed, we ended up in not changing the current_focus
window, causing a crash.

Added test cases that verify this situation.

Related to https://gitlab.gnome.org/GNOME/mutter/issues/308
https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
(cherry picked from commit 2fc7760cee)
2019-06-24 16:12:35 +02:00
689bff0ac2 tests: Add 'can_take_focus' command to runner and client
Allow to set/unset WM_TAKE_FOCUS from client window.
This is added by default by gtk, but this might not happen in other toolkits,
so add an ability to (un)set this.

So fetch the protocols with XGetWMProtocols and unset the atom.

test-client now needs to depend on Xlib directly in meson build.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
(cherry picked from commit f2d2d473b7)
2019-06-24 16:04:22 +02:00
81807fc310 tests: Add 'accept_focus' command to runner and client
Under the hood, calls gtk_window_set_accept_focus in the client

https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
(cherry picked from commit e1f839f48f)
2019-06-24 16:04:22 +02:00
b95700dabc workspace: Focus only ancestors that are focusable
When destroying a window that has a parent, we initially try to focus one of
its ancestors. However if no ancestor can be focused, then we should instead
focus the default focus window instead of trying to request focus for a window
that can't get focus anyways.

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/308
(cherry picked from commit eccc791f3b)
2019-06-24 16:04:22 +02:00
d792a320be Updated Spanish translation 2019-06-20 10:03:36 +02:00
6dbd057ef4 renderer/native: add missing eglTerminate in EGLDevice error path
Currently the EGLDevice code gets the display and calls eglInitialize.
As a follow-up it checks the required EGL extensions - technically it
could check the EGL device extensions earlier.

In either case, eglTerminate is missing. Thus the connection to the
display was still bound.

This was highlighted with Mesa commit d6edccee8da ("egl: add
EGL_platform_device support") + amdgpu.

In that case, since the eglTerminate is missing, we end up reusing the
underlying amdgpu_device due to some caching in libdrm_amdgpu. The
latter in itself being a good solution since it allows buffer sharing
across primary and render node of the same device.

Note: we should really get this in branches all the way back to 3.30.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/619

Fixes: 934184e23 ("MetaRendererNative: Add EGLDevice based rendering support")
Cc: Jonas Ådahl <jadahl@gmail.com>
Signed-off-by: Emil Velikov <emil.velikov@collabora.com>


(cherry picked from commit 9213574870)
2019-06-13 16:45:48 +00:00
49dcf50727 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


(cherry picked from commit 7e0d185120)
2019-05-27 22:40:24 +00:00
ccd5e9fa08 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


(cherry picked from commit 0405786573)
2019-05-27 22:38:16 +00:00
41d28e254a cursor-renderer-native: Free MetaCursorNativePrivate struct
Fix a small leak in native renderer.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/581


(cherry picked from commit b016ff29f6)
2019-05-27 22:35:20 +00:00
956bb80667 clutter/x11: Implement keycode remap to keysyms on virtual key devices
Keycode lookup can fail for serveral reasons, e.g. if there is no combination of
modifiers and keycodes that can produce the target keysym with the current
keyboard layout.

In case the keycode lookup fails, remap temporarily the keysym to an unused
keycodes.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/109

(cherry-picked from commit e3e933c47a)
2019-05-05 11:09:47 -05:00
1d8c4285b9 compositor: Disconnect from stage signals on destruction
From this point there's not any need for the compositor to listen to signals
so we can disconnect from the stage ones we are connected to.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/556


(cherry picked from commit 3ba79961fe)
2019-05-03 18:30:34 +00:00
ffe94b0d73 compositor: Destroy window actors list on destruction
When the compositor is destroyed we should cleanup the list of window actors we
created and destroy them.
Since all the actors are added to the window_group or top_window_group we can
just destroy these containers (together with the feedback_group), and simply
free the windows list.

This is particularly needed under X11 because before we destroy the display, we
might do some cleanups as detaching the surface pixmaps and freeing the damages
and if this happens at later point (for example when triggered by garbage
collector in gnome-shell), we might crash because the x11 dpy reference is
already gone.

Destroying the window actors instead, ensures we avoid any further call to X11
related functions and that we release the actors XServer resources.

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/576


(cherry picked from commit 7718e67f5c)
2019-05-03 18:30:13 +00:00
0f7c35b94a clutter/x11: Consider remapped keys when guessing the keycode from the keysym
Since e3e933c4 a keyval can be temporarily remapped to an unused keycode. Due to
some limitations in XTestFakeKeyEvent, the remapping has to be done in the first
xkb group/layout. In case there are two or more keyboard layouts enabled and the
selected keyboard layout is not the first, clutter_keymap_x11_keycode_for_keyval
will fail to retrieve the correct keycode for a remapped keyval. Let's use the
reserved_keycodes map in order to retrieve the correct keycode if needed.

Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/443


(cherry picked from commit e0811ce141)
2019-04-30 16:51:37 +00:00
db8a29b348 clutter: Fix check for keyboard a11y features
The typo was actually toggling the feature on for those who had it
disabled.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/529
2019-03-28 12:19:03 +01:00
6be3961299 clutter/evdev: Fix toggling accessibility features from keyboard
Enabling keyboard accessibility features on Wayland from the keyboard
was wrongly assumed to be controlled by the "togglekeys" setting,
whereas it should be simply controlled by the "enable" setting.

As "togglekeys" is off by default and doesn't have a UI option to
enable, that would prevent turning on or off the keyboard accessibility
features using the keyboard.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/501
2019-03-21 15:14:34 +00:00
7260ba5db3 monitor-manager: Don't use switch-config when ensuring configuration
Switch-configs are only to be used in certain circumstances (see
meta_monitor_manager_can_switch_config()) so when ensuring
configuration and attempting to create a linear configuration, use the
linear configuration constructor function directly without going via the
switch config method, otherwise we might incorrectly fall back to the
fallback configuration (only enable primary monitor).

This is a regression introduced by 6267732bec.

Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/342


(cherry picked from commit 149e4d6934)
2019-01-30 16:56:44 +00:00
1c57a58420 screen-cast: Fix monitor recording on HiDPI
It scaled the logical monitor rect with scale to get the stream
dimensions, but that is only valid when having
'scale-monitor-framebuffers' enabled. Even when it was, it didn't work
properly, as clutter_stage_capture_into() doesn't work properly with
scaled monitor framebuffers yet.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/415


(cherry picked from commit 3fa6a92cc5)
2019-01-28 15:14:53 +00:00
5e4cb54bb5 tests: Don't check pixels outside actor allocation
The actor-shader-effect test actors are 50px wide, but we check the 51st
pixel. This went along undetected until "clutter: Avoid rounding
compensation when invalidating 2D actors" because the paint volumes were
made slightly bigger and the shaders paint all over them (I guess nobody
noticed those actors being actually ~52px wide).

Update the test to check the middle of the opposite edge, so we keep neatly
rounded numbers.


(cherry picked from commit 1d73533f78)
2019-01-24 17:15:32 +00:00
afc91f0804 clutter: Avoid rounding compensation when invalidating 2D actors
This allows the redraw clip to be more constrained, so MetaCullable doesn't
end up rendering portions of window shadows, frame and background when a
window invalidates (part of) its contents.

https://bugzilla.gnome.org/show_bug.cgi?id=782344


(cherry picked from commit a7df459416)
2019-01-24 16:09:45 +00:00
c6223ffea8 clutter-offscreen-effect: Disable if no texture
If texture allocation fails (e.g. on an old GPU with size limit 2048)
then `update_fbo` would return `FALSE` but leaves `priv->offscreen`
as non-NULL. So the next paint will try to use the offscreen with a
`NULL` texture and crashes. The solution is simply to ensure that
`priv->offscreen` is NULL if there is no `priv->texture`, so the default
(non-offscreen) paint path gets used instead.

Bug reported and fix provided by Gert van de Kraats.

https://launchpad.net/bugs/1795774


(cherry picked from commit f31cf0c3ef)

(cherry picked from commit 1b78ca8c5e)
2019-01-23 23:54:54 +00:00
1cb21877ed cogl-auto-texture: Avoid a double-free crash
If texture allocation fails (e.g. on an old GPU with size limit 2048)
then `cogl_texture_new_with_size` was trying to use the same CoglError
twice. The second time was after it had already been freed.

Bug reported and fix provided by Gert van de Kraats.

https://launchpad.net/bugs/1790525


(cherry picked from commit d21478b0f0)
2019-01-23 23:54:31 +00:00
d0de451e29 Update Basque translation 2018-12-07 12:49:20 +00:00
28d2d54189 Update French translation 2018-11-15 22:35:59 +00:00
bcd6103c44 Bump version to 3.30.2
Update NEWS.
2018-11-13 23:27:20 +01:00
8eabfaaa8b window: Really force update monitor on hot plugs
Commit 8d3e05305 ("window: Force update monitor on hot plugs") added the
flag `META_WINDOW_UPDATE_MONITOR_FLAGS_FORCE` passed to
`update_monitor()` from `update_for_monitors_changed()`.

However, `update_for_monitors_changed()` may choose to call another code
path to `move_between_rects()` and `meta_window_move_resize_internal()`
eventually.

As `meta_window_move_resize_internal()` does not use the "force" flag,
we may still end up in case where the window->monitor is left unchanged.

To avoid that problem, add a new `MetaMoveResizeFlags` that
`update_for_monitors_changed()` can use to force the monitor update from
`meta_window_move_resize_internal()`.

Fixes: 8d3e05305 ("window: Force update monitor on hot plugs")
Closes: https://gitlab.gnome.org/GNOME/mutter/issues/189


(cherry picked from commit fa495286a1)
2018-11-13 09:22:01 +00:00
1d863f4d3e x11: close display in an idle function
Closing a GdkDisplay during an event handler is not currently supported by Gdk
and it will result in a crash when doing e.g. 'mutter --replace'. Using an idle
function will close it safely in a subsequent main loop iteration.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/595
2018-11-08 10:30:13 +00:00
1abab3fe2e Update Slovak translation 2018-10-27 19:20:13 +00:00
d364fa50ba wayland: Defer text_input.done on an idle
IBus naturally doesn't know how to implement the text-input protocol,
and some input methods emit event streams that are incompatible with the
protocol, if not assumed to be part of an grouped series of events. As
IBus doesn't have any API to let us know about such groupings, let's
fake it by adding a specially crafted idle callback.

The idle callback has a known limitation; if there is an idle callback
with a higher priority, that either doesn't remove itself, or
reschedules itself before the next idle, we'll never get triggered.
This, however, is unlikely to actually be the bigger problem in such
situations, as it'd likely mean we'd have a 100% CPU bug.

https://gitlab.gnome.org/GNOME/gtk/issues/1365
2018-10-22 16:50:36 +00:00
50 changed files with 1816 additions and 348 deletions

15
NEWS
View File

@ -1,3 +1,18 @@
3.30.2
======
* Fix handling of non-UTF8 encodings [Florian; !227]
* Fix memory leaks introduced in 3.30.1 [Jonas; #653]
* Work around hangul text input bug [Carlos; gtk#1365]
* Fix crash when restarting window manager [Andrea; gnome-shell#595]
* Fix crash on monitor hotplug [Olivier; #189]
Contributors:
Jonas Ådahl, Andrea Azzarone, Olivier Fourdan, Carlos Garnacho,
Florian Müllner, Akira Nakajima
Translators:
Dušan Kazik [sk]
3.30.1
======
* Improve trackball detection [Tony; #258]

View File

@ -186,6 +186,12 @@ update_fbo (ClutterEffect *effect, int fbo_width, int fbo_height)
priv->texture = NULL;
}
if (priv->offscreen != NULL)
{
cogl_handle_unref (priv->offscreen);
priv->offscreen = NULL;
}
priv->texture =
clutter_offscreen_effect_create_texture (self, fbo_width, fbo_height);
if (priv->texture == NULL)
@ -196,9 +202,6 @@ update_fbo (ClutterEffect *effect, int fbo_width, int fbo_height)
priv->fbo_width = fbo_width;
priv->fbo_height = fbo_height;
if (priv->offscreen != NULL)
cogl_handle_unref (priv->offscreen);
priv->offscreen = cogl_offscreen_new_to_texture (priv->texture);
if (priv->offscreen == NULL)
{

View File

@ -1166,6 +1166,21 @@ _clutter_paint_volume_get_stage_paint_box (ClutterPaintVolume *pv,
_clutter_paint_volume_get_bounding_box (&projected_pv, box);
if (pv->is_2d && pv->actor &&
clutter_actor_get_z_position (pv->actor) == 0)
{
/* If the volume/actor are perfectly 2D, take the bounding box as
* good. We won't need to add any extra room for sub-pixel positioning
* in this case.
*/
clutter_paint_volume_free (&projected_pv);
box->x1 = CLUTTER_NEARBYINT (box->x1);
box->y1 = CLUTTER_NEARBYINT (box->y1);
box->x2 = CLUTTER_NEARBYINT (box->x2);
box->y2 = CLUTTER_NEARBYINT (box->y2);
return;
}
/* The aim here is that for a given rectangle defined with floating point
* coordinates we want to determine a stable quantized size in pixels
* that doesn't vary due to the original box's sub-pixel position.

View File

@ -677,7 +677,7 @@ stop_toggle_slowkeys (ClutterInputDeviceEvdev *device)
}
static void
handle_togglekeys_press (ClutterEvent *event,
handle_enablekeys_press (ClutterEvent *event,
ClutterInputDeviceEvdev *device)
{
if (event->key.keyval == XKB_KEY_Shift_L || event->key.keyval == XKB_KEY_Shift_R)
@ -699,7 +699,7 @@ handle_togglekeys_press (ClutterEvent *event,
}
static void
handle_togglekeys_release (ClutterEvent *event,
handle_enablekeys_release (ClutterEvent *event,
ClutterInputDeviceEvdev *device)
{
if (event->key.keyval == XKB_KEY_Shift_L || event->key.keyval == XKB_KEY_Shift_R)
@ -1133,9 +1133,14 @@ clutter_input_device_evdev_process_kbd_a11y_event (ClutterEvent *e
if (event->key.flags & CLUTTER_EVENT_FLAG_INPUT_METHOD)
goto emit_event;
if (!device_evdev->a11y_flags & CLUTTER_A11Y_KEYBOARD_ENABLED)
if (!(device_evdev->a11y_flags & CLUTTER_A11Y_KEYBOARD_ENABLED))
goto emit_event;
if (event->type == CLUTTER_KEY_PRESS)
handle_enablekeys_press (event, device_evdev);
else
handle_enablekeys_release (event, device_evdev);
if (device_evdev->a11y_flags & CLUTTER_A11Y_MOUSE_KEYS_ENABLED)
{
if (event->type == CLUTTER_KEY_PRESS &&
@ -1146,14 +1151,6 @@ clutter_input_device_evdev_process_kbd_a11y_event (ClutterEvent *e
return; /* swallow event */
}
if (device_evdev->a11y_flags & CLUTTER_A11Y_TOGGLE_KEYS_ENABLED)
{
if (event->type == CLUTTER_KEY_PRESS)
handle_togglekeys_press (event, device_evdev);
else
handle_togglekeys_release (event, device_evdev);
}
if ((device_evdev->a11y_flags & CLUTTER_A11Y_BOUNCE_KEYS_ENABLED) &&
(get_debounce_delay (device) != 0))
{

View File

@ -79,6 +79,9 @@ struct _ClutterKeymapX11
guint current_cache_serial;
DirectionCacheEntry group_direction_cache[4];
int current_group;
GHashTable *reserved_keycodes;
GQueue *available_keycodes;
#endif
guint caps_lock_state : 1;
@ -441,16 +444,100 @@ clutter_keymap_x11_set_property (GObject *gobject,
}
}
#ifdef HAVE_XKB
static void
clutter_keymap_x11_refresh_reserved_keycodes (ClutterKeymapX11 *keymap_x11)
{
Display *dpy = clutter_x11_get_default_display ();
GHashTableIter iter;
gpointer key, value;
g_hash_table_iter_init (&iter, keymap_x11->reserved_keycodes);
while (g_hash_table_iter_next (&iter, &key, &value))
{
guint reserved_keycode = GPOINTER_TO_UINT (key);
guint reserved_keysym = GPOINTER_TO_UINT (value);
guint actual_keysym = XkbKeycodeToKeysym (dpy, reserved_keycode, 0, 0);
/* If an available keycode is no longer mapped to the stored keysym, then
* the keycode should not be considered available anymore and should be
* removed both from the list of available and reserved keycodes.
*/
if (reserved_keysym != actual_keysym)
{
g_hash_table_iter_remove (&iter);
g_queue_remove (keymap_x11->available_keycodes, key);
}
}
}
static gboolean
clutter_keymap_x11_replace_keycode (ClutterKeymapX11 *keymap_x11,
KeyCode keycode,
KeySym keysym)
{
if (CLUTTER_BACKEND_X11 (keymap_x11->backend)->use_xkb)
{
Display *dpy = clutter_x11_get_default_display ();
XkbDescPtr xkb = get_xkb (keymap_x11);
XkbMapChangesRec changes;
XFlush (dpy);
xkb->device_spec = XkbUseCoreKbd;
memset (&changes, 0, sizeof(changes));
if (keysym != NoSymbol)
{
int types[XkbNumKbdGroups] = { XkbOneLevelIndex };
XkbChangeTypesOfKey (xkb, keycode, 1, XkbGroup1Mask, types, &changes);
XkbKeySymEntry (xkb, keycode, 0, 0) = keysym;
}
else
{
/* Reset to NoSymbol */
XkbChangeTypesOfKey (xkb, keycode, 0, XkbGroup1Mask, NULL, &changes);
}
changes.changed = XkbKeySymsMask | XkbKeyTypesMask;
changes.first_key_sym = keycode;
changes.num_key_syms = 1;
changes.first_type = 0;
changes.num_types = xkb->map->num_types;
XkbChangeMap (dpy, xkb, &changes);
XFlush (dpy);
return TRUE;
}
return FALSE;
}
#endif
static void
clutter_keymap_x11_finalize (GObject *gobject)
{
ClutterKeymapX11 *keymap;
ClutterEventTranslator *translator;
GHashTableIter iter;
gpointer key, value;
keymap = CLUTTER_KEYMAP_X11 (gobject);
translator = CLUTTER_EVENT_TRANSLATOR (keymap);
#ifdef HAVE_XKB
clutter_keymap_x11_refresh_reserved_keycodes (keymap);
g_hash_table_iter_init (&iter, keymap->reserved_keycodes);
while (g_hash_table_iter_next (&iter, &key, &value))
{
guint keycode = GPOINTER_TO_UINT (key);
clutter_keymap_x11_replace_keycode (keymap, keycode, NoSymbol);
}
g_hash_table_destroy (keymap->reserved_keycodes);
g_queue_free (keymap->available_keycodes);
_clutter_backend_remove_event_translator (keymap->backend, translator);
if (keymap->xkb_desc != NULL)
@ -460,6 +547,7 @@ clutter_keymap_x11_finalize (GObject *gobject)
G_OBJECT_CLASS (clutter_keymap_x11_parent_class)->finalize (gobject);
}
static void
clutter_keymap_x11_class_init (ClutterKeymapX11Class *klass)
{
@ -483,6 +571,11 @@ clutter_keymap_x11_init (ClutterKeymapX11 *keymap)
{
keymap->current_direction = PANGO_DIRECTION_NEUTRAL;
keymap->current_group = -1;
#ifdef HAVE_XKB
keymap->reserved_keycodes = g_hash_table_new (NULL, NULL);
keymap->available_keycodes = g_queue_new ();
#endif
}
static ClutterTranslateReturn
@ -766,6 +859,80 @@ clutter_keymap_x11_get_entries_for_keyval (ClutterKeymapX11 *keymap_x11,
}
}
#ifdef HAVE_XKB
static guint
clutter_keymap_x11_get_available_keycode (ClutterKeymapX11 *keymap_x11)
{
if (CLUTTER_BACKEND_X11 (keymap_x11->backend)->use_xkb)
{
clutter_keymap_x11_refresh_reserved_keycodes (keymap_x11);
if (g_hash_table_size (keymap_x11->reserved_keycodes) < 5)
{
Display *dpy = clutter_x11_get_default_display ();
XkbDescPtr xkb = get_xkb (keymap_x11);
guint i;
for (i = xkb->max_key_code; i >= xkb->min_key_code; --i)
{
if (XkbKeycodeToKeysym (dpy, i, 0, 0) == NoSymbol)
return i;
}
}
return GPOINTER_TO_UINT (g_queue_pop_head (keymap_x11->available_keycodes));
}
return 0;
}
#endif
gboolean clutter_keymap_x11_reserve_keycode (ClutterKeymapX11 *keymap_x11,
guint keyval,
guint *keycode_out)
{
g_return_val_if_fail (CLUTTER_IS_KEYMAP_X11 (keymap_x11), FALSE);
g_return_val_if_fail (keyval != 0, FALSE);
g_return_val_if_fail (keycode_out != NULL, FALSE);
#ifdef HAVE_XKB
*keycode_out = clutter_keymap_x11_get_available_keycode (keymap_x11);
if (*keycode_out == NoSymbol)
{
g_warning ("Cannot reserve a keycode for keyval %d: no available keycode", keyval);
return FALSE;
}
if (!clutter_keymap_x11_replace_keycode (keymap_x11, *keycode_out, keyval))
{
g_warning ("Failed to remap keycode %d to keyval %d", *keycode_out, keyval);
return FALSE;
}
g_hash_table_insert (keymap_x11->reserved_keycodes, GUINT_TO_POINTER (*keycode_out), GUINT_TO_POINTER (keyval));
g_queue_remove (keymap_x11->available_keycodes, GUINT_TO_POINTER (*keycode_out));
return TRUE;
#else
return FALSE;
#endif
}
void clutter_keymap_x11_release_keycode_if_needed (ClutterKeymapX11 *keymap_x11,
guint keycode)
{
g_return_if_fail (CLUTTER_IS_KEYMAP_X11 (keymap_x11));
#ifdef HAVE_XKB
if (!g_hash_table_contains (keymap_x11->reserved_keycodes, GUINT_TO_POINTER (keycode)) ||
g_queue_index (keymap_x11->available_keycodes, GUINT_TO_POINTER (keycode)) != -1)
return;
g_queue_push_tail (keymap_x11->available_keycodes, GUINT_TO_POINTER (keycode));
#endif
}
void
clutter_keymap_x11_latch_modifiers (ClutterKeymapX11 *keymap_x11,
uint32_t level,
@ -838,6 +1005,26 @@ clutter_keymap_x11_keycode_for_keyval (ClutterKeymapX11 *keymap_x11,
}
}
if (!found)
{
GHashTableIter iter;
gpointer key, value;
g_hash_table_iter_init (&iter, keymap_x11->reserved_keycodes);
while (!found && g_hash_table_iter_next (&iter, &key, &value))
{
guint reserved_keycode = GPOINTER_TO_UINT (key);
guint reserved_keysym = GPOINTER_TO_UINT (value);
if (keyval == reserved_keysym)
{
*keycode_out = reserved_keycode;
*level_out = 0;
found = TRUE;
}
}
}
g_free (keys);
return found;
}

View File

@ -58,7 +58,11 @@ gboolean clutter_keymap_x11_keycode_for_keyval (ClutterKeymapX11 *keymap_x11,
void clutter_keymap_x11_latch_modifiers (ClutterKeymapX11 *keymap_x11,
uint32_t level,
gboolean enable);
gboolean clutter_keymap_x11_reserve_keycode (ClutterKeymapX11 *keymap_x11,
guint keyval,
guint *keycode_out);
void clutter_keymap_x11_release_keycode_if_needed (ClutterKeymapX11 *keymap_x11,
guint keycode);
G_END_DECLS
#endif /* __CLUTTER_KEYMAP_X11_H__ */

View File

@ -143,8 +143,13 @@ clutter_virtual_input_device_x11_notify_keyval (ClutterVirtualInputDevice *virtu
if (!clutter_keymap_x11_keycode_for_keyval (keymap, keyval, &keycode, &level))
{
g_warning ("No keycode found for keyval %x in current group", keyval);
return;
level = 0;
if (!clutter_keymap_x11_reserve_keycode (keymap, keyval, &keycode))
{
g_warning ("No keycode found for keyval %x in current group", keyval);
return;
}
}
if (!_clutter_keymap_x11_get_is_modifier (keymap, keycode) &&
@ -155,9 +160,13 @@ clutter_virtual_input_device_x11_notify_keyval (ClutterVirtualInputDevice *virtu
(KeyCode) keycode,
key_state == CLUTTER_KEY_STATE_PRESSED, 0);
if (!_clutter_keymap_x11_get_is_modifier (keymap, keycode) &&
key_state == CLUTTER_KEY_STATE_RELEASED)
clutter_keymap_x11_latch_modifiers (keymap, level, FALSE);
if (key_state == CLUTTER_KEY_STATE_RELEASED)
{
if (!_clutter_keymap_x11_get_is_modifier (keymap, keycode))
clutter_keymap_x11_latch_modifiers (keymap, level, FALSE);
clutter_keymap_x11_release_keycode_if_needed (keymap, keycode);
}
}
static void

View File

@ -230,13 +230,13 @@ paint_cb (ClutterStage *stage,
gboolean *was_painted = data;
/* old shader effect */
g_assert_cmpint (get_pixel (50, 50), ==, 0xff0000);
g_assert_cmpint (get_pixel (0, 25), ==, 0xff0000);
/* new shader effect */
g_assert_cmpint (get_pixel (150, 50), ==, 0x00ffff);
g_assert_cmpint (get_pixel (100, 25), ==, 0x00ffff);
/* another new shader effect */
g_assert_cmpint (get_pixel (250, 50), ==, 0xff00ff);
g_assert_cmpint (get_pixel (200, 25), ==, 0xff00ff);
/* new shader effect */
g_assert_cmpint (get_pixel (350, 50), ==, 0x00ffff);
g_assert_cmpint (get_pixel (300, 25), ==, 0x00ffff);
*was_painted = TRUE;
}

View File

@ -492,9 +492,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_foreach (pipeline->layer_differences,
@ -508,6 +505,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

@ -94,6 +94,7 @@ cogl_texture_new_with_size (unsigned int width,
if (!cogl_texture_allocate (tex, &skip_error))
{
cogl_error_free (skip_error);
skip_error = NULL;
cogl_object_unref (tex);
tex = NULL;
}

View File

@ -2,7 +2,7 @@ AC_PREREQ(2.62)
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [30])
m4_define([mutter_micro_version], [1])
m4_define([mutter_micro_version], [2])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])

View File

@ -13,9 +13,9 @@ msgid ""
msgstr ""
"Project-Id-Version: mutter master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n"
"POT-Creation-Date: 2018-07-07 09:58+0000\n"
"PO-Revision-Date: 2018-08-04 19:59+0200\n"
"Last-Translator: Mario Blättermann <mario.blaettermann@gmail.com>\n"
"POT-Creation-Date: 2019-08-06 00:49+0000\n"
"PO-Revision-Date: 2019-09-05 23:42+0200\n"
"Last-Translator: Christian Kirbach <christian.kirbach@gmail.com>\n"
"Language-Team: Deutsch <gnome-de@gnome.org>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
@ -152,13 +152,15 @@ msgstr "Zur Arbeitsfläche 4 wechseln"
msgid "Switch to last workspace"
msgstr "Zur letzten Arbeitsfläche wechseln"
# Wechsel der Arbeitsfläche. Es wird nichts verschoben.
#: data/50-mutter-navigation.xml:123
msgid "Move to workspace above"
msgstr "Auf Arbeitsfläche darüber verschieben"
msgstr "Zur Arbeitsfläche darüber wechseln"
# Wechsel der Arbeitsfläche. Es wird nichts verschoben.
#: data/50-mutter-navigation.xml:126
msgid "Move to workspace below"
msgstr "Auf Arbeitsfläche darunter verschieben"
msgstr "Zur Arbeitsfläche darunter wechseln"
#: data/50-mutter-system.xml:6 data/50-mutter-wayland.xml:6
msgid "System"

View File

@ -7,14 +7,14 @@
# Pablo Gonzalo del Campo <pablodc@bigfoot.com>,2002,2003.
# Francisco Javier F. Serrador <serrador@cvs.gnome.org>, 2004, 2005, 2006.
# Jorge González <jorgegonz@svn.gnome.org>, 2007, 2008, 2009, 2010, 2011.
# Daniel Mustieles <daniel.mustieles@gmail.com>, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018.
# Daniel Mustieles <daniel.mustieles@gmail.com>, 2011-2019.
#
msgid ""
msgstr ""
"Project-Id-Version: mutter.master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n"
"POT-Creation-Date: 2018-07-07 09:58+0000\n"
"PO-Revision-Date: 2018-07-23 12:31+0200\n"
"POT-Creation-Date: 2019-06-13 16:46+0000\n"
"PO-Revision-Date: 2019-06-20 09:25+0200\n"
"Last-Translator: Daniel Mustieles <daniel.mustieles@gmail.com>\n"
"Language-Team: es <gnome-es-list@gnome.org>\n"
"Language: es\n"
@ -22,7 +22,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Gtranslator 2.91.6\n"
"X-Generator: Gtranslator 3.32.0\n"
#: data/50-mutter-navigation.xml:6
msgid "Navigation"
@ -397,7 +397,6 @@ msgid "Enable experimental features"
msgstr "Activar las características experimentales"
#: data/org.gnome.mutter.gschema.xml.in:108
#, fuzzy
#| msgid ""
#| "To enable experimental features, add the feature keyword to the list. "
#| "Whether the feature requires restarting the compositor depends on the "
@ -429,9 +428,7 @@ msgstr ""
"manera predeterminada de disponer monitores lógicos en un espacio lógico de "
"coordenadas de píxeles, al escalar framebuffers de monitores framebuffers en "
"lugar del contenido de ventana, para administrar monitores HiDPI. No "
"requiere un reinicio. • \"remote-desktop\" — activa el escritorio remoto. "
"Para soportarlo con compartición de pantalla es necesario activar \"screen-"
"cast\" • \"screen-cast\" — activa el soporte de compartición de pantalla."
"requiere un reinicio."
#: data/org.gnome.mutter.gschema.xml.in:141
msgid "Select window from tab popup"
@ -513,6 +510,11 @@ msgid ""
"window or be among the applications white-listed in key “xwayland-grab-"
"access-rules”."
msgstr ""
"Permitir que las pulsaciones del teclado emitidas por aplicaciones X11 "
"ejecutándose en XWayland se tengan en cuenta. Para que una pulsación X11 se "
"tenga en cuenta en Wayland el cliente debe o bien enviar un ClientMessage "
"específico de X11 a la ventana raíz o estar en la lista blanca de "
"aplicaciones en la clave “xwayland-grab-access-rules”."
#: data/org.gnome.mutter.wayland.gschema.xml.in:77
msgid "Xwayland applications allowed to issue keyboard grabs"
@ -531,11 +533,20 @@ msgid ""
"using the specific keyboard shortcut defined by the keybinding key “restore-"
"shortcuts”."
msgstr ""
"Lista los nombres o las clases de recursos de ventanas X11 permitidas o no "
"para emitir pulsaciones de teclado X11 en XWayland. El nombre o la clase del "
"recurso de una ventana X11 dada se puede obtener usando el comando “xprop "
"WM_CLASS”. Se soportan los comodines «*» y «?». Los valores que empiecen por "
"«!» están en lista negra, que tiene prioridad sobre la lista blanca, para "
"revocar aplicaciones de la lista predeterminada del sistema. Esta lista "
"incluye las siguientes aplicaciones: “@XWAYLAND_GRAB_DEFAULT_ACCESS_RULES@”. "
"Los usuarios pueden romper una pulsación existente usando el atajo "
"específico del teclado definido por la clave “restore-shortcuts”."
#. TRANSLATORS: This string refers to a button that switches between
#. * different modes.
#.
#: src/backends/meta-input-settings.c:2325
#: src/backends/meta-input-settings.c:2310
#, c-format
msgid "Mode Switch (Group %d)"
msgstr "Cambiar modo (grupo %d)"
@ -543,37 +554,37 @@ msgstr "Cambiar modo (grupo %d)"
#. TRANSLATORS: This string refers to an action, cycles drawing tablets'
#. * mapping through the available outputs.
#.
#: src/backends/meta-input-settings.c:2348
#: src/backends/meta-input-settings.c:2333
msgid "Switch monitor"
msgstr "Cambiar monitor"
#: src/backends/meta-input-settings.c:2350
#: src/backends/meta-input-settings.c:2335
msgid "Show on-screen help"
msgstr "Mostrar la ayuda en pantalla"
#: src/backends/meta-monitor-manager.c:907
#: src/backends/meta-monitor-manager.c:886
msgid "Built-in display"
msgstr "Pantalla integrada"
#: src/backends/meta-monitor-manager.c:930
#: src/backends/meta-monitor-manager.c:909
msgid "Unknown"
msgstr "Desconocida"
#: src/backends/meta-monitor-manager.c:932
#: src/backends/meta-monitor-manager.c:911
msgid "Unknown Display"
msgstr "Pantalla desconocida"
#. TRANSLATORS: this is a monitor vendor name, followed by a
#. * size in inches, like 'Dell 15"'
#.
#: src/backends/meta-monitor-manager.c:940
#: src/backends/meta-monitor-manager.c:919
#, c-format
msgid "%s %s"
msgstr "%s %s"
#. This probably means that a non-WM compositor like xcompmgr is running;
#. * we have no way to get it to exit
#: src/compositor/compositor.c:481
#: src/compositor/compositor.c:507
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display “%s”."
@ -679,7 +690,7 @@ msgstr "Imprimir versión"
msgid "Mutter plugin to use"
msgstr "Complemento de mutter que usar"
#: src/core/prefs.c:1915
#: src/core/prefs.c:1787
#, c-format
msgid "Workspace %d"
msgstr "Área de trabajo %d"
@ -693,7 +704,7 @@ msgstr "Mutter fue compilado sin soporte para modo prolijo\n"
msgid "Mode Switch: Mode %d"
msgstr "Cambiar modo: modo %d"
#: src/x11/meta-x11-display.c:666
#: src/x11/meta-x11-display.c:672
#, c-format
msgid ""
"Display “%s” already has a window manager; try using the --replace option to "
@ -702,16 +713,16 @@ msgstr ""
"La pantalla «%s» ya tiene un gestor de ventanas; pruebe a usar la opción «--"
"replace» para reemplazar el gestor de ventanas activo."
#: src/x11/meta-x11-display.c:1010
#: src/x11/meta-x11-display.c:1016
msgid "Failed to initialize GDK\n"
msgstr "Falló al inicializar GDK\n"
#: src/x11/meta-x11-display.c:1034
#: src/x11/meta-x11-display.c:1040
#, c-format
msgid "Failed to open X Window System display “%s”\n"
msgstr "Ocurrió un error al abrir la pantalla de X Window System «%s»\n"
#: src/x11/meta-x11-display.c:1117
#: src/x11/meta-x11-display.c:1123
#, c-format
msgid "Screen %d on display “%s” is invalid\n"
msgstr "La ventana %d en la pantalla «%s» no es válida\n"

282
po/eu.po
View File

@ -4,21 +4,20 @@
#
# Hizkuntza Politikarako Sailburuordetza <hizpol@ej-gv.es>, 2004.
# Iñaki Larrañaga Murgoitio <dooteo@zundan.com>, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011.
# Iñaki Larrañaga Murgoitio <dooteo@zundan.com>, 2012, 2013, 2014, 2015, 2016, 2017.
# Iñaki Larrañaga Murgoitio <dooteo@zundan.com>, 2012, 2013, 2014, 2015, 2016, 2017, 2018.
msgid ""
msgstr ""
"Project-Id-Version: mutter master\n"
"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?"
"product=mutter&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2017-08-21 04:46+0000\n"
"PO-Revision-Date: 2017-08-27 16:47+0200\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n"
"POT-Creation-Date: 2018-10-22 16:18+0000\n"
"PO-Revision-Date: 2018-12-06 13:05+0100\n"
"Last-Translator: Iñaki Larrañaga Murgoitio <dooteo@zundan.com>\n"
"Language-Team: Basque <librezale@librezale.eus>\n"
"Language: eu\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Lokalize 1.5\n"
"X-Generator: Lokalize 2.0\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: data/50-mutter-navigation.xml:6
@ -46,134 +45,118 @@ msgid "Move window to last workspace"
msgstr "Eraman leihoa azkeneko laneko areara"
#: data/50-mutter-navigation.xml:24
msgid "Move window one workspace to the left"
msgstr "Eraman leihoa laneko area bat ezkerrera"
#: data/50-mutter-navigation.xml:27
msgid "Move window one workspace to the right"
msgstr "Eraman leihoa laneko area bat eskuinera"
#: data/50-mutter-navigation.xml:30
msgid "Move window one workspace up"
msgstr "Eraman leihoa laneko area bat gora"
#: data/50-mutter-navigation.xml:33
#: data/50-mutter-navigation.xml:27
msgid "Move window one workspace down"
msgstr "Eraman leihoa laneko area bat behera"
#: data/50-mutter-navigation.xml:36
#: data/50-mutter-navigation.xml:30
msgid "Move window one monitor to the left"
msgstr "Eraman leihoa monitore bat ezkerrera"
#: data/50-mutter-navigation.xml:39
#: data/50-mutter-navigation.xml:33
msgid "Move window one monitor to the right"
msgstr "Eraman leihoa monitore bat eskuinera"
#: data/50-mutter-navigation.xml:42
#: data/50-mutter-navigation.xml:36
msgid "Move window one monitor up"
msgstr "Eraman leihoa monitore bat gora"
#: data/50-mutter-navigation.xml:45
#: data/50-mutter-navigation.xml:39
msgid "Move window one monitor down"
msgstr "Eraman leihoa monitore bat behera"
#: data/50-mutter-navigation.xml:49
#: data/50-mutter-navigation.xml:43
msgid "Switch applications"
msgstr "Aldatu aplikazioz"
#: data/50-mutter-navigation.xml:54
#: data/50-mutter-navigation.xml:48
msgid "Switch to previous application"
msgstr "Aldatu aurreko aplikaziora"
#: data/50-mutter-navigation.xml:58
#: data/50-mutter-navigation.xml:52
msgid "Switch windows"
msgstr "Aldatu leihoz"
#: data/50-mutter-navigation.xml:63
#: data/50-mutter-navigation.xml:57
msgid "Switch to previous window"
msgstr "Aldatu aurreko leihora"
#: data/50-mutter-navigation.xml:67
#: data/50-mutter-navigation.xml:61
msgid "Switch windows of an application"
msgstr "Aldatu aplikazio baten leihoen artean"
#: data/50-mutter-navigation.xml:72
#: data/50-mutter-navigation.xml:66
msgid "Switch to previous window of an application"
msgstr "Aldatu aplikazio baten aurreko leihora"
#: data/50-mutter-navigation.xml:76
#: data/50-mutter-navigation.xml:70
msgid "Switch system controls"
msgstr "Aldatu sistemaren kontrolak"
#: data/50-mutter-navigation.xml:81
#: data/50-mutter-navigation.xml:75
msgid "Switch to previous system control"
msgstr "Aldatu aurreko sistemaren kontrolera"
#: data/50-mutter-navigation.xml:85
#: data/50-mutter-navigation.xml:79
msgid "Switch windows directly"
msgstr "Aldatu leihoa zuzenean"
#: data/50-mutter-navigation.xml:90
#: data/50-mutter-navigation.xml:84
msgid "Switch directly to previous window"
msgstr "Aldatu zuzenean aurreko leihora"
#: data/50-mutter-navigation.xml:94
#: data/50-mutter-navigation.xml:88
msgid "Switch windows of an app directly"
msgstr "Aldatu aplikazio baten leihoa zuzenean"
#: data/50-mutter-navigation.xml:99
#: data/50-mutter-navigation.xml:93
msgid "Switch directly to previous window of an app"
msgstr "Aldatu zuzenean aplik. baten aurreko leihora"
#: data/50-mutter-navigation.xml:103
#: data/50-mutter-navigation.xml:97
msgid "Switch system controls directly"
msgstr "Aldatu sistemaren kontrolak zuzenean"
#: data/50-mutter-navigation.xml:108
#: data/50-mutter-navigation.xml:102
msgid "Switch directly to previous system control"
msgstr "Aldatu zuzenean aurreko sistemaren kontrolera"
#: data/50-mutter-navigation.xml:111
#: data/50-mutter-navigation.xml:105
msgid "Hide all normal windows"
msgstr "Ezkutatu leiho arrunt guztiak"
#: data/50-mutter-navigation.xml:114
#: data/50-mutter-navigation.xml:108
msgid "Switch to workspace 1"
msgstr "Aldatu 1. laneko areara"
#: data/50-mutter-navigation.xml:117
#: data/50-mutter-navigation.xml:111
msgid "Switch to workspace 2"
msgstr "Aldatu 2. laneko areara"
#: data/50-mutter-navigation.xml:120
#: data/50-mutter-navigation.xml:114
msgid "Switch to workspace 3"
msgstr "Aldatu 3. laneko areara"
#: data/50-mutter-navigation.xml:123
#: data/50-mutter-navigation.xml:117
msgid "Switch to workspace 4"
msgstr "Aldatu 4. laneko areara"
#: data/50-mutter-navigation.xml:126
#: data/50-mutter-navigation.xml:120
msgid "Switch to last workspace"
msgstr "Aldatu azkeneko laneko areara"
#: data/50-mutter-navigation.xml:129
msgid "Move to workspace left"
msgstr "Eraman ezkerreko laneko areara"
#: data/50-mutter-navigation.xml:132
msgid "Move to workspace right"
msgstr "Eraman eskuineko laneko areara"
#: data/50-mutter-navigation.xml:135
#: data/50-mutter-navigation.xml:123
msgid "Move to workspace above"
msgstr "Eraman gaineko laneko areara"
#: data/50-mutter-navigation.xml:138
#: data/50-mutter-navigation.xml:126
msgid "Move to workspace below"
msgstr "Eraman azpiko laneko areara"
#: data/50-mutter-system.xml:6
#: data/50-mutter-system.xml:6 data/50-mutter-wayland.xml:6
msgid "System"
msgstr "Sistema"
@ -185,6 +168,10 @@ msgstr "Erakutsi gonbitea komandoa exekutatzeko"
msgid "Show the activities overview"
msgstr "Erakutsi jardueren aurkezpen orokorra"
#: data/50-mutter-wayland.xml:8
msgid "Restore the keyboard shortcuts"
msgstr "Leheneratu laster-teklak"
#: data/50-mutter-windows.xml:6
msgid "Windows"
msgstr "Leihoak"
@ -210,54 +197,50 @@ msgid "Restore window"
msgstr "Leheneratu leihoa"
#: data/50-mutter-windows.xml:18
msgid "Toggle shaded state"
msgstr "Txandakatu bildutako egoera"
#: data/50-mutter-windows.xml:20
msgid "Close window"
msgstr "Itxi leihoa"
#: data/50-mutter-windows.xml:22
#: data/50-mutter-windows.xml:20
msgid "Hide window"
msgstr "Ezkutatu leihoa"
#: data/50-mutter-windows.xml:24
#: data/50-mutter-windows.xml:22
msgid "Move window"
msgstr "Aldatu leihoa lekuz"
#: data/50-mutter-windows.xml:26
#: data/50-mutter-windows.xml:24
msgid "Resize window"
msgstr "Aldatu leihoaren tamaina"
#: data/50-mutter-windows.xml:29
#: data/50-mutter-windows.xml:27
msgid "Toggle window on all workspaces or one"
msgstr "Txandakatu leihoa laneko area guztietan edo bakar batean egotea"
#: data/50-mutter-windows.xml:31
#: data/50-mutter-windows.xml:29
msgid "Raise window if covered, otherwise lower it"
msgstr "Goratu leihoa beste leiho batek estaltzen badu, bestela beheratu"
#: data/50-mutter-windows.xml:33
#: data/50-mutter-windows.xml:31
msgid "Raise window above other windows"
msgstr "Goratu leihoa beste leihoen gainera"
#: data/50-mutter-windows.xml:35
#: data/50-mutter-windows.xml:33
msgid "Lower window below other windows"
msgstr "Beheratu leihoa beste leihoen azpira"
#: data/50-mutter-windows.xml:37
#: data/50-mutter-windows.xml:35
msgid "Maximize window vertically"
msgstr "Maximizatu leihoa bertikalki"
#: data/50-mutter-windows.xml:39
#: data/50-mutter-windows.xml:37
msgid "Maximize window horizontally"
msgstr "Maximizatu leihoa horizontalki"
#: data/50-mutter-windows.xml:43
#: data/50-mutter-windows.xml:41
msgid "View split on left"
msgstr "Ikusi zatia ezkerrean"
#: data/50-mutter-windows.xml:47
#: data/50-mutter-windows.xml:45
msgid "View split on right"
msgstr "Ikusi zatia eskuinean"
@ -417,11 +400,9 @@ msgstr ""
"Eginbideak osatzailea berrabiaraztea behar duen edo ez emandako eginbidearen "
"arabera dago. Ez da derrigorrezkoa edozer eginbide esperimental eskuragarri "
"edo konfiguragarria egotea. Ez uste ezarpen honetan edozer gehitzeak "
"etorkizuneko "
"proba izango denik. Gako erabilgarriak: "
"• “scale-monitor-framebuffer” — honek mutter monitoreen diseinu logikoetara "
"lehenesten du espazioaren koordenatuko pixel logikoetan (leihoaren edukiaren "
"ordez "
"etorkizuneko proba izango denik. Gako erabilgarriak: • “scale-monitor-"
"framebuffer” — honek mutter monitoreen diseinu logikoetara lehenesten du "
"espazioaren koordenatuko pixel logikoetan (leihoaren edukiaren ordez "
"monitorearen framebufferra eskalatzean) HiDPI monitoreak kudeatzeko. Ez du "
"berrabiaraztea eskatzen."
@ -434,7 +415,6 @@ msgid "Cancel tab popup"
msgstr "Utzi laster-fitxa"
#: data/org.gnome.mutter.gschema.xml.in:151
#| msgid "Switch monitor"
msgid "Switch monitor configurations"
msgstr "Aldatu monitorearen konfigurazioak"
@ -494,10 +474,61 @@ msgstr "Aldatu 12. TBra"
msgid "Re-enable shortcuts"
msgstr "Gaitu berriro laster-teklak"
#: data/org.gnome.mutter.wayland.gschema.xml.in:64
msgid "Allow grabs with Xwayland"
msgstr "Baimendu Xwayland-ekin kapturatzea"
#: data/org.gnome.mutter.wayland.gschema.xml.in:65
msgid ""
"Allow keyboard grabs issued by X11 applications running in Xwayland to be "
"taken into account. For a X11 grab to be taken into account under Wayland, "
"the client must also either send a specific X11 ClientMessage to the root "
"window or be among the applications white-listed in key “xwayland-grab-"
"access-rules”."
msgstr ""
"Baimendu Xwayland-en exekutatzen ari diren X11 aplikazioek igorritako "
"teklatuaren kaptura kontutan hartzea. Wayland pean X11 kapturatzea kontutan "
"hartzeko bezeroak X11 ClientMessage zehatz bat bidali behar dio leiho"
" erroari, edo "
"“xwayland-grab-access-rules” gakoaren zerrenda-zuriko aplikazioen artean egon "
"behar da."
#: data/org.gnome.mutter.wayland.gschema.xml.in:77
msgid "Xwayland applications allowed to issue keyboard grabs"
msgstr "Teklatua kaptura dezaketen Xwayland aplikazioak"
#: data/org.gnome.mutter.wayland.gschema.xml.in:78
msgid ""
"List the resource names or resource class of X11 windows either allowed or "
"not allowed to issue X11 keyboard grabs under Xwayland. The resource name or "
"resource class of a given X11 window can be obtained using the command "
"“xprop WM_CLASS”. Wildcards “*” and jokers “?” in the values are supported. "
"Values starting with “!” are blacklisted, which has precedence over the "
"whitelist, to revoke applications from the default system list. The default "
"system list includes the following applications: "
"“@XWAYLAND_GRAB_DEFAULT_ACCESS_RULES@” Users can break an existing grab by "
"using the specific keyboard shortcut defined by the keybinding key “restore-"
"shortcuts”."
msgstr ""
"Xwayland pean teklatuaren kapturatzeko baimendutako edo ez baimendutako "
"X11 leihoen baliabide-izenen edo baliabide-klaseen zerrenda. X11 leihoen"
" baliabide-izenak "
"edo baliabide-klaseak eskuratzeko exekutatu “xprop WM_CLASS” komandoa. "
"“*” eta “?” komodinak onartuta daude. “!” karakterearekin hasten diren"
" balioak "
"zerrenda beltzean daude, zerrenda zurikoei aurre hartzen dietelarik,"
" sistemako "
"zerrenda lehenetsitik aplikazioak errebokatzeko. Sistemako zerrenda"
" lehenetsiak honako "
"aplikazioak ditu: “@XWAYLAND_GRAB_DEFAULT_ACCESS_RULES@” "
"Erabiltzaileek existitzen den kaptura bat hauts dezakete “restore-shortcuts”"
" gakoan "
"zehaztutako laster-tekla zehatza erabiliz."
#. TRANSLATORS: This string refers to a button that switches between
#. * different modes.
#.
#: src/backends/meta-input-settings.c:2151
#: src/backends/meta-input-settings.c:2310
#, c-format
msgid "Mode Switch (Group %d)"
msgstr "Modu aldaketa (%d taldea)"
@ -505,37 +536,37 @@ msgstr "Modu aldaketa (%d taldea)"
#. TRANSLATORS: This string refers to an action, cycles drawing tablets'
#. * mapping through the available outputs.
#.
#: src/backends/meta-input-settings.c:2174
#: src/backends/meta-input-settings.c:2333
msgid "Switch monitor"
msgstr "Aldatu monitorea"
#: src/backends/meta-input-settings.c:2176
#: src/backends/meta-input-settings.c:2335
msgid "Show on-screen help"
msgstr "Erakutsi pantailako laguntza"
#: src/backends/meta-monitor-manager.c:903
#: src/backends/meta-monitor-manager.c:888
msgid "Built-in display"
msgstr "Bertako pantaila"
#: src/backends/meta-monitor-manager.c:926
#: src/backends/meta-monitor-manager.c:911
msgid "Unknown"
msgstr "Ezezaguna"
#: src/backends/meta-monitor-manager.c:928
#: src/backends/meta-monitor-manager.c:913
msgid "Unknown Display"
msgstr "Pantaila ezezaguna"
#. TRANSLATORS: this is a monitor vendor name, followed by a
#. * size in inches, like 'Dell 15"'
#.
#: src/backends/meta-monitor-manager.c:936
#: src/backends/meta-monitor-manager.c:921
#, c-format
msgid "%s %s"
msgstr "%s %s"
#. This probably means that a non-WM compositor like xcompmgr is running;
#. * we have no way to get it to exit
#: src/compositor/compositor.c:476
#: src/compositor/compositor.c:481
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display “%s”."
@ -543,62 +574,65 @@ msgstr ""
"Dagoeneko beste konposatze-kudeatzailea ari da exekutatzen “%2$s“ pantailako "
"%1$i. monitorean."
#: src/core/bell.c:194
#: src/core/bell.c:254
msgid "Bell event"
msgstr "Soinuaren gertaera"
#: src/core/display.c:608
#, c-format
msgid "Failed to open X Window System display “%s”\n"
msgstr "Huts egin du X Window sistemaren “%s“ pantaila irekitzean\n"
#: src/core/main.c:189
#: src/core/main.c:191
msgid "Disable connection to session manager"
msgstr "Desgaitu saio-kudeatzailearen konexioa"
#: src/core/main.c:195
#: src/core/main.c:197
msgid "Replace the running window manager"
msgstr "Ordeztu exekutatzen dagoen leiho-kudeatzailea"
#: src/core/main.c:201
#: src/core/main.c:203
msgid "Specify session management ID"
msgstr "Zehaztu saio-kudeatzailearen IDa"
#: src/core/main.c:206
#: src/core/main.c:208
msgid "X Display to use"
msgstr "X pantaila erabiltzeko"
#: src/core/main.c:212
#: src/core/main.c:214
msgid "Initialize session from savefile"
msgstr "Hasieratu saioa babes-fitxategitik"
#: src/core/main.c:218
#: src/core/main.c:220
msgid "Make X calls synchronous"
msgstr "Egin X deiak sinkronoak izatea"
#: src/core/main.c:225
#: src/core/main.c:227
msgid "Run as a wayland compositor"
msgstr "Exekutatu wayland konposatzaile gisa"
#: src/core/main.c:231
#: src/core/main.c:233
msgid "Run as a nested compositor"
msgstr "Exekutatu habiaratutako konposatzaile gisa"
#: src/core/main.c:239
msgid "Run wayland compositor without starting Xwayland"
msgstr "Exekutatu wayland-en konposatzailea Xwayland abiarazi gabe"
#: src/core/main.c:247
msgid "Run as a full display server, rather than nested"
msgstr "Exekutatu pantaila-zerbitzari oso bezala, habiaratuta baino"
#: src/core/main.c:253
msgid "Run with X11 backend"
msgstr "Exekutatu X11 motorrarekin"
#. Translators: %s is a window title
#: src/core/meta-close-dialog-default.c:147
#: src/core/meta-close-dialog-default.c:148
#, c-format
msgid "“%s” is not responding."
msgstr "'%s'(e)k ez du erantzuten."
#: src/core/meta-close-dialog-default.c:149
#: src/core/meta-close-dialog-default.c:150
msgid "Application is not responding."
msgstr "Aplikazioak ez du erantzuten."
#: src/core/meta-close-dialog-default.c:154
#: src/core/meta-close-dialog-default.c:155
msgid ""
"You may choose to wait a short while for it to continue or force the "
"application to quit entirely."
@ -606,11 +640,11 @@ msgstr ""
"Aukeratu piskatean zai egotea aplikazioak jarraitzeko edo derrigortu "
"aplikazioa erabat ixtea."
#: src/core/meta-close-dialog-default.c:161
#: src/core/meta-close-dialog-default.c:162
msgid "_Force Quit"
msgstr "_Behartu ixtera"
#: src/core/meta-close-dialog-default.c:161
#: src/core/meta-close-dialog-default.c:162
msgid "_Wait"
msgstr "_Itxaron"
@ -637,12 +671,21 @@ msgstr "Erakutsi bertsioa"
msgid "Mutter plugin to use"
msgstr "Mutter-en osagaia erabiltzeko"
#: src/core/prefs.c:1997
#: src/core/prefs.c:1787
#, c-format
msgid "Workspace %d"
msgstr "%d. laneko area"
#: src/core/screen.c:580
#: src/core/util.c:120
msgid "Mutter was compiled without support for verbose mode\n"
msgstr "Mutter modu xehatuaren euskarririk gabe konpilatu da\n"
#: src/wayland/meta-wayland-tablet-pad.c:567
#, c-format
msgid "Mode Switch: Mode %d"
msgstr "Modu aldaketa: %d modua"
#: src/x11/meta-x11-display.c:666
#, c-format
msgid ""
"Display “%s” already has a window manager; try using the --replace option to "
@ -651,21 +694,21 @@ msgstr ""
"“%s“ pantailak badu leiho-kudeatzailea; erabili --replace aukera uneko leiho-"
"kudeatzailea ordezteko."
#: src/core/screen.c:665
#: src/x11/meta-x11-display.c:1010
msgid "Failed to initialize GDK\n"
msgstr "Huts egin du GDK hasieratzean\n"
#: src/x11/meta-x11-display.c:1034
#, c-format
msgid "Failed to open X Window System display “%s”\n"
msgstr "Huts egin du X Window sistemaren “%s“ pantaila irekitzean\n"
#: src/x11/meta-x11-display.c:1117
#, c-format
msgid "Screen %d on display “%s” is invalid\n"
msgstr "“%2$s“ bistaratzeko %1$d pantaila ez da baliozkoa\n"
#: src/core/util.c:120
msgid "Mutter was compiled without support for verbose mode\n"
msgstr "Mutter modu xehatuaren euskarririk gabe konpilatu da\n"
#: src/wayland/meta-wayland-tablet-pad.c:563
#, c-format
msgid "Mode Switch: Mode %d"
msgstr "Modu aldaketa: %d modua"
#: src/x11/session.c:1815
#: src/x11/session.c:1819
msgid ""
"These windows do not support “save current setup” and will have to be "
"restarted manually next time you log in."
@ -673,11 +716,26 @@ msgstr ""
"Leiho hauek ez dute onartzen “gorde uneko konfigurazioa“; eta eskuz "
"berrabiarazi beharko dituzu hurrengo saioa hasten duzunean."
#: src/x11/window-props.c:559
#: src/x11/window-props.c:565
#, c-format
msgid "%s (on %s)"
msgstr "%s (%s)"
#~ msgid "Move window one workspace to the left"
#~ msgstr "Eraman leihoa laneko area bat ezkerrera"
#~ msgid "Move window one workspace to the right"
#~ msgstr "Eraman leihoa laneko area bat eskuinera"
#~ msgid "Move to workspace left"
#~ msgstr "Eraman ezkerreko laneko areara"
#~ msgid "Move to workspace right"
#~ msgstr "Eraman eskuineko laneko areara"
#~ msgid "Toggle shaded state"
#~ msgstr "Txandakatu bildutako egoera"
#~ msgid "Failed to scan themes directory: %s\n"
#~ msgstr "Huts egin du gaien direktorioa aztertzean: %s\n"

View File

@ -14,21 +14,22 @@
# Claude Paroz <claude@2xlibre.net>, 2008-2018.
# Bruno Brouard <annoa.b@gmail.com>, 2011-12.
# Jean-Baptiste Holcroft <jean-baptiste@holcroft.fr>, 2017.
# Charles Monzat <superboa@hotmail.fr>, 2016, 2017.
# Charles Monzat <charles.monzat@numericable.fr>, 2016-2018.
#
msgid ""
msgstr ""
"Project-Id-Version: mutter master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n"
"POT-Creation-Date: 2018-07-07 09:58+0000\n"
"PO-Revision-Date: 2018-07-24 10:22+0200\n"
"Last-Translator: Claude Paroz <claude@2xlibre.net>\n"
"POT-Creation-Date: 2018-11-13 22:58+0000\n"
"PO-Revision-Date: 2018-11-15 22:09+0100\n"
"Last-Translator: Charles Monzat <charles.monzat@numericable.fr>\n"
"Language-Team: français <gnomefr@traduc.org>\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Generator: Gtranslator 3.30.0\n"
#: data/50-mutter-navigation.xml:6
msgid "Navigation"
@ -531,7 +532,7 @@ msgstr ""
"autorisées ou non à émettre des captures clavier sous Xwayland. Le nom ou la "
"classe de ressource dune fenêtre X11 donnée peut être obtenue à laide de "
"la commande « xprop WM_CLASS ». Les caractères joker « * » et « ? » sont "
"acceptées dans les valeurs. Les valeurs commençant pas « ! » sont en liste "
"acceptées dans les valeurs. Les valeurs commençant par « ! » sont en liste "
"noire, qui a priorité sur la liste blanche, pour révoquer les applications "
"de la liste système par défaut. Celle-ci contient les applications "
"suivantes : « @XWAYLAND_GRAB_DEFAULT_ACCESS_RULES@ ». Les utilisateurs "
@ -541,7 +542,7 @@ msgstr ""
#. TRANSLATORS: This string refers to a button that switches between
#. * different modes.
#.
#: src/backends/meta-input-settings.c:2325
#: src/backends/meta-input-settings.c:2310
#, c-format
msgid "Mode Switch (Group %d)"
msgstr "Changement de mode (groupe %d)"
@ -549,30 +550,30 @@ msgstr "Changement de mode (groupe %d)"
#. TRANSLATORS: This string refers to an action, cycles drawing tablets'
#. * mapping through the available outputs.
#.
#: src/backends/meta-input-settings.c:2348
#: src/backends/meta-input-settings.c:2333
msgid "Switch monitor"
msgstr "Changer de moniteur"
#: src/backends/meta-input-settings.c:2350
#: src/backends/meta-input-settings.c:2335
msgid "Show on-screen help"
msgstr "Afficher laide à lécran"
#: src/backends/meta-monitor-manager.c:907
#: src/backends/meta-monitor-manager.c:888
msgid "Built-in display"
msgstr "Affichage intégré"
#: src/backends/meta-monitor-manager.c:930
#: src/backends/meta-monitor-manager.c:911
msgid "Unknown"
msgstr "Inconnu"
#: src/backends/meta-monitor-manager.c:932
#: src/backends/meta-monitor-manager.c:913
msgid "Unknown Display"
msgstr "Affichage inconnu"
#. TRANSLATORS: this is a monitor vendor name, followed by a
#. * size in inches, like 'Dell 15"'
#.
#: src/backends/meta-monitor-manager.c:940
#: src/backends/meta-monitor-manager.c:921
#, c-format
msgid "%s %s"
msgstr "%s %s"
@ -685,7 +686,7 @@ msgstr "Afficher la version"
msgid "Mutter plugin to use"
msgstr "Greffon de Mutter à utiliser"
#: src/core/prefs.c:1915
#: src/core/prefs.c:1787
#, c-format
msgid "Workspace %d"
msgstr "Espace de travail %d"
@ -699,7 +700,7 @@ msgstr "Mutter a été compilé sans la prise en charge du mode bavard\n"
msgid "Mode Switch: Mode %d"
msgstr "Changement de mode : mode %d"
#: src/x11/meta-x11-display.c:666
#: src/x11/meta-x11-display.c:672
#, c-format
msgid ""
"Display “%s” already has a window manager; try using the --replace option to "
@ -708,16 +709,16 @@ msgstr ""
"Laffichage « %s » a déjà un gestionnaire de fenêtres ; essayez dutiliser "
"loption --replace pour remplacer le gestionnaire de fenêtres actuel."
#: src/x11/meta-x11-display.c:1010
#: src/x11/meta-x11-display.c:1016
msgid "Failed to initialize GDK\n"
msgstr "Linitialisation de GDK a échoué\n"
#: src/x11/meta-x11-display.c:1034
#: src/x11/meta-x11-display.c:1040
#, c-format
msgid "Failed to open X Window System display “%s”\n"
msgstr "Impossible douvrir laffichage « %s » du système X Window\n"
#: src/x11/meta-x11-display.c:1117
#: src/x11/meta-x11-display.c:1123
#, c-format
msgid "Screen %d on display “%s” is invalid\n"
msgstr "Lécran %d sur laffichage « %s » nest pas valide\n"

113
po/sk.po
View File

@ -13,8 +13,8 @@ msgid ""
msgstr ""
"Project-Id-Version: mutter\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n"
"POT-Creation-Date: 2018-02-06 04:14+0000\n"
"PO-Revision-Date: 2018-03-17 21:52+0100\n"
"POT-Creation-Date: 2018-10-22 16:18+0000\n"
"PO-Revision-Date: 2018-10-27 21:19+0200\n"
"Last-Translator: Dušan Kazik <prescott66@gmail.com>\n"
"Language-Team: Slovak <gnome-sk-list@gnome.org>\n"
"Language: sk\n"
@ -22,7 +22,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n"
"X-Generator: Poedit 2.0.6\n"
"X-Generator: Poedit 2.2\n"
#: data/50-mutter-navigation.xml:6
msgid "Navigation"
@ -468,29 +468,26 @@ msgid ""
"proof. Currently possible keywords: • “scale-monitor-framebuffer” — makes "
"mutter default to layout logical monitors in a logical pixel coordinate "
"space, while scaling monitor framebuffers instead of window content, to "
"manage HiDPI monitors. Does not require a restart. • “remote-desktop” — "
"enables remote desktop support. To support remote desktop with screen "
"sharing, “screen-cast” must also be enabled. • “screen-cast” — enables "
"screen cast support."
"manage HiDPI monitors. Does not require a restart."
msgstr ""
# summary
#: data/org.gnome.mutter.gschema.xml.in:145
#: data/org.gnome.mutter.gschema.xml.in:141
msgid "Select window from tab popup"
msgstr "Vybrať okno z rozbaľovacej ponuky tabulátora"
# summary
#: data/org.gnome.mutter.gschema.xml.in:150
#: data/org.gnome.mutter.gschema.xml.in:146
msgid "Cancel tab popup"
msgstr "Zrušit rozbaľovaciu ponuku tabulátora"
# PK: predpokladam ze to prepisane medzi tlacidlami
# description
#: data/org.gnome.mutter.gschema.xml.in:155
#: data/org.gnome.mutter.gschema.xml.in:151
msgid "Switch monitor configurations"
msgstr "Prepnúť nastavenia monitorov"
#: data/org.gnome.mutter.gschema.xml.in:160
#: data/org.gnome.mutter.gschema.xml.in:156
msgid "Rotates the built-in monitor configuration"
msgstr "Otočí nastavenie vstavaného monitora"
@ -587,7 +584,7 @@ msgstr ""
#. TRANSLATORS: This string refers to a button that switches between
#. * different modes.
#.
#: src/backends/meta-input-settings.c:2260
#: src/backends/meta-input-settings.c:2310
#, c-format
msgid "Mode Switch (Group %d)"
msgstr "Prepínač režimu (skupina č. %d)"
@ -597,30 +594,30 @@ msgstr "Prepínač režimu (skupina č. %d)"
#. TRANSLATORS: This string refers to an action, cycles drawing tablets'
#. * mapping through the available outputs.
#.
#: src/backends/meta-input-settings.c:2283
#: src/backends/meta-input-settings.c:2333
msgid "Switch monitor"
msgstr "Prepnúť monitor"
#: src/backends/meta-input-settings.c:2285
#: src/backends/meta-input-settings.c:2335
msgid "Show on-screen help"
msgstr "Zobraziť pomocníka na obrazovke"
#: src/backends/meta-monitor-manager.c:900
#: src/backends/meta-monitor-manager.c:888
msgid "Built-in display"
msgstr "Vstavaný displej"
#: src/backends/meta-monitor-manager.c:923
#: src/backends/meta-monitor-manager.c:911
msgid "Unknown"
msgstr "Neznámy"
#: src/backends/meta-monitor-manager.c:925
#: src/backends/meta-monitor-manager.c:913
msgid "Unknown Display"
msgstr "Neznámy displej"
#. TRANSLATORS: this is a monitor vendor name, followed by a
#. * size in inches, like 'Dell 15"'
#.
#: src/backends/meta-monitor-manager.c:933
#: src/backends/meta-monitor-manager.c:921
#, c-format
msgid "%s %s"
msgstr "%s %s"
@ -634,86 +631,84 @@ msgid ""
msgstr ""
"Pre obrazovku č. %i na displeji „%s“ je spustený už iný správca rozloženia."
#: src/core/bell.c:194
#: src/core/bell.c:254
msgid "Bell event"
msgstr "Udalosť zvončeka"
# X window system preloz, napr. system na spravu okien X
#: src/core/display.c:608
#, c-format
msgid "Failed to open X Window System display “%s”\n"
msgstr "Zlyhalo otvorenie displeja systému na správu okien X „%s“\n"
# cmd desc
#: src/core/main.c:190
#: src/core/main.c:191
msgid "Disable connection to session manager"
msgstr "Zakáže pripojenia k správcovi relácií"
# cmd desc
#: src/core/main.c:196
#: src/core/main.c:197
msgid "Replace the running window manager"
msgstr "Nahradí bežiaceho správcu okien"
# cmd desc
#: src/core/main.c:202
#: src/core/main.c:203
msgid "Specify session management ID"
msgstr "Zadá identifikátor správy relácií"
#: src/core/main.c:207
#: src/core/main.c:208
msgid "X Display to use"
msgstr "X displej, ktorý bude použitý"
# cmd desc
#: src/core/main.c:213
#: src/core/main.c:214
msgid "Initialize session from savefile"
msgstr "Inicializuje reláciu z uloženého súboru"
# cmd desc
#: src/core/main.c:219
#: src/core/main.c:220
msgid "Make X calls synchronous"
msgstr "Použije synchrónne volania X"
# cmd desc
#: src/core/main.c:226
#: src/core/main.c:227
msgid "Run as a wayland compositor"
msgstr "Spustí ako kompozitor protokolu wayland"
# cmd desc
#: src/core/main.c:232
#: src/core/main.c:233
msgid "Run as a nested compositor"
msgstr "Spustí ako kompozitor s vnoreným režimom"
#: src/core/main.c:240
#: src/core/main.c:239
msgid "Run wayland compositor without starting Xwayland"
msgstr ""
#: src/core/main.c:247
msgid "Run as a full display server, rather than nested"
msgstr "Spustí ako plnohodnotný zobrazovací server, namiesto vnoreného režimu"
#: src/core/main.c:246
#: src/core/main.c:253
msgid "Run with X11 backend"
msgstr "Spustí s obslužným programom X11"
# %s is a window title
#. Translators: %s is a window title
#: src/core/meta-close-dialog-default.c:147
#: src/core/meta-close-dialog-default.c:148
#, c-format
msgid "“%s” is not responding."
msgstr "„%s“ neodpovedá."
#: src/core/meta-close-dialog-default.c:149
#: src/core/meta-close-dialog-default.c:150
msgid "Application is not responding."
msgstr "Aplikácia neodpovedá."
#: src/core/meta-close-dialog-default.c:154
#: src/core/meta-close-dialog-default.c:155
msgid ""
"You may choose to wait a short while for it to continue or force the "
"application to quit entirely."
msgstr ""
"Môžete chvíľu počkať na pokračovanie aplikácie, alebo ju môžete ukončiť."
#: src/core/meta-close-dialog-default.c:161
#: src/core/meta-close-dialog-default.c:162
msgid "_Force Quit"
msgstr "_Vynútiť ukončenie"
#: src/core/meta-close-dialog-default.c:161
#: src/core/meta-close-dialog-default.c:162
msgid "_Wait"
msgstr "_Počkať"
@ -742,12 +737,21 @@ msgstr "Zobrazí verziu"
msgid "Mutter plugin to use"
msgstr "Použije zásuvný modul Mutter"
#: src/core/prefs.c:1997
#: src/core/prefs.c:1787
#, c-format
msgid "Workspace %d"
msgstr "Pracovný priestor č. %d"
#: src/core/screen.c:583
#: src/core/util.c:120
msgid "Mutter was compiled without support for verbose mode\n"
msgstr "Mutter bol skompilovaný bez výpisu podrobností pri behu\n"
#: src/wayland/meta-wayland-tablet-pad.c:567
#, c-format
msgid "Mode Switch: Mode %d"
msgstr "Prepínač režimu: Režim č. %d"
#: src/x11/meta-x11-display.c:666
#, c-format
msgid ""
"Display “%s” already has a window manager; try using the --replace option to "
@ -756,21 +760,22 @@ msgstr ""
"Displej „%s“ už má správcu okien. Skúste použiť prepínač --replace, aby sa "
"aktuálny správca nahradil."
#: src/core/screen.c:668
#: src/x11/meta-x11-display.c:1010
msgid "Failed to initialize GDK\n"
msgstr "Zlyhala inicializácia rozhrania GDK\n"
# X window system preloz, napr. system na spravu okien X
#: src/x11/meta-x11-display.c:1034
#, c-format
msgid "Failed to open X Window System display “%s”\n"
msgstr "Zlyhalo otvorenie displeja systému na správu okien X „%s“\n"
#: src/x11/meta-x11-display.c:1117
#, c-format
msgid "Screen %d on display “%s” is invalid\n"
msgstr "Obrazovka č. %d na displeji „%s“ nie je platná\n"
#: src/core/util.c:120
msgid "Mutter was compiled without support for verbose mode\n"
msgstr "Mutter bol skompilovaný bez výpisu podrobností pri behu\n"
#: src/wayland/meta-wayland-tablet-pad.c:563
#, c-format
msgid "Mode Switch: Mode %d"
msgstr "Prepínač režimu: Režim č. %d"
#: src/x11/session.c:1818
#: src/x11/session.c:1819
msgid ""
"These windows do not support “save current setup” and will have to be "
"restarted manually next time you log in."
@ -779,7 +784,7 @@ msgstr ""
"prihlásení ich budete musieť znovu spustiť ručne."
# window title; wm_client_machine
#: src/x11/window-props.c:559
#: src/x11/window-props.c:565
#, c-format
msgid "%s (on %s)"
msgstr "%s (na %s)"

View File

@ -15,6 +15,13 @@ dist_stacking_DATA = \
$(srcdir)/tests/stacking/basic-x11.metatest \
$(srcdir)/tests/stacking/basic-wayland.metatest \
$(srcdir)/tests/stacking/closed-transient.metatest \
$(srcdir)/tests/stacking/closed-transient-no-input-no-take-focus-parent.metatest \
$(srcdir)/tests/stacking/closed-transient-no-input-no-take-focus-parents.metatest \
$(srcdir)/tests/stacking/closed-transient-no-input-parent.metatest \
$(srcdir)/tests/stacking/closed-transient-no-input-parent-delayed-focus-default-cancelled.metatest \
$(srcdir)/tests/stacking/closed-transient-no-input-parents.metatest \
$(srcdir)/tests/stacking/closed-transient-no-input-parents-queued-default-focus-destroyed.metatest \
$(srcdir)/tests/stacking/closed-transient-only-take-focus-parents.metatest \
$(srcdir)/tests/stacking/minimized.metatest \
$(srcdir)/tests/stacking/mixed-windows.metatest \
$(srcdir)/tests/stacking/set-parent.metatest \

View File

@ -51,6 +51,14 @@
#define META_TYPE_BACKEND (meta_backend_get_type ())
G_DECLARE_DERIVABLE_TYPE (MetaBackend, meta_backend, META, BACKEND, GObject)
typedef enum
{
META_SEQUENCE_NONE,
META_SEQUENCE_ACCEPTED,
META_SEQUENCE_REJECTED,
META_SEQUENCE_PENDING_END
} MetaSequenceState;
struct _MetaBackendClass
{
GObjectClass parent_class;
@ -73,6 +81,10 @@ struct _MetaBackendClass
int device_id,
uint32_t timestamp);
void (* finish_touch_sequence) (MetaBackend *backend,
ClutterEventSequence *sequence,
MetaSequenceState state);
void (* warp_pointer) (MetaBackend *backend,
int x,
int y);
@ -136,6 +148,10 @@ gboolean meta_backend_ungrab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp);
void meta_backend_finish_touch_sequence (MetaBackend *backend,
ClutterEventSequence *sequence,
MetaSequenceState state);
void meta_backend_warp_pointer (MetaBackend *backend,
int x,
int y);

View File

@ -960,6 +960,20 @@ meta_backend_ungrab_device (MetaBackend *backend,
return META_BACKEND_GET_CLASS (backend)->ungrab_device (backend, device_id, timestamp);
}
/**
* meta_backend_finish_touch_sequence: (skip)
*/
void
meta_backend_finish_touch_sequence (MetaBackend *backend,
ClutterEventSequence *sequence,
MetaSequenceState state)
{
if (META_BACKEND_GET_CLASS (backend)->finish_touch_sequence)
META_BACKEND_GET_CLASS (backend)->finish_touch_sequence (backend,
sequence,
state);
}
/**
* meta_backend_warp_pointer: (skip)
*/

View File

@ -561,9 +561,7 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
g_clear_object (&config);
}
config =
meta_monitor_config_manager_create_for_switch_config (manager->config_manager,
META_MONITOR_SWITCH_CONFIG_ALL_LINEAR);
config = meta_monitor_config_manager_create_linear (manager->config_manager);
if (config)
{
if (!meta_monitor_manager_apply_monitors_config (manager,

View File

@ -87,7 +87,11 @@ meta_screen_cast_monitor_stream_src_get_specs (MetaScreenCastStreamSrc *src,
logical_monitor = meta_monitor_get_logical_monitor (monitor);
mode = meta_monitor_get_current_mode (monitor);
scale = logical_monitor->scale;
if (meta_is_stage_views_scaled ())
scale = logical_monitor->scale;
else
scale = 1.0;
*width = (int) roundf (logical_monitor->rect.width * scale);
*height = (int) roundf (logical_monitor->rect.height * scale);
*frame_rate = meta_monitor_mode_get_refresh_rate (mode);

View File

@ -798,6 +798,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

@ -3342,6 +3342,7 @@ create_renderer_gpu_data_egl_device (MetaRendererNative *renderer_native,
G_IO_ERROR_FAILED,
"Missing EGL extensions required for EGLDevice renderer: %s",
missing_extensions_str);
meta_egl_terminate (egl, egl_display, NULL);
g_free (missing_extensions_str);
g_free (missing_extensions);
return NULL;

View File

@ -60,6 +60,10 @@ struct _MetaBackendX11Private
XSyncAlarm user_active_alarm;
XSyncCounter counter;
int current_touch_replay_sync_serial;
int pending_touch_replay_sync_serial;
Atom touch_replay_sync_atom;
int xinput_opcode;
int xinput_event_base;
int xinput_error_base;
@ -168,6 +172,26 @@ meta_backend_x11_translate_device_event (MetaBackendX11 *x11,
backend_x11_class->translate_device_event (x11, device_event);
}
static void
maybe_translate_touch_replay_pointer_event (MetaBackendX11 *x11,
XIDeviceEvent *device_event)
{
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
if (!device_event->send_event &&
device_event->time != META_CURRENT_TIME &&
priv->current_touch_replay_sync_serial !=
priv->pending_touch_replay_sync_serial &&
XSERVER_TIME_IS_BEFORE (device_event->time, priv->latest_evtime))
{
/* Emulated pointer events received after XIRejectTouch is received
* on a passive touch grab will contain older timestamps, update those
* so we dont get InvalidTime at grabs.
*/
device_event->time = priv->latest_evtime;
}
}
static void
translate_device_event (MetaBackendX11 *x11,
XIDeviceEvent *device_event)
@ -177,19 +201,7 @@ translate_device_event (MetaBackendX11 *x11,
meta_backend_x11_translate_device_event (x11, device_event);
if (!device_event->send_event && device_event->time != META_CURRENT_TIME)
{
if (XSERVER_TIME_IS_BEFORE (device_event->time, priv->latest_evtime))
{
/* Emulated pointer events received after XIRejectTouch is received
* on a passive touch grab will contain older timestamps, update those
* so we dont get InvalidTime at grabs.
*/
device_event->time = priv->latest_evtime;
}
/* Update the internal latest evtime, for any possible later use */
priv->latest_evtime = device_event->time;
}
priv->latest_evtime = device_event->time;
}
static void
@ -254,6 +266,9 @@ maybe_spoof_event_as_stage_event (MetaBackendX11 *x11,
case XI_Motion:
case XI_ButtonPress:
case XI_ButtonRelease:
maybe_translate_touch_replay_pointer_event (x11,
(XIDeviceEvent *) input_event);
/* Intentional fall-through */
case XI_KeyPress:
case XI_KeyRelease:
case XI_TouchBegin:
@ -321,6 +336,17 @@ handle_host_xevent (MetaBackend *backend,
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
gboolean bypass_clutter = FALSE;
switch (event->type)
{
case ClientMessage:
if (event->xclient.window == meta_backend_x11_get_xwindow (x11) &&
event->xclient.message_type == priv->touch_replay_sync_atom)
priv->current_touch_replay_sync_serial = event->xclient.data.l[0];
break;
default:
break;
}
XGetEventData (priv->xdisplay, &event->xcookie);
{
@ -528,6 +554,10 @@ meta_backend_x11_post_init (MetaBackend *backend)
monitor_manager = meta_backend_get_monitor_manager (backend);
g_signal_connect (monitor_manager, "monitors-changed-internal",
G_CALLBACK (on_monitors_changed), backend);
priv->touch_replay_sync_atom = XInternAtom (priv->xdisplay,
"_MUTTER_TOUCH_SEQUENCE_SYNC",
False);
}
static ClutterBackend *
@ -584,6 +614,43 @@ meta_backend_x11_ungrab_device (MetaBackend *backend,
return (ret == Success);
}
static void
meta_backend_x11_finish_touch_sequence (MetaBackend *backend,
ClutterEventSequence *sequence,
MetaSequenceState state)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
int event_mode;
if (state == META_SEQUENCE_ACCEPTED)
event_mode = XIAcceptTouch;
else if (state == META_SEQUENCE_REJECTED)
event_mode = XIRejectTouch;
else
g_return_if_reached ();
XIAllowTouchEvents (priv->xdisplay,
META_VIRTUAL_CORE_POINTER_ID,
clutter_x11_event_sequence_get_touch_detail (sequence),
DefaultRootWindow (priv->xdisplay), event_mode);
if (state == META_SEQUENCE_REJECTED)
{
XClientMessageEvent ev;
ev = (XClientMessageEvent) {
.type = ClientMessage,
.window = meta_backend_x11_get_xwindow (x11),
.message_type = priv->touch_replay_sync_atom,
.format = 32,
.data.l[0] = ++priv->pending_touch_replay_sync_serial,
};
XSendEvent (priv->xdisplay, meta_backend_x11_get_xwindow (x11),
False, 0, (XEvent *) &ev);
}
}
static void
meta_backend_x11_warp_pointer (MetaBackend *backend,
int x,
@ -769,6 +836,7 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
backend_class->post_init = meta_backend_x11_post_init;
backend_class->grab_device = meta_backend_x11_grab_device;
backend_class->ungrab_device = meta_backend_x11_ungrab_device;
backend_class->finish_touch_sequence = meta_backend_x11_finish_touch_sequence;
backend_class->warp_pointer = meta_backend_x11_warp_pointer;
backend_class->get_current_logical_monitor = meta_backend_x11_get_current_logical_monitor;
backend_class->get_keymap = meta_backend_x11_get_keymap;

View File

@ -18,6 +18,9 @@ struct _MetaCompositor
guint pre_paint_func_id;
guint post_paint_func_id;
guint stage_presented_id;
guint stage_after_paint_id;
gint64 server_time_query_time;
gint64 server_time_offset;

View File

@ -91,6 +91,10 @@ on_presented (ClutterStage *stage,
ClutterFrameInfo *frame_info,
MetaCompositor *compositor);
static void
on_top_window_actor_destroyed (MetaWindowActor *window_actor,
MetaCompositor *compositor);
static gboolean
is_modal (MetaDisplay *display)
{
@ -130,9 +134,31 @@ meta_switch_workspace_completed (MetaCompositor *compositor)
void
meta_compositor_destroy (MetaCompositor *compositor)
{
g_signal_handler_disconnect (compositor->stage,
compositor->stage_after_paint_id);
g_signal_handler_disconnect (compositor->stage,
compositor->stage_presented_id);
compositor->stage_after_paint_id = 0;
compositor->stage_presented_id = 0;
compositor->stage = NULL;
clutter_threads_remove_repaint_func (compositor->pre_paint_func_id);
clutter_threads_remove_repaint_func (compositor->post_paint_func_id);
if (compositor->top_window_actor)
{
g_signal_handlers_disconnect_by_func (compositor->top_window_actor,
on_top_window_actor_destroyed,
compositor);
compositor->top_window_actor = NULL;
}
g_clear_pointer (&compositor->window_group, clutter_actor_destroy);
g_clear_pointer (&compositor->top_window_group, clutter_actor_destroy);
g_clear_pointer (&compositor->feedback_group, clutter_actor_destroy);
g_clear_pointer (&compositor->windows, g_list_free);
if (compositor->have_x11_sync_object)
meta_sync_ring_destroy ();
}
@ -502,9 +528,10 @@ meta_compositor_manage (MetaCompositor *compositor)
compositor->stage = meta_backend_get_stage (backend);
g_signal_connect (compositor->stage, "presented",
G_CALLBACK (on_presented),
compositor);
compositor->stage_presented_id =
g_signal_connect (compositor->stage, "presented",
G_CALLBACK (on_presented),
compositor);
/* We use connect_after() here to accomodate code in GNOME Shell that,
* when benchmarking drawing performance, connects to ::after-paint
@ -514,8 +541,9 @@ meta_compositor_manage (MetaCompositor *compositor)
* connections to ::after-paint, connect() vs. connect_after() doesn't
* matter.
*/
g_signal_connect_after (CLUTTER_STAGE (compositor->stage), "after-paint",
G_CALLBACK (after_stage_paint), compositor);
compositor->stage_after_paint_id =
g_signal_connect_after (compositor->stage, "after-paint",
G_CALLBACK (after_stage_paint), compositor);
clutter_stage_set_sync_delay (CLUTTER_STAGE (compositor->stage), META_SYNC_DELAY);

View File

@ -33,6 +33,7 @@
#include <meta/meta-x11-errors.h>
#include "window-private.h"
#include "meta-shaped-texture-private.h"
#include "meta-window-actor-private.h"
#include "meta-cullable.h"
#include "x11/window-x11.h"
#include "x11/meta-x11-display-private.h"
@ -69,11 +70,13 @@ free_damage (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = priv->display;
Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display);
Display *xdisplay;
if (priv->damage == None)
return;
xdisplay = meta_x11_display_get_xdisplay (display->x11_display);
meta_x11_error_trap_push (display->x11_display);
XDamageDestroy (xdisplay, priv->damage);
priv->damage = None;
@ -85,12 +88,14 @@ detach_pixmap (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = priv->display;
Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display);
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
Display *xdisplay;
if (priv->pixmap == None)
return;
xdisplay = meta_x11_display_get_xdisplay (display->x11_display);
/* Get rid of all references to the pixmap before freeing it; it's unclear whether
* you are supposed to be able to free a GLXPixmap after freeing the underlying
* pixmap, but it certainly doesn't work with current DRI/Mesa
@ -353,13 +358,19 @@ meta_surface_actor_x11_is_unredirected (MetaSurfaceActor *actor)
return priv->unredirected;
}
static void
release_x11_resources (MetaSurfaceActorX11 *self)
{
detach_pixmap (self);
free_damage (self);
}
static void
meta_surface_actor_x11_dispose (GObject *object)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (object);
detach_pixmap (self);
free_damage (self);
release_x11_resources (self);
G_OBJECT_CLASS (meta_surface_actor_x11_parent_class)->dispose (object);
}
@ -417,8 +428,7 @@ window_decorated_notify (MetaWindow *window,
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (user_data);
detach_pixmap (self);
free_damage (self);
release_x11_resources (self);
create_damage (self);
}
@ -457,6 +467,10 @@ meta_surface_actor_x11_new (MetaWindow *window)
g_signal_connect_object (priv->window, "notify::decorated",
G_CALLBACK (window_decorated_notify), self, 0);
g_signal_connect_object (meta_window_actor_from_window (window), "destroy",
G_CALLBACK (release_x11_resources), self,
G_CONNECT_SWAPPED);
priv->unredirected = FALSE;
sync_unredirected (self);

View File

@ -471,6 +471,9 @@ meta_window_actor_constructed (GObject *object)
priv->compositor = window->display->compositor;
/* Hang our compositor window state off the MetaWindow for fast retrieval */
meta_window_set_compositor_private (window, object);
meta_window_actor_update_surface (self);
meta_window_actor_update_opacity (self);
@ -1448,9 +1451,6 @@ meta_window_actor_new (MetaWindow *window)
meta_window_actor_sync_actor_geometry (self, priv->window->placed);
/* Hang our compositor window state off the MetaWindow for fast retrieval */
meta_window_set_compositor_private (window, G_OBJECT (self));
if (window->layer == META_LAYER_OVERRIDE_REDIRECT)
window_group = compositor->top_window_group;
else

View File

@ -57,6 +57,7 @@
#include "backends/native/meta-backend-native.h"
#include "backends/x11/meta-backend-x11.h"
#include "backends/meta-stage-private.h"
#include "backends/meta-backend-private.h"
#include "backends/meta-input-settings-private.h"
#include <clutter/x11/clutter-x11.h>
@ -602,27 +603,23 @@ gesture_tracker_state_changed (MetaGestureTracker *tracker,
MetaSequenceState state,
MetaDisplay *display)
{
if (meta_is_wayland_compositor ())
switch (state)
{
if (state == META_SEQUENCE_ACCEPTED)
meta_display_cancel_touch (display);
}
else
{
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
int event_mode;
case META_SEQUENCE_NONE:
case META_SEQUENCE_PENDING_END:
return;
case META_SEQUENCE_ACCEPTED:
meta_display_cancel_touch (display);
if (state == META_SEQUENCE_ACCEPTED)
event_mode = XIAcceptTouch;
else if (state == META_SEQUENCE_REJECTED)
event_mode = XIRejectTouch;
else
return;
/* Intentional fall-through */
case META_SEQUENCE_REJECTED:
{
MetaBackend *backend;
XIAllowTouchEvents (meta_backend_x11_get_xdisplay (backend),
META_VIRTUAL_CORE_POINTER_ID,
clutter_x11_event_sequence_get_touch_detail (sequence),
DefaultRootWindow (display->x11_display->xdisplay), event_mode);
backend = meta_get_backend ();
meta_backend_finish_touch_sequence (backend, sequence, state);
break;
}
}
}

View File

@ -28,6 +28,8 @@
#include <clutter/clutter.h>
#include <meta/window.h>
#include "backends/meta-backend-private.h"
#define META_TYPE_GESTURE_TRACKER (meta_gesture_tracker_get_type ())
#define META_GESTURE_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_GESTURE_TRACKER, MetaGestureTracker))
#define META_GESTURE_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_GESTURE_TRACKER, MetaGestureTrackerClass))
@ -38,13 +40,6 @@
typedef struct _MetaGestureTracker MetaGestureTracker;
typedef struct _MetaGestureTrackerClass MetaGestureTrackerClass;
typedef enum {
META_SEQUENCE_NONE,
META_SEQUENCE_ACCEPTED,
META_SEQUENCE_REJECTED,
META_SEQUENCE_PENDING_END
} MetaSequenceState;
struct _MetaGestureTracker
{
GObject parent_instance;

View File

@ -1183,6 +1183,27 @@ window_contains_point (MetaWindow *window,
return POINT_IN_RECT (root_x, root_y, rect);
}
static gboolean
window_can_get_default_focus (MetaWindow *window)
{
if (window->unmaps_pending > 0)
return FALSE;
if (window->unmanaging)
return FALSE;
if (!(window->input || window->take_focus))
return FALSE;
if (!meta_window_should_be_showing (window))
return FALSE;
if (window->type == META_WINDOW_DOCK)
return FALSE;
return TRUE;
}
static MetaWindow*
get_default_focus_window (MetaStack *stack,
MetaWorkspace *workspace,
@ -1210,24 +1231,12 @@ get_default_focus_window (MetaStack *stack,
if (window == not_this_one)
continue;
if (window->unmaps_pending > 0)
continue;
if (window->unmanaging)
continue;
if (!(window->input || window->take_focus))
continue;
if (!meta_window_should_be_showing (window))
if (!window_can_get_default_focus (window))
continue;
if (must_be_at_point && !window_contains_point (window, root_x, root_y))
continue;
if (window->type == META_WINDOW_DOCK)
continue;
return window;
}
@ -1282,6 +1291,26 @@ meta_stack_list_windows (MetaStack *stack,
return workspace_windows;
}
GList *
meta_stack_get_default_focus_candidates (MetaStack *stack,
MetaWorkspace *workspace)
{
GList *windows = meta_stack_list_windows (stack, workspace);
GList *l;
for (l = windows; l;)
{
GList *next = l->next;
if (!window_can_get_default_focus (l->data))
windows = g_list_delete_link (windows, l);
l = next;
}
return windows;
}
int
meta_stack_windows_cmp (MetaStack *stack,
MetaWindow *window_a,

View File

@ -337,6 +337,21 @@ MetaWindow* meta_stack_get_default_focus_window_at_point (MetaStack *stack,
int root_x,
int root_y);
/**
* meta_stack_get_default_focus_candidates:
* @stack: The stack to examine.
* @workspace: If not %NULL, only windows on this workspace will be
* returned; otherwise all windows in the stack will be
* returned.
*
* Returns all the focus candidate windows in the stack, in order.
*
* Returns: (transfer container) (element-type Meta.Window):
* A #GList of #MetaWindow, in stacking order, honouring layers.
*/
GList * meta_stack_get_default_focus_candidates (MetaStack *stack,
MetaWorkspace *workspace);
/**
* meta_stack_list_windows:
* @stack: The stack to examine.

View File

@ -82,6 +82,7 @@ typedef enum
META_MOVE_RESIZE_UNMAXIMIZE = 1 << 6,
META_MOVE_RESIZE_FORCE_MOVE = 1 << 7,
META_MOVE_RESIZE_WAYLAND_STATE_CHANGED = 1 << 8,
META_MOVE_RESIZE_FORCE_UPDATE_MONITOR = 1 << 9,
} MetaMoveResizeFlags;
typedef enum

View File

@ -121,6 +121,7 @@ static gboolean queue_calc_showing_func (MetaWindow *window,
void *data);
static void meta_window_move_between_rects (MetaWindow *window,
MetaMoveResizeFlags move_resize_flags,
const MetaRectangle *old_area,
const MetaRectangle *new_area);
@ -3638,6 +3639,13 @@ meta_window_activate_full (MetaWindow *window,
{
MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
gboolean allow_workspace_switch;
if (window->unmanaging)
{
g_warning ("Trying to activate unmanaged window '%s'", window->desc);
return;
}
meta_topic (META_DEBUG_FOCUS,
"_NET_ACTIVE_WINDOW message sent for %s at time %u "
"by client type %u.\n",
@ -3865,6 +3873,7 @@ meta_window_update_for_monitors_changed (MetaWindow *window)
* monitors changed and the same index could be refereing
* to a different monitor. */
meta_window_move_between_rects (window,
META_MOVE_RESIZE_FORCE_UPDATE_MONITOR,
&old->rect,
&new->rect);
}
@ -4046,6 +4055,8 @@ meta_window_move_resize_internal (MetaWindow *window,
update_monitor_flags = META_WINDOW_UPDATE_MONITOR_FLAGS_NONE;
if (flags & META_MOVE_RESIZE_USER_ACTION)
update_monitor_flags |= META_WINDOW_UPDATE_MONITOR_FLAGS_USER_OP;
if (flags & META_MOVE_RESIZE_FORCE_UPDATE_MONITOR)
update_monitor_flags |= META_WINDOW_UPDATE_MONITOR_FLAGS_FORCE;
if (window->monitor)
{
@ -4105,6 +4116,7 @@ meta_window_move_frame (MetaWindow *window,
static void
meta_window_move_between_rects (MetaWindow *window,
MetaMoveResizeFlags move_resize_flags,
const MetaRectangle *old_area,
const MetaRectangle *new_area)
{
@ -4128,7 +4140,12 @@ meta_window_move_between_rects (MetaWindow *window,
window->saved_rect.x = window->unconstrained_rect.x;
window->saved_rect.y = window->unconstrained_rect.y;
meta_window_move_resize_now (window);
meta_window_move_resize_internal (window,
move_resize_flags |
META_MOVE_RESIZE_MOVE_ACTION |
META_MOVE_RESIZE_RESIZE_ACTION,
NorthWestGravity,
window->unconstrained_rect);
}
/**
@ -4189,14 +4206,14 @@ meta_window_move_to_monitor (MetaWindow *window,
window->unconstrained_rect.height == 0 ||
!meta_rectangle_overlap (&window->unconstrained_rect, &old_area))
{
meta_window_move_between_rects (window, NULL, &new_area);
meta_window_move_between_rects (window, 0, NULL, &new_area);
}
else
{
if (monitor == window->monitor->number)
return;
meta_window_move_between_rects (window, &old_area, &new_area);
meta_window_move_between_rects (window, 0, &old_area, &new_area);
}
window->preferred_output_winsys_id = window->monitor->winsys_id;

View File

@ -86,6 +86,12 @@ typedef struct _MetaWorkspaceLogicalMonitorData
MetaRectangle logical_monitor_work_area;
} MetaWorkspaceLogicalMonitorData;
typedef struct _MetaWorkspaceFocusableAncestorData
{
MetaWorkspace *workspace;
MetaWindow *out_window;
} MetaWorkspaceFocusableAncestorData;
static MetaWorkspaceLogicalMonitorData *
meta_workspace_get_logical_monitor_data (MetaWorkspace *workspace,
MetaLogicalMonitor *logical_monitor)
@ -1327,13 +1333,20 @@ meta_workspace_focus_default_window (MetaWorkspace *workspace,
}
static gboolean
record_ancestor (MetaWindow *window,
void *data)
find_focusable_ancestor (MetaWindow *window,
gpointer user_data)
{
MetaWindow **result = data;
MetaWorkspaceFocusableAncestorData *data = user_data;
*result = window;
return FALSE; /* quit with the first ancestor we find */
if (!window->unmanaging && (window->input || window->take_focus) &&
meta_window_located_on_workspace (window, data->workspace) &&
meta_window_showing_on_its_workspace (window))
{
data->out_window = window;
return FALSE;
}
return TRUE;
}
/* Focus ancestor of not_this_one if there is one */
@ -1355,11 +1368,15 @@ focus_ancestor_or_top_window (MetaWorkspace *workspace,
if (not_this_one)
{
MetaWindow *ancestor;
ancestor = NULL;
meta_window_foreach_ancestor (not_this_one, record_ancestor, &ancestor);
if (ancestor != NULL &&
meta_window_located_on_workspace (ancestor, workspace) &&
meta_window_showing_on_its_workspace (ancestor))
MetaWorkspaceFocusableAncestorData data;
data = (MetaWorkspaceFocusableAncestorData) {
.workspace = workspace,
};
meta_window_foreach_ancestor (not_this_one, find_focusable_ancestor, &data);
ancestor = data.out_window;
if (ancestor)
{
meta_topic (META_DEBUG_FOCUS,
"Focusing %s, ancestor of %s\n",

View File

@ -0,0 +1,23 @@
new_client 1 x11
create 1/1
show 1/1
create 1/2 csd
set_parent 1/2 1
can_take_focus 1/2 false
accept_focus 1/2 false
show 1/2
create 1/3 csd
set_parent 1/3 2
show 1/3
wait
assert_focused 1/3
assert_stacking 1/1 1/2 1/3
destroy 1/3
wait
assert_focused 1/1
assert_stacking 1/1 1/2

View File

@ -0,0 +1,30 @@
new_client 2 x11
create 2/1
show 2/1
wait
new_client 1 x11
create 1/1
accept_focus 1/1 false
can_take_focus 1/1 false
show 1/1
create 1/2 csd
set_parent 1/2 1
can_take_focus 1/2 false
accept_focus 1/2 false
show 1/2
create 1/3 csd
set_parent 1/3 2
show 1/3
wait
assert_focused 1/3
assert_stacking 2/1 1/1 1/2 1/3
destroy 1/3
wait
assert_stacking 1/1 1/2 2/1
assert_focused 2/1

View File

@ -0,0 +1,36 @@
new_client 2 x11
create 2/1
show 2/1
new_client 1 x11
create 1/1
show 1/1
create 1/2 csd
set_parent 1/2 1
accept_focus 1/2 false
show 1/2
create 1/3 csd
set_parent 1/3 2
show 1/3
wait
assert_focused 1/3
assert_stacking 2/1 1/1 1/2 1/3
destroy 1/3
sleep 10
assert_focused none
assert_stacking 2/1 1/1 1/2
activate 2/1
wait
assert_focused 2/1
assert_stacking 1/1 1/2 2/1
sleep 250
assert_focused 2/1
assert_stacking 1/1 1/2 2/1

View File

@ -0,0 +1,30 @@
new_client 2 x11
create 2/1
show 2/1
new_client 1 x11
create 1/1
show 1/1
create 1/2 csd
set_parent 1/2 1
accept_focus 1/2 false
show 1/2
create 1/3 csd
set_parent 1/3 2
show 1/3
wait
assert_focused 1/3
assert_stacking 2/1 1/1 1/2 1/3
destroy 1/3
dispatch
assert_focused none
assert_stacking 2/1 1/1 1/2
sleep 150
assert_focused 1/1
assert_stacking 2/1 1/1 1/2

View File

@ -0,0 +1,43 @@
new_client 0 x11
create 0/1
show 0/1
new_client 1 x11
create 1/1
show 1/1
create 1/2 csd
set_parent 1/2 1
accept_focus 1/2 false
show 1/2
create 1/3 csd
set_parent 1/3 2
accept_focus 1/3 false
show 1/3
create 1/4 csd
set_parent 1/4 3
accept_focus 1/4 false
show 1/4
create 1/5 csd
set_parent 1/5 3
show 1/5
wait
assert_focused 1/5
assert_stacking 0/1 1/1 1/2 1/3 1/4 1/5
destroy 1/5
dispatch
assert_focused none
assert_stacking 0/1 1/1 1/2 1/3 1/4
destroy 1/2
dispatch
sleep 450
assert_focused 1/1
assert_stacking 0/1 1/1 1/3 1/4

View File

@ -0,0 +1,46 @@
new_client 0 x11
create 0/1
show 0/1
new_client 1 x11
create 1/1
show 1/1
create 1/2 csd
set_parent 1/2 1
accept_focus 1/2 false
show 1/2
create 1/3 csd
set_parent 1/3 2
accept_focus 1/3 false
show 1/3
create 1/4 csd
set_parent 1/4 3
accept_focus 1/4 false
show 1/4
create 1/5 csd
set_parent 1/5 3
show 1/5
wait
assert_focused 1/5
assert_stacking 0/1 1/1 1/2 1/3 1/4 1/5
destroy 1/5
dispatch
assert_focused none
assert_stacking 0/1 1/1 1/2 1/3 1/4
sleep 600
assert_focused 1/1
assert_stacking 0/1 1/1 1/2 1/3 1/4
destroy 1/3
wait
assert_focused 1/1
assert_stacking 0/1 1/1 1/2 1/4

View File

@ -0,0 +1,34 @@
new_client 0 x11
create 0/1
show 0/1
new_client 1 x11
create 1/1
accept_focus 1/1 false
can_take_focus 1/1 true
accept_take_focus 1/1 true
show 1/1
create 1/2 csd
set_parent 1/2 1
accept_focus 1/2 false
can_take_focus 1/2 true
accept_take_focus 1/2 true
show 1/2
create 1/3
set_parent 1/3 2
show 1/3
assert_focused 1/3
assert_stacking 0/1 1/1 1/2 1/3
destroy 1/3
wait
assert_focused 1/2
assert_stacking 0/1 1/1 1/2
sleep 150
assert_focused 1/2
assert_stacking 0/1 1/1 1/2

View File

@ -29,6 +29,11 @@
const char *client_id = "0";
static gboolean wayland;
GHashTable *windows;
GQuark event_source_quark;
GQuark event_handlers_quark;
GQuark can_take_focus_quark;
typedef void (*XEventHandler) (GtkWidget *window, XEvent *event);
static void read_next_line (GDataInputStream *in);
@ -55,6 +60,186 @@ lookup_window (const char *window_id)
return window;
}
typedef struct {
GSource base;
GSource **self_ref;
GPollFD event_poll_fd;
Display *xdisplay;
} XClientEventSource;
static gboolean
x_event_source_prepare (GSource *source,
int *timeout)
{
XClientEventSource *x_source = (XClientEventSource *) source;
*timeout = -1;
return XPending (x_source->xdisplay);
}
static gboolean
x_event_source_check (GSource *source)
{
XClientEventSource *x_source = (XClientEventSource *) source;
return XPending (x_source->xdisplay);
}
static gboolean
x_event_source_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
XClientEventSource *x_source = (XClientEventSource *) source;
while (XPending (x_source->xdisplay))
{
GHashTableIter iter;
XEvent event;
gpointer value;
XNextEvent (x_source->xdisplay, &event);
g_hash_table_iter_init (&iter, windows);
while (g_hash_table_iter_next (&iter, NULL, &value))
{
GList *l;
GtkWidget *window = value;
GList *handlers =
g_object_get_qdata (G_OBJECT (window), event_handlers_quark);
for (l = handlers; l; l = l->next)
{
XEventHandler handler = l->data;
handler (window, &event);
}
}
}
return TRUE;
}
static void
x_event_source_finalize (GSource *source)
{
XClientEventSource *x_source = (XClientEventSource *) source;
*x_source->self_ref = NULL;
}
static GSourceFuncs x_event_funcs = {
x_event_source_prepare,
x_event_source_check,
x_event_source_dispatch,
x_event_source_finalize,
};
static GSource*
ensure_xsource_handler (GdkDisplay *gdkdisplay)
{
static GSource *source = NULL;
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdkdisplay);
XClientEventSource *x_source;
if (source)
return g_source_ref (source);
source = g_source_new (&x_event_funcs, sizeof (XClientEventSource));
x_source = (XClientEventSource *) source;
x_source->self_ref = &source;
x_source->xdisplay = xdisplay;
x_source->event_poll_fd.fd = ConnectionNumber (xdisplay);
x_source->event_poll_fd.events = G_IO_IN;
g_source_add_poll (source, &x_source->event_poll_fd);
g_source_set_priority (source, GDK_PRIORITY_EVENTS - 1);
g_source_set_can_recurse (source, TRUE);
g_source_attach (source, NULL);
return source;
}
static gboolean
window_has_x11_event_handler (GtkWidget *window,
XEventHandler handler)
{
GList *handlers =
g_object_get_qdata (G_OBJECT (window), event_handlers_quark);
g_return_val_if_fail (handler, FALSE);
g_return_val_if_fail (!wayland, FALSE);
return g_list_find (handlers, handler) != NULL;
}
static void
unref_and_maybe_destroy_gsource (GSource *source)
{
g_source_unref (source);
if (source->ref_count == 1)
g_source_destroy (source);
}
static void
window_add_x11_event_handler (GtkWidget *window,
XEventHandler handler)
{
GSource *source;
GList *handlers =
g_object_get_qdata (G_OBJECT (window), event_handlers_quark);
g_return_if_fail (!window_has_x11_event_handler (window, handler));
source = ensure_xsource_handler (gtk_widget_get_display (window));
g_object_set_qdata_full (G_OBJECT (window), event_source_quark, source,
(GDestroyNotify) unref_and_maybe_destroy_gsource);
handlers = g_list_append (handlers, handler);
g_object_set_qdata (G_OBJECT (window), event_handlers_quark, handlers);
}
static void
window_remove_x11_event_handler (GtkWidget *window,
XEventHandler handler)
{
GList *handlers =
g_object_get_qdata (G_OBJECT (window), event_handlers_quark);
g_return_if_fail (window_has_x11_event_handler (window, handler));
g_object_set_qdata (G_OBJECT (window), event_source_quark, NULL);
handlers = g_list_remove (handlers, handler);
g_object_set_qdata (G_OBJECT (window), event_handlers_quark, handlers);
}
static void
handle_take_focus (GtkWidget *window,
XEvent *xevent)
{
GdkWindow *gdkwindow = gtk_widget_get_window (window);
GdkDisplay *display = gtk_widget_get_display (window);
Atom wm_protocols =
gdk_x11_get_xatom_by_name_for_display (display, "WM_PROTOCOLS");
Atom wm_take_focus =
gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
if (xevent->xany.type != ClientMessage ||
xevent->xany.window != GDK_WINDOW_XID (gdkwindow))
return;
if (xevent->xclient.message_type == wm_protocols &&
(Atom) xevent->xclient.data.l[0] == wm_take_focus)
{
XSetInputFocus (xevent->xany.display,
GDK_WINDOW_XID (gdkwindow),
RevertToParent,
xevent->xclient.data.l[1]);
}
}
static void
process_line (const char *line)
{
@ -123,6 +308,9 @@ process_line (const char *line)
gtk_window_set_title (GTK_WINDOW (window), title);
g_free (title);
g_object_set_qdata (G_OBJECT (window), can_take_focus_quark,
GUINT_TO_POINTER (TRUE));
gtk_widget_realize (window);
if (!wayland)
@ -194,6 +382,130 @@ process_line (const char *line)
NULL))
g_print ("Fail to export handle for window id %s", argv[2]);
}
else if (strcmp (argv[0], "accept_focus") == 0)
{
if (argc != 3)
{
g_print ("usage: %s <window-id> [true|false]", argv[0]);
goto out;
}
GtkWidget *window = lookup_window (argv[1]);
if (!window)
{
g_print ("unknown window %s", argv[1]);
goto out;
}
if (!wayland &&
window_has_x11_event_handler (window, handle_take_focus))
{
g_print ("Impossible to use %s for windows accepting take focus",
argv[1]);
goto out;
}
gboolean enabled = g_ascii_strcasecmp (argv[2], "true") == 0;
gtk_window_set_accept_focus (GTK_WINDOW (window), enabled);
}
else if (strcmp (argv[0], "can_take_focus") == 0)
{
if (argc != 3)
{
g_print ("usage: %s <window-id> [true|false]", argv[0]);
goto out;
}
GtkWidget *window = lookup_window (argv[1]);
if (!window)
{
g_print ("unknown window %s", argv[1]);
goto out;
}
if (wayland)
{
g_print ("%s not supported under wayland", argv[0]);
goto out;
}
if (window_has_x11_event_handler (window, handle_take_focus))
{
g_print ("Impossible to change %s for windows accepting take focus",
argv[1]);
goto out;
}
GdkDisplay *display = gdk_display_get_default ();
GdkWindow *gdkwindow = gtk_widget_get_window (window);
Display *xdisplay = gdk_x11_display_get_xdisplay (display);
Window xwindow = GDK_WINDOW_XID (gdkwindow);
Atom wm_take_focus = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
gboolean add = g_ascii_strcasecmp(argv[2], "true") == 0;
Atom *protocols = NULL;
Atom *new_protocols;
int n_protocols = 0;
int i, n = 0;
gdk_display_sync (display);
XGetWMProtocols (xdisplay, xwindow, &protocols, &n_protocols);
new_protocols = g_new0 (Atom, n_protocols + (add ? 1 : 0));
for (i = 0; i < n_protocols; ++i)
{
if (protocols[i] != wm_take_focus)
new_protocols[n++] = protocols[i];
}
if (add)
new_protocols[n++] = wm_take_focus;
XSetWMProtocols (xdisplay, xwindow, new_protocols, n);
g_object_set_qdata (G_OBJECT (window), can_take_focus_quark,
GUINT_TO_POINTER (add));
XFree (new_protocols);
XFree (protocols);
}
else if (strcmp (argv[0], "accept_take_focus") == 0)
{
if (argc != 3)
{
g_print ("usage: %s <window-id> [true|false]", argv[0]);
goto out;
}
GtkWidget *window = lookup_window (argv[1]);
if (!window)
{
g_print ("unknown window %s", argv[1]);
goto out;
}
if (wayland)
{
g_print ("%s not supported under wayland", argv[0]);
goto out;
}
if (gtk_window_get_accept_focus (GTK_WINDOW (window)))
{
g_print ("%s not supported for input windows", argv[0]);
goto out;
}
if (!g_object_get_qdata (G_OBJECT (window), can_take_focus_quark))
{
g_print ("%s not supported for windows with no WM_TAKE_FOCUS set",
argv[0]);
goto out;
}
if (g_ascii_strcasecmp (argv[2], "true") == 0)
window_add_x11_event_handler (window, handle_take_focus);
else
window_remove_x11_event_handler (window, handle_take_focus);
}
else if (strcmp (argv[0], "show") == 0)
{
if (argc != 2)
@ -442,6 +754,9 @@ main(int argc, char **argv)
windows = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
event_source_quark = g_quark_from_static_string ("event-source");
event_handlers_quark = g_quark_from_static_string ("event-handlers");
can_take_focus_quark = g_quark_from_static_string ("can-take-focus");
GInputStream *raw_in = g_unix_input_stream_new (0, FALSE);
GDataInputStream *in = g_data_input_stream_new (raw_in);

View File

@ -114,7 +114,7 @@ test_case_new (void)
}
static gboolean
test_case_before_redraw (gpointer data)
test_case_loop_quit (gpointer data)
{
TestCase *test = data;
@ -123,6 +123,24 @@ test_case_before_redraw (gpointer data)
return FALSE;
}
static gboolean
test_case_dispatch (TestCase *test,
GError **error)
{
/* Wait until we've done any outstanding queued up work.
* Though we add this as BEFORE_REDRAW, the iteration that runs the
* BEFORE_REDRAW idles will proceed on and do the redraw, so we're
* waiting until after *all* frame processing.
*/
meta_later_add (META_LATER_BEFORE_REDRAW,
test_case_loop_quit,
test,
NULL);
g_main_loop_run (test->loop);
return TRUE;
}
static gboolean
test_case_wait (TestCase *test,
GError **error)
@ -139,16 +157,8 @@ test_case_wait (TestCase *test,
if (!test_client_wait (value, error))
return FALSE;
/* Then wait until we've done any outstanding queued up work.
* Though we add this as BEFORE_REDRAW, the iteration that runs the
* BEFORE_REDRAW idles will proceed on and do the redraw, so we're
* waiting until after *all* frame processing.
*/
meta_later_add (META_LATER_BEFORE_REDRAW,
test_case_before_redraw,
test,
NULL);
g_main_loop_run (test->loop);
/* Then wait until we've done any outstanding queued up work. */
test_case_dispatch (test, error);
/* Then set an XSync counter ourselves and and wait until
* we receive the resulting event - this makes sure that we've
@ -158,6 +168,17 @@ test_case_wait (TestCase *test,
return TRUE;
}
static gboolean
test_case_sleep (TestCase *test,
guint32 interval,
GError **error)
{
g_timeout_add_full (G_PRIORITY_LOW, interval, test_case_loop_quit, test, NULL);
g_main_loop_run (test->loop);
return TRUE;
}
#define BAD_COMMAND(...) \
G_STMT_START { \
g_set_error (error, \
@ -274,6 +295,37 @@ test_case_assert_stacking (TestCase *test,
return *error == NULL;
}
static gboolean
test_case_assert_focused (TestCase *test,
const char *expected_window,
GError **error)
{
MetaDisplay *display = meta_get_display ();
if (!display->focus_window)
{
if (g_strcmp0 (expected_window, "none") != 0)
{
g_set_error (error, TEST_RUNNER_ERROR, TEST_RUNNER_ERROR_ASSERTION_FAILED,
"focus: expected='%s', actual='none'", expected_window);
}
}
else
{
const char *focused = display->focus_window->title;
if (g_str_has_prefix (focused, "test/"))
focused += 5;
if (g_strcmp0 (focused, expected_window) != 0)
g_set_error (error, TEST_RUNNER_ERROR, TEST_RUNNER_ERROR_ASSERTION_FAILED,
"focus: expected='%s', actual='%s'",
expected_window, focused);
}
return *error == NULL;
}
static gboolean
test_case_check_xserver_stacking (TestCase *test,
GError **error)
@ -435,6 +487,63 @@ test_case_do (TestCase *test,
if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error))
return FALSE;
if (!test_client_do (client, error,
argv[0], window_id,
argv[2],
NULL))
return FALSE;
}
else if (strcmp (argv[0], "accept_focus") == 0)
{
if (argc != 3 ||
(g_ascii_strcasecmp (argv[2], "true") != 0 &&
g_ascii_strcasecmp (argv[2], "false") != 0))
BAD_COMMAND("usage: %s <client-id>/<window-id> [true|false]",
argv[0]);
TestClient *client;
const char *window_id;
if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error))
return FALSE;
if (!test_client_do (client, error,
argv[0], window_id,
argv[2],
NULL))
return FALSE;
}
else if (strcmp (argv[0], "can_take_focus") == 0)
{
if (argc != 3 ||
(g_ascii_strcasecmp (argv[2], "true") != 0 &&
g_ascii_strcasecmp (argv[2], "false") != 0))
BAD_COMMAND("usage: %s <client-id>/<window-id> [true|false]",
argv[0]);
TestClient *client;
const char *window_id;
if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error))
return FALSE;
if (!test_client_do (client, error,
argv[0], window_id,
argv[2],
NULL))
return FALSE;
}
else if (strcmp (argv[0], "accept_take_focus") == 0)
{
if (argc != 3 ||
(g_ascii_strcasecmp (argv[2], "true") != 0 &&
g_ascii_strcasecmp (argv[2], "false") != 0))
BAD_COMMAND("usage: %s <client-id>/<window-id> [true|false]",
argv[0]);
TestClient *client;
const char *window_id;
if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error))
return FALSE;
if (!test_client_do (client, error,
argv[0], window_id,
argv[2],
@ -514,6 +623,28 @@ test_case_do (TestCase *test,
if (!test_case_wait (test, error))
return FALSE;
}
else if (strcmp (argv[0], "dispatch") == 0)
{
if (argc != 1)
BAD_COMMAND("usage: %s", argv[0]);
if (!test_case_dispatch (test, error))
return FALSE;
}
else if (strcmp (argv[0], "sleep") == 0)
{
guint64 interval;
if (argc != 2)
BAD_COMMAND("usage: %s <milliseconds>", argv[0]);
if (!g_ascii_string_to_unsigned (argv[1], 10, 0, G_MAXUINT32,
&interval, error))
return FALSE;
if (!test_case_sleep (test, (guint32) interval, error))
return FALSE;
}
else if (strcmp (argv[0], "assert_stacking") == 0)
{
if (!test_case_assert_stacking (test, argv + 1, argc - 1, error))
@ -522,6 +653,11 @@ test_case_do (TestCase *test,
if (!test_case_check_xserver_stacking (test, error))
return FALSE;
}
else if (strcmp (argv[0], "assert_focused") == 0)
{
if (!test_case_assert_focused (test, argv[1], error))
return FALSE;
}
else
{
BAD_COMMAND("Unknown command %s", argv[0]);

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

@ -70,6 +70,8 @@ struct _MetaWaylandTextInput
uint32_t content_type_purpose;
uint32_t text_change_cause;
gboolean enabled;
guint done_idle_id;
};
struct _MetaWaylandTextInputFocus
@ -114,6 +116,52 @@ increment_serial (MetaWaylandTextInput *text_input,
GUINT_TO_POINTER (serial + 1));
}
static gboolean
done_idle_cb (gpointer user_data)
{
ClutterInputFocus *focus = user_data;
MetaWaylandTextInput *text_input;
struct wl_resource *resource;
text_input = META_WAYLAND_TEXT_INPUT_FOCUS (focus)->text_input;
wl_resource_for_each (resource, &text_input->focus_resource_list)
{
zwp_text_input_v3_send_done (resource,
lookup_serial (text_input, resource));
}
text_input->done_idle_id = 0;
return G_SOURCE_REMOVE;
}
static void
meta_wayland_text_input_focus_defer_done (ClutterInputFocus *focus)
{
MetaWaylandTextInput *text_input;
text_input = META_WAYLAND_TEXT_INPUT_FOCUS (focus)->text_input;
if (text_input->done_idle_id != 0)
return;
/* This operates on 3 principles:
* - GDBus uses G_PRIORITY_DEFAULT to put messages in the thread default main
* context.
* - All relevant ClutterInputFocus methods are ultimately backed by
* DBus methods inside IBus.
* - We want to run .done after them all. The slightly lower
* G_PRIORITY_DEFAULT + 1 priority should ensure we at least group
* all messages seen so far.
*
* FIXME: .done may be delayed indefinitely if there's a high enough
* priority idle source in the main loop. It's unlikely that
* recurring idles run at this high priority though.
*/
text_input->done_idle_id = g_idle_add_full (G_PRIORITY_DEFAULT + 1,
done_idle_cb, focus, NULL);
}
static void
meta_wayland_text_input_focus_delete_surrounding (ClutterInputFocus *focus,
guint cursor,
@ -127,9 +175,9 @@ meta_wayland_text_input_focus_delete_surrounding (ClutterInputFocus *focus,
wl_resource_for_each (resource, &text_input->focus_resource_list)
{
zwp_text_input_v3_send_delete_surrounding_text (resource, cursor, len);
zwp_text_input_v3_send_done (resource,
lookup_serial (text_input, resource));
}
meta_wayland_text_input_focus_defer_done (focus);
}
static void
@ -145,9 +193,9 @@ meta_wayland_text_input_focus_commit_text (ClutterInputFocus *focus,
{
zwp_text_input_v3_send_preedit_string (resource, NULL, 0, 0);
zwp_text_input_v3_send_commit_string (resource, text);
zwp_text_input_v3_send_done (resource,
lookup_serial (text_input, resource));
}
meta_wayland_text_input_focus_defer_done (focus);
}
static void
@ -163,9 +211,9 @@ meta_wayland_text_input_focus_set_preedit_text (ClutterInputFocus *focus,
wl_resource_for_each (resource, &text_input->focus_resource_list)
{
zwp_text_input_v3_send_preedit_string (resource, text, cursor, cursor);
zwp_text_input_v3_send_done (resource,
lookup_serial (text_input, resource));
}
meta_wayland_text_input_focus_defer_done (focus);
}
static void

View File

@ -1138,6 +1138,18 @@ process_selection_request (MetaX11Display *x11_display,
meta_verbose ("Handled selection request\n");
}
static gboolean
close_display_idle_cb (gpointer user_data)
{
MetaX11Display *x11_display = META_X11_DISPLAY (user_data);
meta_display_close (x11_display->display,
x11_display->xselectionclear_timestamp);
x11_display->display_close_idle = 0;
return G_SOURCE_REMOVE;
}
static gboolean
process_selection_clear (MetaX11Display *x11_display,
XEvent *event)
@ -1163,8 +1175,13 @@ process_selection_clear (MetaX11Display *x11_display,
meta_verbose ("Got selection clear for on display %s\n",
x11_display->name);
meta_display_close (x11_display->display,
event->xselectionclear.time);
/* We can't close a GdkDisplay in an even handler. */
if (!x11_display->display_close_idle)
{
x11_display->xselectionclear_timestamp = event->xselectionclear.time;
x11_display->display_close_idle = g_idle_add (close_display_idle_cb, x11_display);
}
return TRUE;
}
@ -1818,11 +1835,8 @@ meta_x11_display_handle_xevent (MetaX11Display *x11_display,
{
if (process_selection_clear (x11_display, event))
{
/* This means we called meta_display_unmanage_screen, which
* means the MetaDisplay is effectively dead. We don't want
* to poke into display->current_time below, since that would
* crash, so just directly return. */
return TRUE;
bypass_gtk = TRUE;
goto out;
}
}

View File

@ -92,6 +92,9 @@ struct _MetaX11Display
Atom wm_sn_atom;
guint32 wm_sn_timestamp;
guint display_close_idle;
guint32 xselectionclear_timestamp;
Window wm_cm_selection_window;
Window composite_overlay_window;

View File

@ -215,6 +215,12 @@ meta_x11_display_dispose (GObject *object)
x11_display->gdk_display = NULL;
}
if (x11_display->display_close_idle)
{
g_source_remove (x11_display->display_close_idle);
x11_display->display_close_idle = 0;
}
g_free (x11_display->name);
x11_display->name = NULL;
@ -1186,6 +1192,9 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
x11_display->timestamp_pinging_window = None;
x11_display->wm_sn_selection_window = None;
x11_display->display_close_idle = 0;
x11_display->xselectionclear_timestamp = 0;
x11_display->last_bell_time = 0;
x11_display->focus_serial = 0;
x11_display->server_focus_window = None;

View File

@ -55,8 +55,15 @@
#include "backends/meta-logical-monitor.h"
#include "backends/x11/meta-backend-x11.h"
#define TAKE_FOCUS_FALLBACK_DELAY_MS 150
G_DEFINE_TYPE_WITH_PRIVATE (MetaWindowX11, meta_window_x11, META_TYPE_WINDOW)
static void
meta_window_x11_maybe_focus_delayed (MetaWindow *window,
GQueue *other_focus_candidates,
guint32 timestamp);
static void
meta_window_x11_init (MetaWindowX11 *window_x11)
{
@ -734,6 +741,160 @@ request_take_focus (MetaWindow *window,
send_icccm_message (window, display->x11_display->atom_WM_TAKE_FOCUS, timestamp);
}
typedef struct
{
MetaWindow *window;
GQueue *pending_focus_candidates;
guint32 timestamp;
guint timeout_id;
gulong unmanaged_id;
gulong focused_changed_id;
} MetaWindowX11DelayedFocusData;
static void
disconnect_pending_focus_window_signals (MetaWindow *window,
GQueue *focus_candidates)
{
g_signal_handlers_disconnect_by_func (window, g_queue_remove,
focus_candidates);
}
static void
meta_window_x11_delayed_focus_data_free (MetaWindowX11DelayedFocusData *data)
{
g_signal_handler_disconnect (data->window, data->unmanaged_id);
g_signal_handler_disconnect (data->window->display, data->focused_changed_id);
if (data->pending_focus_candidates)
{
g_queue_foreach (data->pending_focus_candidates,
(GFunc) disconnect_pending_focus_window_signals,
data->pending_focus_candidates);
g_queue_free (data->pending_focus_candidates);
}
if (data->timeout_id)
g_source_remove (data->timeout_id);
g_free (data);
}
static void
focus_candidates_maybe_take_and_focus_next (GQueue **focus_candidates_ptr,
guint32 timestamp)
{
MetaWindow *focus_window;
GQueue *focus_candidates;
g_assert (*focus_candidates_ptr);
if (g_queue_is_empty (*focus_candidates_ptr))
return;
focus_candidates = g_steal_pointer (focus_candidates_ptr);
focus_window = g_queue_pop_head (focus_candidates);
disconnect_pending_focus_window_signals (focus_window, focus_candidates);
meta_window_x11_maybe_focus_delayed (focus_window, focus_candidates, timestamp);
}
static gboolean
focus_window_delayed_timeout (gpointer user_data)
{
MetaWindowX11DelayedFocusData *data = user_data;
MetaWindow *window = data->window;
guint32 timestamp = data->timestamp;
focus_candidates_maybe_take_and_focus_next (&data->pending_focus_candidates,
timestamp);
data->timeout_id = 0;
meta_window_x11_delayed_focus_data_free (data);
meta_window_focus (window, timestamp);
return G_SOURCE_REMOVE;
}
static void
meta_window_x11_maybe_focus_delayed (MetaWindow *window,
GQueue *other_focus_candidates,
guint32 timestamp)
{
MetaWindowX11DelayedFocusData *data;
data = g_new0 (MetaWindowX11DelayedFocusData, 1);
data->window = window;
data->timestamp = timestamp;
data->pending_focus_candidates = other_focus_candidates;
meta_topic (META_DEBUG_FOCUS,
"Requesting delayed focus to %s\n", window->desc);
data->unmanaged_id =
g_signal_connect_swapped (window, "unmanaged",
G_CALLBACK (meta_window_x11_delayed_focus_data_free),
data);
data->focused_changed_id =
g_signal_connect_swapped (window->display, "notify::focus-window",
G_CALLBACK (meta_window_x11_delayed_focus_data_free),
data);
data->timeout_id = g_timeout_add (TAKE_FOCUS_FALLBACK_DELAY_MS,
focus_window_delayed_timeout, data);
}
static void
maybe_focus_default_window (MetaDisplay *display,
MetaWindow *not_this_one,
guint32 timestamp)
{
MetaWorkspace *workspace;
MetaStack *stack = display->stack;
g_autoptr (GList) focusable_windows = NULL;
g_autoptr (GQueue) focus_candidates = NULL;
GList *l;
if (not_this_one && not_this_one->workspace)
workspace = not_this_one->workspace;
else
workspace = display->workspace_manager->active_workspace;
/* Go through all the focusable windows and try to focus them
* in order, waiting for a delay. The first one that replies to
* the request (in case of take focus windows) changing the display
* focused window, will stop the chained requests.
*/
focusable_windows =
meta_stack_get_default_focus_candidates (stack, workspace);
focus_candidates = g_queue_new ();
for (l = g_list_last (focusable_windows); l; l = l->prev)
{
MetaWindow *focus_window = l->data;
if (focus_window == not_this_one)
continue;
g_queue_push_tail (focus_candidates, focus_window);
g_signal_connect_swapped (focus_window, "unmanaged",
G_CALLBACK (g_queue_remove),
focus_candidates);
if (!META_IS_WINDOW_X11 (focus_window))
break;
if (focus_window->input)
break;
if (focus_window->shaded && focus_window->frame)
break;
}
focus_candidates_maybe_take_and_focus_next (&focus_candidates, timestamp);
}
static void
meta_window_x11_focus (MetaWindow *window,
guint32 timestamp)
@ -783,13 +944,20 @@ meta_window_x11_focus (MetaWindow *window,
* Normally, we want to just leave the focus undisturbed until
* the window responds to WM_TAKE_FOCUS, but if we're unmanaging
* the current focus window we *need* to move the focus away, so
* we focus the no_focus_window now (and set
* display->focus_window to that) before sending WM_TAKE_FOCUS.
* we focus the no focus window before sending WM_TAKE_FOCUS,
* and eventually the default focus windwo excluding this one,
* if meanwhile we don't get any focus request.
*/
if (window->display->focus_window != NULL &&
window->display->focus_window->unmanaging)
meta_x11_display_focus_the_no_focus_window (window->display->x11_display,
timestamp);
{
MetaX11Display *x11_display = window->display->x11_display;
meta_x11_display_focus_the_no_focus_window (x11_display,
timestamp);
maybe_focus_default_window (window->display, window,
timestamp);
}
}
request_take_focus (window, timestamp);