Compare commits

...

53 Commits

Author SHA1 Message Date
4947e8ae5b Bump version to 3.34.3
Update NEWS.
2020-01-05 12:37:05 +01:00
5724310899 clutter/stage: Fix picking of rectangles with negative positions
FLT_MIN is the smallest *positive* number above 0 that can be
represented as floating point number. If this is used to initialize the
maximum x/y coordinates of a rectangle, this will always be used if all
x/y coordinates of the rectangle are negative. This means that picking
at 0,0 will always be a hit for such rectangles.

Since mutter creates such a window for server side decorations on X11,
this window will always be picked at 0,0 preventing clicking/hovering
the activities button in gnome-shell at that coordinate.

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


(cherry picked from commit 674f52ba74)
2019-12-24 16:52:37 +00:00
9772f084bf screen-cast: Fix window recording on HiDPI
Using the same scale for the window as the
logical monitor only works correctly when having
the experimental 'scale-monitor-framebuffer'
feature enabled.
Without this experimental feature, the stream
will contain a black screen, where the actual
window only takes a small part of it.

Therefore, use a scale of 1 for the non-
experimental case.

Patch is based on commit 3fa6a92cc5.

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


(cherry picked from commit e89cea8e5a)
2019-12-18 19:54:03 +00:00
8b087cfe56 Bump version to 3.34.2
Update NEWS.
2019-12-11 20:05:26 +01:00
c05328f76a Update British English translation 2019-12-11 10:25:27 +00:00
868a617907 backends/native: Fix double free of error
error is an autoptr, so must not be explicitly freed.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1852
Fixes: 5c500ad402 ("backend: Move GPU ownership from the monitor manager to the backend")

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


(cherry picked from commit d70ddc65ea)
2019-12-06 19:56:51 +00:00
6f02d2ead0 kms-impl/simple: Fix meta_set_fallback_feedback_idle
Presumably this function is supposed to be like
meta_kms_impl_simple_handle_page_flip_callback() but the condition in the
if-statement is inverted. Fix the inversion to make these two functions look
alike.

This is part 2 of 2 fixing a complete desktop freeze when drmModePageFlip()
fails with EINVAL and the fallback to drmModeSetCrtc() succeeds but the success
is not registered correctly as completed "flip". The freeze occurs under
wait_for_pending_flips() which calls down into meta_kms_impl_device_dispatch()
which ends up poll()'ing the DRM fd even though drmModeSetCrtc() will not
produce a DRM event, hence the poll() never returns. The freeze was observed
when hotplugging a DisplayLink dock for the first time on Ubuntu 19.10.

This patch makes meta_set_fallback_feedback_idle() actually end up calling into
notify_view_crtc_presented() which decrements
secondary_gpu_state->pending_flips so that wait_for_pending_flips() can finish.

CC stable: gnome-3-34

https://gitlab.gnome.org/GNOME/mutter/merge_requests/953
(cherry picked from commit 832a522cce)
2019-12-06 17:27:15 +01:00
fc77efbcd7 kms: Process impl idle callbacks before pre dispatch flush
mode_set_fallback() schedules a call to mode_set_fallback_feedback_idle(), but
it is possible for Mutter to repaint before the idle callbacks are dispatched.
If that happens, mode_set_fallback_feedback_idle() does not get called before
Mutter enters wait_for_pending_flips(), leading to a deadlock.

Add the needed interfaces so that meta_kms_device_dispatch_sync() can flush all
the implementation idle callbacks before it checks if any "events" are
available. This prevents the deadlock by ensuring
mode_set_fallback_feedback_idle() does get called before potentially waiting
for actual DRM events.

Presumably this call would not be needed if the implementation was running in
its own thread, since it would eventually dispatch its idle callbacks before
going to sleep polling on the DRM fd. This call might even be unnecessary
overhead in that case, synchronizing with the implementation thread needlessly.
But the thread does not exist yet, so this is needed for now.

This is part 1 of 2 fixing a complete desktop freeze when drmModePageFlip()
fails with EINVAL and the fallback to drmModeSetCrtc() succeeds but the success
is not registered correctly as completed "flip". The freeze occurs under
wait_for_pending_flips() which calls down into meta_kms_impl_device_dispatch()
which ends up poll()'ing the DRM fd even though drmModeSetCrtc() will not
produce a DRM event, hence the poll() never returns. The freeze was observed
when hotplugging a DisplayLink dock for the first time on Ubuntu 19.10.

CC stable: gnome-3-34

https://gitlab.gnome.org/GNOME/mutter/merge_requests/953
(cherry picked from commit 79491df2b8)
2019-12-06 17:27:14 +01:00
c0e76186da stack: Allow promoting transient windows to their parent's layer
When a window that should be stacked above another one is placed in a lower
layer than the other window, we currently allow promoting it to the higher
layer when it has a "transient type". We should do the same when the window
is an actual transient of the other window.

This is particularly relevant for wayland windows, where types play a
much smaller role: Transient windows like non-modal dialogs (and since
commit 666bef7a, popup windows as well) currently end up underneath their
always-on-top parent.

https://gitlab.gnome.org/GNOME/mutter/issues/587


(cherry picked from commit 1c89fce30e)
2019-11-29 14:18:59 +00:00
1b75d78c72 shaped-texture: Do not invalidate content on set_cogl_texture()
This was wrongly introduced in 75cffd0ec4. As the comment above explains, we
only want to queue redraws in response to surface/buffer damage.

This triggered a full redraw when using DMA buffers on Wayland as we currently
create a new texture on every buffer_attach(), breaking partial invalidation.

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


(cherry picked from commit 0247d35e5a)
2019-11-26 22:43:54 +00:00
cbbffd1db7 cursor-tracker: Add API to keep the wayland pointer focus while hidden
Since commit a2a8f0cda we force the focus surface of the
meta-wayland-pointer to NULL while the pointer is invisible. This
introduced an issue with the a11y magnifier of the shell, which uses
`meta_cursor_tracker_set_pointer_visible` to hide the real cursor and
show its own magnified cursor at the correct position: Because the
meta-wayland-pointer is still used to communicate with Wayland clients,
the UI of the windows will not respond to mouse movement anymore as
soon as the real cursor is hidden.

Fix this issue for now by adding an additional method to the
cursor-tracker which allows disabling the behavior commit a2a8f0cda
introduced.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/832
2019-11-25 16:15:14 +01:00
06202c342b device-manager-x11: Ignore events if no source device is set
There might be some inconsistent event for which we don't have a known
source device.

In the current state we don't handle them and we could crash when getting
the current device tool.

So, add an utility function that retrieves the source device for an event
that warns if no device is found, and use this for Motion, Key and Button
events.

In case we don't have a valid source in such case, just return early instead
of trying to generate invalid clutter events.

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


(cherry picked from commit 427670cc63)
2019-11-23 01:47:33 +00:00
9c372388da clutter/cally-root: Use g_clear_signal_handler and fix a signal leak
This commit was split out from `cleanup: Use g_clear_signal_handler()
where possible` as it fixes an actual signal leak and should therefore
get backported to stable releases.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/940
2019-11-21 16:22:14 +01:00
7e741fe2d2 wayland: Move "ownership" of the DnD selection source to the data device
On wl_data_source destruction we used to indirectly unset the DnD selection
owner via the wl_resource destructor triggering the destruction of the
MetaWaylandDataSource, which would be caught through the weak ref set by
the MetaWaylandDragGrab.

This works as long as the grab is held, however we have a window between
the button being released and the drop site replying with
wl_data_offer.finish that the MetaWaylandDataSource is alive, but its
destruction wouldn't result in the call chain above to unsetting the DnD
source.

In other selection sources, we let the MetaWaylandDataDevice hold the
"ownership" of the MetaWaylandDataSource, and its weak ref functions unset
the respective MetaSelection owners. Do the same here, so the
MetaWaylandDataSource destruction is listened for all its lifetime.

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

(cherry picked from commit e5af790acb)
2019-11-20 12:59:58 +01:00
edb618b2a4 wayland: Do not cancel data source on offer destruction
This is wrong for both clipboard and DnD, as the selection source
will still be able to focus another surface, and churn another
wl_offer.

We should just detach the data offer from the data source in this
case, and let the source live on. However, we should still check
that there is a source and an offer to finish DnD, do that when
handling the drop operation instead.

https://gitlab.gnome.org/GNOME/mutter/issues/591

(cherry picked from commit 48639ac5da)
2019-11-20 12:59:40 +01:00
e2d6b33b61 wayland: Avoid redundant cancel() call
This is unnecessary as we are unsetting the DnD selection owner,
and will result in the related data source being cancelled already.

https://gitlab.gnome.org/GNOME/mutter/issues/591

(cherry picked from commit e7b2f9603e)
2019-11-20 12:59:19 +01:00
eac37b17b0 wayland: Drop unused wl_signal structs
Those were used to signal clipboard ownership around, but that got
replaced by MetaSelection and friends. These signals are no longer
listened on, so can be safely removed.

https://gitlab.gnome.org/GNOME/mutter/issues/591

(cherry picked from commit 46b3811e22)
2019-11-20 12:58:30 +01:00
d78585d68a cursor-renderer/native: Fix cursor drawing in combination with panel_orientation_transform
Properly take the panel_orientation_transform into account in
update_monitor_crtc_cursor. This fixes us sometimes drawing the cursor
on two monitors at the same time as we did not properly swap the crtc
width/height when a panel_orientation_transform is active.

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


(cherry picked from commit 8907a29912)
2019-11-13 10:35:31 +00:00
c462544f78 output-kms: Fix "panel orientation" kms-prop being ignored on native outputs
Actually store the panel_orientation_transform in the meta_output, so
that it gets honored by the core code.

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


(cherry picked from commit a5f986259f)
2019-11-13 10:35:04 +00:00
eb78b7d0d1 compositor: Plug cairo_region_t leak
The MetaBackgroundActor uses a region to find out the areas that need
repainting, but forgot to free it, oops.

(cherry-picked from 40e6aa7d94)

https://gitlab.gnome.org/GNOME/mutter/merge_requests/873
2019-11-12 13:37:30 +01:00
cc00e55513 backends: Plug MetaKmsPageFlipData leak
If the page flip is postponed, keep a ref to it, but still unref it
on the page flip callback anyways. Fix suggested by Jonas Ådahl.

(cherry-picked from 668be1f4bd)

https://gitlab.gnome.org/GNOME/mutter/merge_requests/873
2019-11-12 13:37:30 +01:00
a14e7b441c input-settings/x11: Add missing clutter_x11_trap_x_errors around XIGetProperty
Add missing clutter_x11_[un]trap_x_errors around the XIGetProperty call
in meta-input-settings-x11.c's get_property helper function.

This fixes mutter crashing with the following error if the XInput device
goes away at an unconvenient time:

 X Error of failed request:  XI_BadDevice (invalid Device parameter)
   Major opcode of failed request:  131 (XInputExtension)
   Minor opcode of failed request:  59 ()
   Device id in failed request: 0x200011
   Serial number of failed request:  454
   Current serial number in output stream:  454

https://gitlab.gnome.org/GNOME/mutter/merge_requests/928
2019-11-10 22:42:44 +01:00
403d8fcc66 plugin-manager: Kill window effects on destroy
We do so for all other window effects already. Why this was left out
is unknown (9b3a0d1ad8), but we will need it for a fix in GS.

Related: https://gitlab.gnome.org/GNOME/mutter/issues/655

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


(cherry picked from commit a4f51da184)
2019-11-08 22:44:34 +00:00
7e5366f233 plugins/default: Handle skipped animations
We currently assume that the actor_animate() helper function returns
a timeline. However Clutter may skip implicit animations and simple
set properties directly, for example when the actor is hidden.

The returned timeline will be NULL in that case, and we abort when
using it as instance parameter to g_signal_connect().

Fix this by only setting up a completed handler when we are actually
animating, and complete the effect directly otherwise.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/925
2019-11-08 19:19:45 -03:00
cf78598974 wayland/surface: Don't double scale when getting absolute coordinates
The actor is already in surface coordinate space, so we should not scale
with the buffer scale to transform surface coordinates to stage
coordinates.

This bug causes input method using wayland text-input protocol to
receive wrong cursor location. Reproduced in ibus (when candidate
window is open) with scaling factor other than 1.

This commit also fixes pointer confinement.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/915
2019-11-07 17:56:14 +01:00
7c1f3498fe window-props: Don't set override redirect windows as top-level parent
Java applications might use override-redirect windows as parent windows for
top-level windows, although this is not following the standard [1].

In such case, the first non-override-redirect child window that is created
was marked as being on_all_workspaces since the call to
should_be_on_all_workspaces() returns TRUE for its parent, and this even
though the on_all_workspaces_requested bit is unset.
When a further child of this window was added, it was set as not having a
workspace and not being on_all_workspaces, since the call to
should_be_on_all_workspaces() for its parent would return FALSE (unless if
it is in a different monitor, and the multiple-monitors workspaces are
disabled).

Since per commit 09bab98b we don't recompute the workspace if the
on_all_workspaces bit is unset, we could end up in a case where a window can
be nor in all the workspaces or in a specific workspace.

So let's just ignore the transient_for bit for a window if that points to an
override-redirect, using the x11 root window instead.

Add a stacking test to verify this scenario (was failing before of this
commit).

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/885
https://gitlab.gnome.org/GNOME/mutter/merge_requests/895

[1] https://standards.freedesktop.org/wm-spec/wm-spec-latest.html#idm140200472512128


(cherry picked from commit bacbbbd628)
2019-11-07 16:21:37 +00:00
598be2b1d8 window-props: Don't look for parent multiple times
Once we set the transient_for, we look for parent MetaWindow, so instead
of overwriting this value for loops check, just use another function
and avoid to look for the xwindow again when setting the MetaWindow parent.

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


(cherry picked from commit c85fb107c0)
2019-11-07 16:21:09 +00:00
a8776a9634 window: Assert we only set a NULL workspace when unmanaging
There might be cases in which a window might be marked as both not in all
workspaces and with NULL workspace.

So to avoid this to happen, let's just assert early instead of doing this at
later point where the context might not be clear.

Related to https://gitlab.gnome.org/GNOME/mutter/issues/885

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


(cherry picked from commit 13f10e36e4)
2019-11-07 16:19:25 +00:00
4b238c10f4 window: Warn if O-R window workspace state is used
Override-redirect windows have no workspace by default, and can't be parent
of a top-level window, so we must check that the parent window is not an
O-R one when setting the workspace state.

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


(cherry picked from commit 2644e54c51)
2019-11-07 16:18:55 +00:00
6fa860481c wayland/actor-surface: Always store away frame callbacks on commit
We're expected by MetaWaylandSurface to always pick the frame callbacks
out from the pending state when committing (applying) so that no frame
callbacks are unaccounted for. We failed to do this if our actor for
some reason (e.g. associated window was unmanaged) was destroyed. To
handle this situation better, store away the frame callbacks until we
some later point in time need to pass them on forward.

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


(cherry picked from commit 0e5a5df5fe)
2019-11-07 13:51:43 +00:00
4ba3c4537e ci: Fix checking out gnome-shell on stable branches
For stable branches, we currently only check out the correct shell
branch for merge requests. For the regular pipeline, our code to
determine the current mutter branch fails because CI runs on a
temporary "pipeline/12345" branch that doesn't exist for gnome-shell.

Switching to the correct gitlab environment variable fixes that.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/811
2019-11-07 00:14:41 +01:00
1f56514e40 x11-display: Don't unset the X11 focused window after setting one
When using DesktopIcons extension and clicking in an icon, gnome-shell
starts an infinite loop caused by the first focus change that may trigger
on X11 a focus in/out event that leads to stage activation/deactivation
which never ends.

This happens because as part of meta_x11_display_set_input_focus_xwindow()
to focus the X11 stage window, we unset the display focus, but this also
causes to request the X11 display to unset the focus since we convolute by
calling meta_x11_display_set_input_focus() with no window, that leads to
focusing the no_focus_window and then a focus-in / focus-out dance that the
shell amplifies in order to give back the focus to the stage.

In order to fix this, mimic what meta_display_set_input_focus() does, but
without updating the X11 display, and so without implicitly calling
meta_x11_display_set_input_focus(), stopping the said convolution and
properly focusing the requested xwindow.
Also ensure that we're not doing this when using an older timestamp, since
this check isn't performed anymore.

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/896
Fixes https://gitlab.gnome.org/GNOME/mutter/issues/899

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


(cherry picked from commit efe5bed5b4)
2019-11-06 17:48:19 +00:00
5e1bbb770e tests/monitor-unit-tests: Add another tiling window hot plug test
Checks that we handle hot plugs of a untiled window, that was previously
tiled.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:26 -03:00
3df4348f23 window: Reset tile monitor number when untiling
Otherwise we'll end up trying to access the out of date state later.

Fixes the following test failure backtrace:

    #0  _g_log_abort ()
    #1  g_logv ()
    #2  g_log ()
    #3  meta_monitor_manager_get_logical_monitor_from_number ()
    #4  meta_window_get_work_area_for_monitor ()
    #5  meta_window_get_tile_area ()
    #6  constrain_maximization ()
    #7  do_all_constraints ()
    #8  meta_window_constrain ()
    #9  meta_window_move_resize_internal ()
    #10 meta_window_tile ()

https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:25 -03:00
9ed33dc72e tests/monitor-unit-tests: Add window tiling hot plug test
This test that we handle hot plugs correctly together with tiled
windows.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:23 -03:00
8cb0646b62 tests/runner: Move window shown synchronization to helper
https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:22 -03:00
c9a05d4581 tests/monitor-unit-tests: Move test client sanity check into helper
https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:21 -03:00
98a1630fa2 window: Always update tile monitor number on hot plug
Otherwise we'll end up crashing if we had two connected monitors,
unplugged both, then replugged in a single one.

Avoids the following error:

    #0  _g_log_abort ()
    #1  g_logv ()
    #2  g_log ()
    #3  meta_monitor_manager_get_logical_monitor_from_number ()
    #4  meta_window_get_work_area_for_monitor ()
    #5  meta_window_get_tile_area ()
    #6  constrain_maximization ()
    #7  do_all_constraints ()
    #8  meta_window_constrain ()
    #9  meta_window_move_resize_internal ()
    #10 meta_window_move_resize_frame ()
    #11 meta_window_move_resize_now ()
    #12 idle_move_resize ()
    #13 call_idle_later ()

https://bugzilla.redhat.com/show_bug.cgi?id=1767703

https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:20 -03:00
4c48c859ea plugins/default: Clean up tile preview when closing display
On finalize, the preview actor will have been destroyed behind our back;
avoid that by cleaning up before it's too late.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:19 -03:00
d7bdaeeb82 plugin/default: Init quark before using
Cut lines in pieces, and remove useless "optimizations" while at it

https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:17 -03:00
3564b0df4a display: Add 'closing' signal
Emitted when the MetaDisplay is closing. Meant for clean up that depends
on things that will be torn down during closing.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:15 -03:00
34b5a07d58 renderer-native: Separate offscreen and shadowfb
Create the intermediate shadow framebuffer for use exclusively when a
shadowfb is required.

Keep the previous offscreen framebuffer is as an intermediate
framebuffer for transformations only.

This way, we can apply transformations between in-memory framebuffers
prior to blit the result to screen, and achieve acceptable performance
even with software rendering on discrete GPU.

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

(cherry picked from commit 551641c74822ca2e3c685e49603836ebf5397df2)
2019-11-04 11:08:02 +01:00
a112d7a10e clutter/stage-view: Separate offscreen and shadowfb
Previously, we would use a single offscreen framebuffer for both
transformations and when a shadow framebuffer should be used, but that
can be dreadfully slow when using software rendering with a discrete GPU
due to bandwidth limitations.

Keep the offscreen framebuffer for transformations only and add another
intermediate shadow framebuffer used as a copy of the onscreen
framebuffer.

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

(cherry picked from commit 2b8b450fe16c21f0f37a1779560c0e5da61a9b89)
2019-11-04 11:08:02 +01:00
51f7e8c4dd wayland: Check stylus serials on meta_wayland_seat_can_popup()
This allows xdg_popup.grab() to work with styli. Without this check
we would bail out and emit xdg_popup.popup_done, leaving stylus users
unable to interact with popup menus, comboboxes, etc...

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/886
2019-10-30 10:08:51 +01:00
f4574ea36f 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
2019-10-30 10:08:39 +01:00
2301cde8f7 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
2019-10-30 10:08:32 +01:00
ef2f5f07f0 x11: Update X11 focus before updating MetaDisplay focus
In a similar vein to commit 8fd55fef85. This notably failed when setting
the focus on the stage (eg. to redirect key events to Clutter actors).
Deeper in MetaDisplay focus updating machinery, it would check
meta_stage_is_focused() which would still return FALSE at the time it's
called.

This would not typically have side effects, but our "App does not respond"
dialogs see the focus change under their feet, so they try to bring
themselves to focus again. This results in a feedback loop.

Changing the order results in later checks on the X11 POV of the focus
being correct, so focus is not mistakenly stolen from the close dialog,
and it actually succeeds in keeping the key focus.

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

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


(cherry picked from commit 71c3f4af31)
2019-10-24 15:52:41 +00:00
85f5db7e73 wayland/surface: Reset buffer_destroy_handler_id
Syncronized subsurfaces that call into `merge_pending_state` might
otherwise not create new destroy handlers, ending up with a invalid
handler ids, throwing errors and leaking.

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


(cherry picked from commit 98892391d7)
2019-10-21 13:03:25 +00:00
c0037305eb window-actor: Add a missing NULL-check
We shouldn't crash on a NULL-clip.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/856
2019-10-18 13:40:20 +02:00
ff885fea31 monitor-manager: check for underscan setting validity upfront
Instead of doing a roundtrip to the X server before setting it, rely on
the previous value fetched before the configuration was sent over DBus.
This matches the argument check we already do elsewhere, and will allow
us to more easily add an additional condition to determine if underscan
is supported.

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


(cherry picked from commit 8665084df1)
2019-10-18 11:36:34 +00:00
bf17e04010 clutter/stage: Actually set key focus to an actor on key focus
As per commit c2d03bf73 we're using a private method to set the actors key
focus and emit key-focus-in signal, but we're using inverted logic here.

So flip the parameter to match the expected result.

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


(cherry picked from commit 553211dd81)
2019-10-15 18:31:50 +00:00
a22731e2b2 clutter/actor: Save key-focus state and unset it before destruction
When clutter actors with key focus are destroyed we emit ::key-focus-out on
them just after their destruction. This is against our assumption that no
signal should be emitted after "::destroy" (see GNOME/mutter!769 [1]), and
in fact could cause the shell to do actions that we won't ever stop on
destroy callback.

To avoid this to happen, use a private function to set its key-state (so we
can avoid looking for the stage) and emit ::key-focus-in/out events and use
this value in both clutter_actor_has_key_focus(),
clutter_actor_grab_key_focus() and on unmap and destruction to unset the
stage key focus before we emit the ::destroy signal.

As result of this, we can now avoid to unset the key focus on actor
destruction in the stage.

[1] https://gitlab.gnome.org/GNOME/mutter/merge_requests/769

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


(cherry picked from commit c2d03bf73e)
2019-10-15 10:42:55 +00:00
b6ed7d6781 dbus-session-watcher: Chain up to parent finalize()
https://gitlab.gnome.org/GNOME/mutter/merge_requests/847


(cherry picked from commit 3a688988e0)
2019-10-14 07:51:15 +00:00
57 changed files with 1080 additions and 412 deletions

View File

@ -1,6 +1,5 @@
#!/usr/bin/bash
mutter_branch=$(git describe --contains --all HEAD)
gnome_shell_target=
git clone https://gitlab.gnome.org/GNOME/gnome-shell.git
@ -26,8 +25,7 @@ if [ "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
fi
if [ -z "$gnome_shell_target" ]; then
gnome_shell_target=$(git branch -r -l origin/$mutter_branch)
gnome_shell_target=${gnome_shell_target:-$(git branch -r -l ${mutter_branch#remotes/})}
gnome_shell_target=$(git branch -r -l origin/$CI_COMMIT_REF_NAME)
gnome_shell_target=${gnome_shell_target:-origin/master}
echo Using $gnome_shell_target instead
fi

42
NEWS
View File

@ -1,3 +1,45 @@
3.34.3
======
* Fix window recording on HiDPI [Pascal; !976]
* Fix top-left pixel being insensitive to clicks [Sebastian; #893]
Contributors:
Sebastian Keller, Pascal Nowack
3.34.2
======
* Fix immediate screen blank after releasing inhibitor [Tim; #573]
* Respond to frame callbacks regardless of damage [Jonas Å.; !839]
* Translate well-known selection atoms to mimetypes [Carlos; !842]
* Fix Night Light on wayland [Jonas Å.; !840]
* Fix various copy+paste/DND regressions [Carlos; !848, #789, #842,
#793, #845, #854]
* Don't emit focus event after desctruction [Marco; gnome-shell#1704, !860]
* Fix hang when opening not-responding dialog on Xorg [Carlos; !876]
* Fix frozen grabs on Xorg after weeks of inactivity [Jonas Å.; !886]
* Fix triggering popups from stylus devices on wayland [Carlos; #886]
* Support shadow framebuffers for offscreen rendering [Olivier; !917]
* Fix hang after interacting with desktop icons on X11 [Marco; !909]
* Don't double scale when getting absolute surface coordinates [Xiang; !915]
* Kill window effects on destroy [Robert; !924]
* Use partial damage for dma-buf and EGLImage buffers on wayland [Robert; #947]
* Do not stack transients underneath their always-on-top parent [Florian; #587]
* Fix KMS freeze after pageflip [Pekka; !953]
* Fixed crashes [Robert, Jonas Å., Marco, Hans, Carlos, Tim; !856, !912, !895,
!928, #591, !823, !960]
* Plugged memory leaks [Niels, Robert, Carlos; !847, !868, !873]
* Misc. bug fixes and cleanups [Daniel, Marco, Jonas Å., Georges, Cosimo,
Florian, Hans, Robert, Jonas D.; !841, !764, !837, !846, !673, !811, !893,
!925, !927, !940, !832]
Contributors:
Marco Trevisan (Treviño), Cosimo Cecchi, Tim Crawford, Jonas Dreßler,
Xiang Fan, Olivier Fourdan, Carlos Garnacho, Hans de Goede, Niels De Graef,
Tim Klocke, Robert Mader, Florian Müllner, Georges Basile Stavracas Neto,
Pekka Paalanen, Daniel van Vugt, Jonas Ådahl
Translators:
Bruce Cowan [en_GB]
3.34.1
======
* Fix startup of X11 session services on wayland [Carlos; #771]

View File

@ -75,8 +75,8 @@ struct _CallyRootPrivate
GSList *stage_list;
/* signals id */
guint stage_added_id;
guint stage_removed_id;
gulong stage_added_id;
gulong stage_removed_id;
};
G_DEFINE_TYPE_WITH_PRIVATE (CallyRoot, cally_root, ATK_TYPE_GOBJECT_ACCESSIBLE)
@ -149,11 +149,9 @@ cally_root_finalize (GObject *object)
stage_manager = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (root));
g_signal_handler_disconnect (stage_manager,
root->priv->stage_added_id);
g_clear_signal_handler (&root->priv->stage_added_id, stage_manager);
g_signal_handler_disconnect (stage_manager,
root->priv->stage_added_id);
g_clear_signal_handler (&root->priv->stage_removed_id, stage_manager);
G_OBJECT_CLASS (cally_root_parent_class)->finalize (object);
}

View File

@ -274,6 +274,9 @@ void _clutter_actor_set_enable_paint_unmapped
void _clutter_actor_set_has_pointer (ClutterActor *self,
gboolean has_pointer);
void _clutter_actor_set_has_key_focus (ClutterActor *self,
gboolean has_key_focus);
void _clutter_actor_queue_redraw_with_clip (ClutterActor *self,
ClutterRedrawFlags flags,
const ClutterPaintVolume *clip_volume);

View File

@ -835,6 +835,7 @@ struct _ClutterActorPrivate
guint enable_model_view_transform : 1;
guint enable_paint_unmapped : 1;
guint has_pointer : 1;
guint has_key_focus : 1;
guint propagated_one_redraw : 1;
guint paint_volume_valid : 1;
guint last_paint_volume_valid : 1;
@ -1691,6 +1692,20 @@ clutter_actor_is_mapped (ClutterActor *self)
return CLUTTER_ACTOR_IS_MAPPED (self);
}
static void
maybe_unset_key_focus (ClutterActor *self)
{
ClutterActor *stage;
if (!self->priv->has_key_focus)
return;
stage = _clutter_actor_get_stage_internal (self);
if (stage)
clutter_stage_set_key_focus (CLUTTER_STAGE (stage), NULL);
}
static void
clutter_actor_real_unmap (ClutterActor *self)
{
@ -1724,17 +1739,7 @@ clutter_actor_real_unmap (ClutterActor *self)
/* relinquish keyboard focus if we were unmapped while owning it */
if (!CLUTTER_ACTOR_IS_TOPLEVEL (self))
{
ClutterStage *stage;
stage = CLUTTER_STAGE (_clutter_actor_get_stage_internal (self));
if (stage != NULL &&
clutter_stage_get_key_focus (stage) == self)
{
clutter_stage_set_key_focus (stage, NULL);
}
}
maybe_unset_key_focus (self);
}
/**
@ -6064,6 +6069,8 @@ clutter_actor_dispose (GObject *object)
object->ref_count,
g_type_name (G_OBJECT_TYPE (self)));
maybe_unset_key_focus (self);
/* Stop the emission of any property change */
g_object_freeze_notify (object);
@ -15979,6 +15986,9 @@ clutter_actor_grab_key_focus (ClutterActor *self)
g_return_if_fail (CLUTTER_IS_ACTOR (self));
if (self->priv->has_key_focus)
return;
stage = _clutter_actor_get_stage_internal (self);
if (stage != NULL)
clutter_stage_set_key_focus (CLUTTER_STAGE (stage), self);
@ -16768,6 +16778,23 @@ _clutter_actor_set_has_pointer (ClutterActor *self,
}
}
void
_clutter_actor_set_has_key_focus (ClutterActor *self,
gboolean has_key_focus)
{
ClutterActorPrivate *priv = self->priv;
if (priv->has_key_focus != has_key_focus)
{
priv->has_key_focus = has_key_focus;
if (has_key_focus)
g_signal_emit (self, actor_signals[KEY_FOCUS_IN], 0);
else
g_signal_emit (self, actor_signals[KEY_FOCUS_OUT], 0);
}
}
/**
* clutter_actor_get_text_direction:
* @self: a #ClutterActor
@ -17616,15 +17643,9 @@ clutter_actor_clear_effects (ClutterActor *self)
gboolean
clutter_actor_has_key_focus (ClutterActor *self)
{
ClutterActor *stage;
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
stage = _clutter_actor_get_stage_internal (self);
if (stage == NULL)
return FALSE;
return clutter_stage_get_key_focus (CLUTTER_STAGE (stage)) == self;
return self->priv->has_key_focus;
}
static gboolean

View File

@ -30,6 +30,7 @@ enum
PROP_LAYOUT,
PROP_FRAMEBUFFER,
PROP_OFFSCREEN,
PROP_SHADOWFB,
PROP_SCALE,
PROP_LAST
@ -44,7 +45,10 @@ typedef struct _ClutterStageViewPrivate
CoglFramebuffer *framebuffer;
CoglOffscreen *offscreen;
CoglPipeline *pipeline;
CoglPipeline *offscreen_pipeline;
CoglOffscreen *shadowfb;
CoglPipeline *shadowfb_pipeline;
guint dirty_viewport : 1;
guint dirty_projection : 1;
@ -78,6 +82,8 @@ clutter_stage_view_get_framebuffer (ClutterStageView *view)
if (priv->offscreen)
return priv->offscreen;
else if (priv->shadowfb)
return priv->shadowfb;
else
return priv->framebuffer;
}
@ -99,6 +105,24 @@ clutter_stage_view_get_onscreen (ClutterStageView *view)
return priv->framebuffer;
}
static CoglPipeline *
clutter_stage_view_create_framebuffer_pipeline (CoglFramebuffer *framebuffer)
{
CoglPipeline *pipeline;
pipeline = cogl_pipeline_new (cogl_framebuffer_get_context (framebuffer));
cogl_pipeline_set_layer_filters (pipeline, 0,
COGL_PIPELINE_FILTER_NEAREST,
COGL_PIPELINE_FILTER_NEAREST);
cogl_pipeline_set_layer_texture (pipeline, 0,
cogl_offscreen_get_texture (framebuffer));
cogl_pipeline_set_layer_wrap_mode (pipeline, 0,
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
return pipeline;
}
static void
clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view)
{
@ -109,21 +133,27 @@ clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view)
g_assert (priv->offscreen != NULL);
if (priv->pipeline)
if (priv->offscreen_pipeline)
return;
priv->pipeline =
cogl_pipeline_new (cogl_framebuffer_get_context (priv->offscreen));
cogl_pipeline_set_layer_filters (priv->pipeline, 0,
COGL_PIPELINE_FILTER_NEAREST,
COGL_PIPELINE_FILTER_NEAREST);
cogl_pipeline_set_layer_texture (priv->pipeline, 0,
cogl_offscreen_get_texture (priv->offscreen));
cogl_pipeline_set_layer_wrap_mode (priv->pipeline, 0,
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
priv->offscreen_pipeline =
clutter_stage_view_create_framebuffer_pipeline (priv->offscreen);
if (view_class->setup_offscreen_blit_pipeline)
view_class->setup_offscreen_blit_pipeline (view, priv->pipeline);
view_class->setup_offscreen_blit_pipeline (view, priv->offscreen_pipeline);
}
static void
clutter_stage_view_ensure_shadowfb_blit_pipeline (ClutterStageView *view)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
if (priv->shadowfb_pipeline)
return;
priv->shadowfb_pipeline =
clutter_stage_view_create_framebuffer_pipeline (priv->shadowfb);
}
void
@ -132,7 +162,45 @@ clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view)
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
g_clear_pointer (&priv->pipeline, cogl_object_unref);
g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref);
}
static void
clutter_stage_view_copy_to_framebuffer (ClutterStageView *view,
const cairo_rectangle_int_t *rect,
CoglPipeline *pipeline,
CoglFramebuffer *src_framebuffer,
CoglFramebuffer *dst_framebuffer,
gboolean can_blit)
{
CoglMatrix matrix;
/* First, try with blit */
if (can_blit)
{
if (cogl_blit_framebuffer (src_framebuffer,
dst_framebuffer,
0, 0,
0, 0,
cogl_framebuffer_get_width (dst_framebuffer),
cogl_framebuffer_get_height (dst_framebuffer),
NULL))
return;
}
/* If blit fails, fallback to the slower painting method */
cogl_framebuffer_push_matrix (dst_framebuffer);
cogl_matrix_init_identity (&matrix);
cogl_matrix_translate (&matrix, -1, 1, 0);
cogl_matrix_scale (&matrix, 2, -2, 0);
cogl_framebuffer_set_projection_matrix (dst_framebuffer, &matrix);
cogl_framebuffer_draw_rectangle (dst_framebuffer,
pipeline,
0, 0, 1, 1);
cogl_framebuffer_pop_matrix (dst_framebuffer);
}
void
@ -141,39 +209,46 @@ clutter_stage_view_blit_offscreen (ClutterStageView *view,
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
CoglMatrix matrix;
clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix);
if (cogl_matrix_is_identity (&matrix))
if (priv->offscreen)
{
int fb_width = cogl_framebuffer_get_width (priv->framebuffer);
int fb_height = cogl_framebuffer_get_height (priv->framebuffer);
gboolean can_blit;
CoglMatrix matrix;
if (cogl_blit_framebuffer (priv->offscreen,
priv->framebuffer,
0, 0,
0, 0,
fb_width, fb_height,
NULL))
return;
clutter_stage_view_ensure_offscreen_blit_pipeline (view);
clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix);
can_blit = cogl_matrix_is_identity (&matrix);
if (priv->shadowfb)
{
clutter_stage_view_copy_to_framebuffer (view,
rect,
priv->offscreen_pipeline,
priv->offscreen,
priv->shadowfb,
can_blit);
}
else
{
clutter_stage_view_copy_to_framebuffer (view,
rect,
priv->offscreen_pipeline,
priv->offscreen,
priv->framebuffer,
can_blit);
}
}
clutter_stage_view_ensure_offscreen_blit_pipeline (view);
cogl_framebuffer_push_matrix (priv->framebuffer);
/* Set transform so 0,0 is on the top left corner and 1,1 on
* the bottom right corner.
*/
cogl_matrix_init_identity (&matrix);
cogl_matrix_translate (&matrix, -1, 1, 0);
cogl_matrix_scale (&matrix, 2, -2, 0);
cogl_framebuffer_set_projection_matrix (priv->framebuffer, &matrix);
cogl_framebuffer_draw_rectangle (priv->framebuffer,
priv->pipeline,
0, 0, 1, 1);
cogl_framebuffer_pop_matrix (priv->framebuffer);
if (priv->shadowfb)
{
clutter_stage_view_ensure_shadowfb_blit_pipeline (view);
clutter_stage_view_copy_to_framebuffer (view,
rect,
priv->shadowfb_pipeline,
priv->shadowfb,
priv->framebuffer,
TRUE);
}
}
float
@ -273,6 +348,9 @@ clutter_stage_view_get_property (GObject *object,
case PROP_OFFSCREEN:
g_value_set_boxed (value, priv->offscreen);
break;
case PROP_SHADOWFB:
g_value_set_boxed (value, priv->shadowfb);
break;
case PROP_SCALE:
g_value_set_float (value, priv->scale);
break;
@ -318,6 +396,9 @@ clutter_stage_view_set_property (GObject *object,
case PROP_OFFSCREEN:
priv->offscreen = g_value_dup_boxed (value);
break;
case PROP_SHADOWFB:
priv->shadowfb = g_value_dup_boxed (value);
break;
case PROP_SCALE:
priv->scale = g_value_get_float (value);
break;
@ -334,8 +415,10 @@ clutter_stage_view_dispose (GObject *object)
clutter_stage_view_get_instance_private (view);
g_clear_pointer (&priv->framebuffer, cogl_object_unref);
g_clear_pointer (&priv->shadowfb, cogl_object_unref);
g_clear_pointer (&priv->offscreen, cogl_object_unref);
g_clear_pointer (&priv->pipeline, cogl_object_unref);
g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref);
g_clear_pointer (&priv->shadowfb_pipeline, cogl_object_unref);
G_OBJECT_CLASS (clutter_stage_view_parent_class)->dispose (object);
}
@ -390,6 +473,15 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_props[PROP_SHADOWFB] =
g_param_spec_boxed ("shadowfb",
"Shadow framebuffer",
"Framebuffer used as intermediate shadow buffer",
COGL_TYPE_HANDLE,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_props[PROP_SCALE] =
g_param_spec_float ("scale",
"View scale",

View File

@ -486,9 +486,9 @@ is_inside_axis_aligned_rectangle (const ClutterPoint *point,
const ClutterPoint *vertices)
{
float min_x = FLT_MAX;
float max_x = FLT_MIN;
float max_x = -FLT_MAX;
float min_y = FLT_MAX;
float max_y = FLT_MIN;
float max_y = -FLT_MAX;
int i;
for (i = 0; i < 3; i++)
@ -1066,10 +1066,7 @@ clutter_stage_emit_key_focus_event (ClutterStage *stage,
if (priv->key_focused_actor == NULL)
return;
if (focus_in)
g_signal_emit_by_name (priv->key_focused_actor, "key-focus-in");
else
g_signal_emit_by_name (priv->key_focused_actor, "key-focus-out");
_clutter_actor_set_has_key_focus (CLUTTER_ACTOR (stage), focus_in);
g_object_notify_by_pspec (G_OBJECT (stage), obj_props[PROP_KEY_FOCUS]);
}
@ -3011,14 +3008,6 @@ clutter_stage_get_title (ClutterStage *stage)
return stage->priv->title;
}
static void
on_key_focus_destroy (ClutterActor *actor,
ClutterStage *stage)
{
/* unset the key focus */
clutter_stage_set_key_focus (stage, NULL);
}
/**
* clutter_stage_set_key_focus:
* @stage: the #ClutterStage
@ -3058,18 +3047,14 @@ clutter_stage_set_key_focus (ClutterStage *stage,
old_focused_actor = priv->key_focused_actor;
/* set key_focused_actor to NULL before emitting the signal or someone
* might hide the previously focused actor in the signal handler and we'd
* get re-entrant call and get glib critical from g_object_weak_unref
* might hide the previously focused actor in the signal handler
*/
g_signal_handlers_disconnect_by_func (priv->key_focused_actor,
G_CALLBACK (on_key_focus_destroy),
stage);
priv->key_focused_actor = NULL;
g_signal_emit_by_name (old_focused_actor, "key-focus-out");
_clutter_actor_set_has_key_focus (old_focused_actor, FALSE);
}
else
g_signal_emit_by_name (stage, "key-focus-out");
_clutter_actor_set_has_key_focus (CLUTTER_ACTOR (stage), FALSE);
/* Note, if someone changes key focus in focus-out signal handler we'd be
* overriding the latter call below moving the focus where it was originally
@ -3079,14 +3064,10 @@ clutter_stage_set_key_focus (ClutterStage *stage,
if (actor != NULL)
{
priv->key_focused_actor = actor;
g_signal_connect (actor,
"destroy", G_CALLBACK (on_key_focus_destroy),
stage);
g_signal_emit_by_name (priv->key_focused_actor, "key-focus-in");
_clutter_actor_set_has_key_focus (actor, TRUE);
}
else
g_signal_emit_by_name (stage, "key-focus-in");
_clutter_actor_set_has_key_focus (CLUTTER_ACTOR (stage), TRUE);
g_object_notify_by_pspec (G_OBJECT (stage), obj_props[PROP_KEY_FOCUS]);
}

View File

@ -526,11 +526,7 @@ paint_stage (ClutterStageCogl *stage_cogl,
_clutter_stage_maybe_setup_viewport (stage, view);
_clutter_stage_paint_view (stage, view, clip);
if (clutter_stage_view_get_onscreen (view) !=
clutter_stage_view_get_framebuffer (view))
{
clutter_stage_view_blit_offscreen (view, clip);
}
clutter_stage_view_blit_offscreen (view, clip);
}
static void

View File

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

View File

@ -6,21 +6,22 @@
# Philip Withnall <philip@tecnocode.co.uk>, 2010.
# Chris Leonard <cjlhomeaddress@gmail.com>, 2012.
# Bruce Cowan <bruce@bcowan.me.uk>, 2011, 2012, 2013, 2018.
# Zander Brown <zbrown@gnome.org>, 2019.
#
msgid ""
msgstr ""
"Project-Id-Version: mutter\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-19 17:43+0100\n"
"Last-Translator: Bruce Cowan <bruce@bcowan.me.uk>\n"
"Language-Team: British English <en@li.org>\n"
"POT-Creation-Date: 2019-11-22 01:35+0000\n"
"PO-Revision-Date: 2019-08-25 15:11+0100\n"
"Last-Translator: Zander Brown <zbrown@gnome.org>\n"
"Language-Team: English - United Kingdom <en_GB@li.org>\n"
"Language: en_GB\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: Poedit 2.0.7\n"
"X-Generator: Gtranslator 3.32.1\n"
"X-Project-Style: gnome\n"
#: data/50-mutter-navigation.xml:6
@ -256,11 +257,6 @@ msgid "Modifier to use for extended window management operations"
msgstr "Modifier to use for extended window management operations"
#: data/org.gnome.mutter.gschema.xml.in:8
#| msgid ""
#| "This key will initiate the \"overlay\", which is a combination window "
#| "overview and application launching system. The default is intended to be "
#| "the \"Windows key\" on PC hardware. It's expected that this binding "
#| "either the default or set to the empty string."
msgid ""
"This key will initiate the “overlay”, which is a combination window overview "
"and application launching system. The default is intended to be the “Windows "
@ -305,10 +301,6 @@ msgid "Workspaces are managed dynamically"
msgstr "Workspaces are managed dynamically"
#: data/org.gnome.mutter.gschema.xml.in:41
#| msgid ""
#| "Determines whether workspaces are managed dynamically or whether there's "
#| "a static number of workspaces (determined by the num-workspaces key in "
#| "org.gnome.desktop.wm.preferences)."
msgid ""
"Determines whether workspaces are managed dynamically or whether theres a "
"static number of workspaces (determined by the num-workspaces key in org."
@ -347,10 +339,6 @@ msgid "Delay focus changes until the pointer stops moving"
msgstr "Delay focus changes until the pointer stops moving"
#: data/org.gnome.mutter.gschema.xml.in:69
#| msgid ""
#| "If set to true, and the focus mode is either \"sloppy\" or \"mouse\" then "
#| "the focus will not be changed immediately when entering a window, but "
#| "only after the pointer stops moving."
msgid ""
"If set to true, and the focus mode is either “sloppy” or “mouse” then the "
"focus will not be changed immediately when entering a window, but only after "
@ -365,9 +353,6 @@ msgid "Draggable border width"
msgstr "Draggable border width"
#: data/org.gnome.mutter.gschema.xml.in:80
#| msgid ""
#| "The amount of total draggable borders. If the theme's visible borders are "
#| "not enough, invisible borders will be added to meet this value."
msgid ""
"The amount of total draggable borders. If the themes visible borders are "
"not enough, invisible borders will be added to meet this value."
@ -412,7 +397,10 @@ 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."
"manage HiDPI monitors. Does not require a restart. • “rt-scheduler” — makes "
"mutter request a low priority real-time scheduling. The executable or user "
"must have CAP_SYS_NICE. Requires a restart. • “autostart-xwayland” — "
"initializes Xwayland lazily if there are X11 clients. Requires restart."
msgstr ""
"To enable experimental features, add the feature keyword to the list. "
"Whether the feature requires restarting the compositor depends on the given "
@ -421,22 +409,32 @@ msgstr ""
"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."
"manage HiDPI monitors. Does not require a restart. • “rt-scheduler” — makes "
"mutter request a low priority real-time scheduling. The executable or user "
"must have CAP_SYS_NICE. Requires a restart. • “autostart-xwayland” — "
"initialises Xwayland lazily if there are X11 clients. Requires restart."
#: data/org.gnome.mutter.gschema.xml.in:141
#: data/org.gnome.mutter.gschema.xml.in:134
msgid "Modifier to use to locate the pointer"
msgstr "Modifier to use to locate the pointer"
#: data/org.gnome.mutter.gschema.xml.in:135
msgid "This key will initiate the “locate pointer” action."
msgstr "This key will initiate the “locate pointer” action."
#: data/org.gnome.mutter.gschema.xml.in:155
msgid "Select window from tab popup"
msgstr "Select window from tab popup"
#: data/org.gnome.mutter.gschema.xml.in:146
#: data/org.gnome.mutter.gschema.xml.in:160
msgid "Cancel tab popup"
msgstr "Cancel tab popup"
#: data/org.gnome.mutter.gschema.xml.in:151
#| msgid "Switch monitor"
#: data/org.gnome.mutter.gschema.xml.in:165
msgid "Switch monitor configurations"
msgstr "Switch monitor configurations"
#: data/org.gnome.mutter.gschema.xml.in:156
#: data/org.gnome.mutter.gschema.xml.in:170
msgid "Rotates the built-in monitor configuration"
msgstr "Rotates the built-in monitor configuration"
@ -493,28 +491,36 @@ msgid "Re-enable shortcuts"
msgstr "Re-enable shortcuts"
#: data/org.gnome.mutter.wayland.gschema.xml.in:64
msgid "Allow grabs with Xwayland"
msgstr "Allow grabs with Xwayland"
msgid "Allow X11 grabs to lock keyboard focus with Xwayland"
msgstr "Allow X11 grabs to lock keyboard focus with Xwayland"
#: 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”."
"Allow all keyboard events to be routed to X11 “override redirect” windows "
"with a grab when running in Xwayland. This option is to support X11 clients "
"which map an “override redirect” window (which do not receive keyboard "
"focus) and issue a keyboard grab to force all keyboard events to that "
"window. This option is seldom used and has no effect on regular X11 windows "
"which can receive keyboard focus under normal circumstances. 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 ""
"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”."
"Allow all keyboard events to be routed to X11 “override redirect” windows "
"with a grab when running in Xwayland. This option is to support X11 clients "
"which map an “override redirect” window (which do not receive keyboard "
"focus) and issue a keyboard grab to force all keyboard events to that "
"window. This option is seldom used and has no effect on regular X11 windows "
"which can receive keyboard focus under normal circumstances. 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”."
#: data/org.gnome.mutter.wayland.gschema.xml.in:77
#: data/org.gnome.mutter.wayland.gschema.xml.in:84
msgid "Xwayland applications allowed to issue keyboard grabs"
msgstr "Xwayland applications allowed to issue keyboard grabs"
#: data/org.gnome.mutter.wayland.gschema.xml.in:78
#: data/org.gnome.mutter.wayland.gschema.xml.in:85
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 "
@ -541,114 +547,122 @@ 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:2528
#, c-format
#| msgid "Mode Switch: Mode %d"
msgid "Mode Switch (Group %d)"
msgstr "Mode Switch (Group %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:2551
msgid "Switch monitor"
msgstr "Switch monitor"
#: src/backends/meta-input-settings.c:2350
#: src/backends/meta-input-settings.c:2553
msgid "Show on-screen help"
msgstr "Show on-screen help"
#: src/backends/meta-monitor-manager.c:907
#: src/backends/meta-monitor.c:223
msgid "Built-in display"
msgstr "Built-in display"
#: src/backends/meta-monitor-manager.c:930
#: src/backends/meta-monitor.c:252
msgid "Unknown"
msgstr "Unknown"
#: src/backends/meta-monitor-manager.c:932
#: src/backends/meta-monitor.c:254
msgid "Unknown Display"
msgstr "Unknown Display"
#. 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.c:262
#, c-format
msgctxt ""
"This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'"
msgid "%s %s"
msgstr "%s %s"
#: src/backends/meta-monitor.c:270
#, c-format
msgctxt ""
"This is a monitor vendor name followed by product/model name where size in "
"inches could not be calculated, e.g. Dell U2414H"
msgid "%s %s"
msgstr "%s %s"
#. Translators: this string will appear in Sysprof
#: src/backends/meta-profiler.c:79
msgid "Compositor"
msgstr "Compositor"
#. 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:533
#, c-format
#| msgid ""
#| "Another compositing manager is already running on screen %i on display "
#| "\"%s\"."
msgid ""
"Another compositing manager is already running on screen %i on display “%s”."
msgstr ""
"Another compositing manager is already running on screen %i on display “%s”."
#: src/core/bell.c:254
#: src/core/bell.c:192
msgid "Bell event"
msgstr "Bell event"
#: src/core/main.c:191
#: src/core/main.c:190
msgid "Disable connection to session manager"
msgstr "Disable connection to session manager"
#: src/core/main.c:197
#: src/core/main.c:196
msgid "Replace the running window manager"
msgstr "Replace the running window manager"
#: src/core/main.c:203
#: src/core/main.c:202
msgid "Specify session management ID"
msgstr "Specify session management ID"
#: src/core/main.c:208
#: src/core/main.c:207
msgid "X Display to use"
msgstr "X Display to use"
#: src/core/main.c:214
#: src/core/main.c:213
msgid "Initialize session from savefile"
msgstr "Initialise session from savefile"
#: src/core/main.c:220
#: src/core/main.c:219
msgid "Make X calls synchronous"
msgstr "Make X calls synchronous"
#: src/core/main.c:227
#: src/core/main.c:226
msgid "Run as a wayland compositor"
msgstr "Run as a wayland compositor"
#: src/core/main.c:233
#: src/core/main.c:232
msgid "Run as a nested compositor"
msgstr "Run as a nested compositor"
#: src/core/main.c:239
#: src/core/main.c:238
msgid "Run wayland compositor without starting Xwayland"
msgstr "Run wayland compositor without starting Xwayland"
#: src/core/main.c:247
#: src/core/main.c:246
msgid "Run as a full display server, rather than nested"
msgstr "Run as a full display server, rather than nested"
#: src/core/main.c:253
#: src/core/main.c:252
msgid "Run with X11 backend"
msgstr "Run with X11 backend"
#. Translators: %s is a window title
#: src/core/meta-close-dialog-default.c:148
#: src/core/meta-close-dialog-default.c:151
#, c-format
msgid "“%s” is not responding."
msgstr "“%s” is not responding."
#: src/core/meta-close-dialog-default.c:150
#: src/core/meta-close-dialog-default.c:153
msgid "Application is not responding."
msgstr "Application is not responding."
#: src/core/meta-close-dialog-default.c:155
#: src/core/meta-close-dialog-default.c:158
msgid ""
"You may choose to wait a short while for it to continue or force the "
"application to quit entirely."
@ -656,22 +670,16 @@ msgstr ""
"You may choose to wait a short while for it to continue or force the "
"application to quit entirely."
#: src/core/meta-close-dialog-default.c:162
#: src/core/meta-close-dialog-default.c:165
msgid "_Force Quit"
msgstr "_Force Quit"
#: src/core/meta-close-dialog-default.c:162
#: src/core/meta-close-dialog-default.c:165
msgid "_Wait"
msgstr "_Wait"
#: src/core/mutter.c:39
#: src/core/mutter.c:38
#, c-format
#| msgid ""
#| "mutter %s\n"
#| "Copyright (C) 2001-%d Havoc Pennington, Red Hat, Inc., and others\n"
#| "This is free software; see the source for copying conditions.\n"
#| "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A "
#| "PARTICULAR PURPOSE.\n"
msgid ""
"mutter %s\n"
"Copyright © 2001-%d Havoc Pennington, Red Hat, Inc., and others\n"
@ -685,33 +693,30 @@ msgstr ""
"There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A "
"PARTICULAR PURPOSE.\n"
#: src/core/mutter.c:53
#: src/core/mutter.c:52
msgid "Print version"
msgstr "Print version"
#: src/core/mutter.c:59
#: src/core/mutter.c:58
msgid "Mutter plugin to use"
msgstr "Mutter plugin to use"
#: src/core/prefs.c:1915
#: src/core/prefs.c:1849
#, c-format
msgid "Workspace %d"
msgstr "Workspace %d"
#: src/core/util.c:120
#: src/core/util.c:122
msgid "Mutter was compiled without support for verbose mode\n"
msgstr "Mutter was compiled without support for verbose mode\n"
#: src/wayland/meta-wayland-tablet-pad.c:567
#: src/wayland/meta-wayland-tablet-pad.c:568
#, c-format
msgid "Mode Switch: Mode %d"
msgstr "Mode Switch: Mode %d"
#: src/x11/meta-x11-display.c:666
#: src/x11/meta-x11-display.c:675
#, c-format
#| msgid ""
#| "Display \"%s\" already has a window manager; try using the --replace "
#| "option to replace the current window manager."
msgid ""
"Display “%s” already has a window manager; try using the --replace option to "
"replace the current window manager."
@ -719,26 +724,26 @@ msgstr ""
"Display “%s” already has a window manager; try using the --replace option to "
"replace the current window manager."
#: src/x11/meta-x11-display.c:1010
#: src/x11/meta-x11-display.c:1036
msgid "Failed to initialize GDK\n"
msgstr "Failed to initialise GDK\n"
#: src/x11/meta-x11-display.c:1034
#: src/x11/meta-x11-display.c:1060
#, c-format
#| msgid "Failed to open X Window System display '%s'\n"
msgid "Failed to open X Window System display “%s”\n"
msgstr "Failed to open X Window System display “%s”\n"
#: src/x11/meta-x11-display.c:1117
#: src/x11/meta-x11-display.c:1143
#, c-format
#| msgid "Screen %d on display '%s' is invalid\n"
msgid "Screen %d on display “%s” is invalid\n"
msgstr "Screen %d on display “%s” is invalid\n"
#: src/x11/session.c:1819
#| msgid ""
#| "These windows do not support &quot;save current setup&quot; and will have "
#| "to be restarted manually next time you log in."
#: src/x11/meta-x11-selection-input-stream.c:460
#, c-format
msgid "Format %s not supported"
msgstr "Format %s not supported"
#: src/x11/session.c:1821
msgid ""
"These windows do not support “save current setup” and will have to be "
"restarted manually next time you log in."
@ -746,7 +751,7 @@ msgstr ""
"These windows do not support “save current setup” and will have to be "
"restarted manually next time you log in."
#: src/x11/window-props.c:565
#: src/x11/window-props.c:569
#, c-format
msgid "%s (on %s)"
msgstr "%s (on %s)"
@ -2033,9 +2038,6 @@ msgstr "%s (on %s)"
#~ msgid "Commands to run in response to keybindings"
#~ msgstr "Commands to run in response to keybindings"
#~ msgid "Compositing Manager"
#~ msgstr "Compositing Manager"
#~ msgid "Control how new windows get focus"
#~ msgstr "Control how new windows get focus"

View File

@ -49,6 +49,14 @@
#define DEFAULT_XKB_RULES_FILE "evdev"
#define DEFAULT_XKB_MODEL "pc105+inet"
typedef enum
{
META_SEQUENCE_NONE,
META_SEQUENCE_ACCEPTED,
META_SEQUENCE_REJECTED,
META_SEQUENCE_PENDING_END
} MetaSequenceState;
struct _MetaBackendClass
{
GObjectClass parent_class;
@ -71,6 +79,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);
@ -135,6 +147,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

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

@ -31,6 +31,7 @@ struct _MetaCursorTracker {
GObject parent_instance;
gboolean is_showing;
gboolean keep_focus_while_hidden;
MetaCursorSprite *effective_cursor; /* May be NULL when hidden */
MetaCursorSprite *displayed_cursor;

View File

@ -136,6 +136,7 @@ static void
meta_cursor_tracker_init (MetaCursorTracker *self)
{
self->is_showing = TRUE;
self->keep_focus_while_hidden = FALSE;
}
static void
@ -457,6 +458,44 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
g_signal_emit (tracker, signals[VISIBILITY_CHANGED], 0);
}
/**
* meta_cursor_tracker_get_keep_focus_while_hidden:
* @tracker: a #MetaCursorTracker object.
*
* Returns: %FALSE if the Wayland focus surface of the pointer will
* be forced to NULL while the pointer is hidden, %TRUE otherwise.
* This function is only meant to be used by the magnifier of the shell
* and will be removed in a future release.
*/
gboolean
meta_cursor_tracker_get_keep_focus_while_hidden (MetaCursorTracker *tracker)
{
return tracker->keep_focus_while_hidden;
}
/**
* meta_cursor_tracker_set_keep_focus_while_hidden:
* @tracker: a #MetaCursorTracker object.
* @keep_focus: whether to keep the cursor focus while hidden
*
* If this is set to %TRUE, the Wayland focus surface of the pointer will
* not be forced to NULL while the pointer is hidden.
* This function is only meant to be used by the magnifier of the shell
* and will be removed in a future release.
*/
void
meta_cursor_tracker_set_keep_focus_while_hidden (MetaCursorTracker *tracker,
gboolean keep_focus)
{
if (keep_focus == tracker->keep_focus_while_hidden)
return;
tracker->keep_focus_while_hidden = keep_focus;
sync_cursor (tracker);
g_signal_emit (tracker, signals[VISIBILITY_CHANGED], 0);
}
MetaCursorSprite *
meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker)
{

View File

@ -214,6 +214,8 @@ meta_dbus_session_watcher_finalize (GObject *object)
MetaDbusSessionWatcher *session_watcher = META_DBUS_SESSION_WATCHER (object);
g_hash_table_destroy (session_watcher->clients);
G_OBJECT_CLASS (meta_dbus_session_watcher_parent_class)->finalize (object);
}
static void

View File

@ -1648,6 +1648,7 @@ create_monitor_config_from_variant (MetaMonitorManager *manager,
MetaMonitorModeSpec *monitor_mode_spec;
g_autoptr (GVariant) properties_variant = NULL;
gboolean enable_underscanning = FALSE;
gboolean set_underscanning = FALSE;
g_variant_get (monitor_config_variant, "(ss@a{sv})",
&connector,
@ -1670,7 +1671,18 @@ create_monitor_config_from_variant (MetaMonitorManager *manager,
return NULL;
}
g_variant_lookup (properties_variant, "underscanning", "b", &enable_underscanning);
set_underscanning =
g_variant_lookup (properties_variant, "underscanning", "b",
&enable_underscanning);
if (set_underscanning)
{
if (enable_underscanning && !meta_monitor_supports_underscanning (monitor))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Underscanning requested but unsupported");
return NULL;
}
}
monitor_spec = meta_monitor_spec_clone (meta_monitor_get_spec (monitor));

View File

@ -226,11 +226,15 @@ meta_screen_cast_window_stream_initable_init (GInitable *initable,
G_CALLBACK (on_window_unmanaged),
window_stream);
if (meta_is_stage_views_scaled ())
scale = (int) ceilf (meta_logical_monitor_get_scale (logical_monitor));
else
scale = 1;
/* We cannot set the stream size to the exact size of the window, because
* windows can be resized, whereas streams cannot.
* So we set a size equals to the size of the logical monitor for the window.
*/
scale = (int) ceil (meta_logical_monitor_get_scale (logical_monitor));
window_stream->logical_width = logical_monitor->rect.width;
window_stream->logical_height = logical_monitor->rect.height;
window_stream->stream_width = logical_monitor->rect.width * scale;

View File

@ -583,7 +583,6 @@ on_udev_device_added (MetaUdev *udev,
{
g_warning ("Failed to hotplug secondary gpu '%s': %s",
device_path, error->message);
g_error_free (error);
return;
}

View File

@ -322,6 +322,7 @@ update_monitor_crtc_cursor (MetaMonitor *monitor,
&crtc_x, &crtc_y);
transform = meta_logical_monitor_get_transform (data->in_logical_monitor);
transform = meta_monitor_logical_to_crtc_transform (monitor, transform);
if (meta_monitor_transform_is_rotated (transform))
{
crtc_width = monitor_crtc_mode->crtc_mode->height;

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2019 Red Hat
* Copyright (C) 2019 DisplayLink (UK) Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@ -149,12 +150,28 @@ dispatch_in_impl (MetaKmsImpl *impl,
return meta_kms_impl_device_dispatch (impl_device, error);
}
static gboolean
dispatch_idle_in_impl (MetaKmsImpl *impl,
gpointer user_data,
GError **error)
{
meta_kms_impl_dispatch_idle (impl);
return TRUE;
}
int
meta_kms_device_dispatch_sync (MetaKmsDevice *device,
GError **error)
{
int callback_count;
if (!meta_kms_run_impl_task_sync (device->kms,
dispatch_idle_in_impl,
device->impl_device,
error))
return -1;
callback_count = meta_kms_flush_callbacks (device->kms);
if (callback_count > 0)
return TRUE;

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2018-2019 Red Hat
* Copyright (C) 2019 DisplayLink (UK) Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@ -518,7 +519,7 @@ mode_set_fallback_feedback_idle (gpointer user_data)
g_clear_pointer (&impl_simple->mode_set_fallback_feedback_source,
g_source_unref);
if (!impl_simple->pending_page_flip_retries)
if (impl_simple->pending_page_flip_retries)
{
impl_simple->postponed_mode_set_fallback_datas =
g_steal_pointer (&impl_simple->mode_set_fallback_page_flip_datas);
@ -772,12 +773,14 @@ meta_kms_impl_simple_handle_page_flip_callback (MetaKmsImpl *impl,
{
impl_simple->postponed_page_flip_datas =
g_list_append (impl_simple->postponed_page_flip_datas,
page_flip_data);
meta_kms_page_flip_data_ref (page_flip_data));
}
else
{
meta_kms_page_flip_data_flipped_in_impl (page_flip_data);
}
meta_kms_page_flip_data_unref (page_flip_data);
}
static void
@ -804,6 +807,15 @@ meta_kms_impl_simple_discard_pending_page_flips (MetaKmsImpl *impl)
g_source_destroy);
}
static void
meta_kms_impl_simple_dispatch_idle (MetaKmsImpl *impl)
{
MetaKmsImplSimple *impl_simple = META_KMS_IMPL_SIMPLE (impl);
if (impl_simple->mode_set_fallback_feedback_source)
mode_set_fallback_feedback_idle (impl_simple);
}
static void
meta_kms_impl_simple_finalize (GObject *object)
{
@ -843,4 +855,5 @@ meta_kms_impl_simple_class_init (MetaKmsImplSimpleClass *klass)
impl_class->process_update = meta_kms_impl_simple_process_update;
impl_class->handle_page_flip_callback = meta_kms_impl_simple_handle_page_flip_callback;
impl_class->discard_pending_page_flips = meta_kms_impl_simple_discard_pending_page_flips;
impl_class->dispatch_idle = meta_kms_impl_simple_dispatch_idle;
}

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2018 Red Hat
* Copyright (C) 2019 DisplayLink (UK) Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@ -65,6 +66,12 @@ meta_kms_impl_discard_pending_page_flips (MetaKmsImpl *impl)
META_KMS_IMPL_GET_CLASS (impl)->discard_pending_page_flips (impl);
}
void
meta_kms_impl_dispatch_idle (MetaKmsImpl *impl)
{
META_KMS_IMPL_GET_CLASS (impl)->dispatch_idle (impl);
}
static void
meta_kms_impl_set_property (GObject *object,
guint prop_id,

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2018 Red Hat
* Copyright (C) 2019 DisplayLink (UK) Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@ -38,6 +39,7 @@ struct _MetaKmsImplClass
void (* handle_page_flip_callback) (MetaKmsImpl *impl,
MetaKmsPageFlipData *page_flip_data);
void (* discard_pending_page_flips) (MetaKmsImpl *impl);
void (* dispatch_idle) (MetaKmsImpl *impl);
};
MetaKms * meta_kms_impl_get_kms (MetaKmsImpl *impl);
@ -51,4 +53,6 @@ void meta_kms_impl_handle_page_flip_callback (MetaKmsImpl *impl,
void meta_kms_impl_discard_pending_page_flips (MetaKmsImpl *impl);
void meta_kms_impl_dispatch_idle (MetaKmsImpl *impl);
#endif /* META_KMS_IMPL_H */

View File

@ -295,7 +295,6 @@ meta_create_kms_output (MetaGpuKms *gpu_kms,
MetaOutput *output;
MetaOutputKms *output_kms;
const MetaKmsConnectorState *connector_state;
MetaMonitorTransform panel_orientation_transform;
uint32_t connector_id;
GArray *crtcs;
GList *l;
@ -318,8 +317,9 @@ meta_create_kms_output (MetaGpuKms *gpu_kms,
connector_state = meta_kms_connector_get_current_state (kms_connector);
panel_orientation_transform = connector_state->panel_orientation_transform;
if (meta_monitor_transform_is_rotated (panel_orientation_transform))
output->panel_orientation_transform =
connector_state->panel_orientation_transform;
if (meta_monitor_transform_is_rotated (output->panel_orientation_transform))
{
output->width_mm = connector_state->height_mm;
output->height_mm = connector_state->width_mm;

View File

@ -3053,7 +3053,6 @@ meta_renderer_native_create_onscreen (MetaRendererNative *renderer_native,
static CoglOffscreen *
meta_renderer_native_create_offscreen (MetaRendererNative *renderer,
CoglContext *context,
MetaMonitorTransform transform,
gint view_width,
gint view_height,
GError **error)
@ -3256,6 +3255,7 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
MetaMonitorTransform view_transform;
CoglOnscreen *onscreen = NULL;
CoglOffscreen *offscreen = NULL;
CoglOffscreen *shadowfb = NULL;
float scale;
int width, height;
MetaRendererView *view;
@ -3282,18 +3282,35 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
if (!onscreen)
g_error ("Failed to allocate onscreen framebuffer: %s", error->message);
if (view_transform != META_MONITOR_TRANSFORM_NORMAL ||
should_force_shadow_fb (renderer_native,
renderer_native->primary_gpu_kms))
if (view_transform != META_MONITOR_TRANSFORM_NORMAL)
{
offscreen = meta_renderer_native_create_offscreen (renderer_native,
cogl_context,
view_transform,
width,
height,
&error);
if (!offscreen)
g_error ("Failed to allocate back buffer texture: %s", error->message);
}
if (should_force_shadow_fb (renderer_native,
renderer_native->primary_gpu_kms))
{
int shadow_width;
int shadow_height;
/* The shadowfb must be the same size as the on-screen framebuffer */
shadow_width = cogl_framebuffer_get_width (COGL_FRAMEBUFFER (onscreen));
shadow_height = cogl_framebuffer_get_height (COGL_FRAMEBUFFER (onscreen));
shadowfb = meta_renderer_native_create_offscreen (renderer_native,
cogl_context,
shadow_width,
shadow_height,
&error);
if (!shadowfb)
g_error ("Failed to allocate shadow buffer texture: %s", error->message);
}
view = g_object_new (META_TYPE_RENDERER_VIEW,
@ -3301,10 +3318,12 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
"scale", scale,
"framebuffer", onscreen,
"offscreen", offscreen,
"shadowfb", shadowfb,
"logical-monitor", logical_monitor,
"transform", view_transform,
NULL);
g_clear_pointer (&offscreen, cogl_object_unref);
g_clear_pointer (&shadowfb, cogl_object_unref);
meta_onscreen_native_set_view (onscreen, view);

View File

@ -67,6 +67,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;
@ -175,6 +179,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)
@ -184,19 +208,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
@ -261,6 +273,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:
@ -329,6 +344,17 @@ handle_host_xevent (MetaBackend *backend,
gboolean bypass_clutter = FALSE;
MetaDisplay *display;
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);
display = meta_get_display ();
@ -533,6 +559,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 *
@ -590,6 +620,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,
meta_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,
@ -781,6 +848,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

@ -1291,6 +1291,22 @@ handle_raw_event (MetaDeviceManagerX11 *manager_xi2,
}
}
static ClutterInputDevice *
get_source_device_checked (MetaDeviceManagerX11 *manager_xi2,
XIDeviceEvent *xev)
{
ClutterInputDevice *source_device;
source_device = g_hash_table_lookup (manager_xi2->devices_by_id,
GINT_TO_POINTER (xev->sourceid));
if (!source_device)
g_warning ("Impossible to get the source device with id %d for event of "
"type %d", xev->sourceid, xev->evtype);
return source_device;
}
gboolean
meta_device_manager_x11_translate_event (MetaDeviceManagerX11 *manager_xi2,
XEvent *xevent,
@ -1379,6 +1395,10 @@ meta_device_manager_x11_translate_event (MetaDeviceManagerX11 *manager_xi2,
char buffer[7] = { 0, };
gunichar n;
source_device = get_source_device_checked (manager_xi2, xev);
if (!source_device)
return FALSE;
event->key.type = event->type = (xev->evtype == XI_KeyPress)
? CLUTTER_KEY_PRESS
: CLUTTER_KEY_RELEASE;
@ -1413,8 +1433,6 @@ meta_device_manager_x11_translate_event (MetaDeviceManagerX11 *manager_xi2,
event_x11->caps_lock_set =
clutter_keymap_get_caps_lock_state (CLUTTER_KEYMAP (keymap_x11));
source_device = g_hash_table_lookup (manager_xi2->devices_by_id,
GINT_TO_POINTER (xev->sourceid));
clutter_event_set_source_device (event, source_device);
device = g_hash_table_lookup (manager_xi2->devices_by_id,
@ -1458,8 +1476,10 @@ meta_device_manager_x11_translate_event (MetaDeviceManagerX11 *manager_xi2,
{
XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
source_device = g_hash_table_lookup (manager_xi2->devices_by_id,
GINT_TO_POINTER (xev->sourceid));
source_device = get_source_device_checked (manager_xi2, xev);
if (!source_device)
return FALSE;
device = g_hash_table_lookup (manager_xi2->devices_by_id,
GINT_TO_POINTER (xev->deviceid));
@ -1626,7 +1646,7 @@ meta_device_manager_x11_translate_event (MetaDeviceManagerX11 *manager_xi2,
break;
}
if (source_device != NULL && device->stage != NULL)
if (device->stage != NULL)
_clutter_input_device_set_stage (source_device, device->stage);
if (xev->flags & XIPointerEmulated)
@ -1644,8 +1664,10 @@ meta_device_manager_x11_translate_event (MetaDeviceManagerX11 *manager_xi2,
XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
double delta_x, delta_y;
source_device = g_hash_table_lookup (manager_xi2->devices_by_id,
GINT_TO_POINTER (xev->sourceid));
source_device = get_source_device_checked (manager_xi2, xev);
if (!source_device)
return FALSE;
device = g_hash_table_lookup (manager_xi2->devices_by_id,
GINT_TO_POINTER (xev->deviceid));
@ -1716,7 +1738,7 @@ meta_device_manager_x11_translate_event (MetaDeviceManagerX11 *manager_xi2,
event->motion.y,
&xev->valuators);
if (source_device != NULL && device->stage != NULL)
if (device->stage != NULL)
_clutter_input_device_set_stage (source_device, device->stage);
if (xev->flags & XIPointerEmulated)

View File

@ -118,9 +118,12 @@ get_property (ClutterInputDevice *device,
device_id = clutter_input_device_get_device_id (device);
clutter_x11_trap_x_errors ();
rc = XIGetProperty (xdisplay, device_id, property_atom,
0, 10, False, type, &type_ret, &format_ret,
&nitems_ret, &bytes_after_ret, &data_ret);
clutter_x11_untrap_x_errors ();
if (rc == Success && type_ret == type && format_ret == format && nitems_ret >= nitems)
{
if (nitems_ret > nitems)

View File

@ -573,6 +573,8 @@ meta_background_actor_paint (ClutterActor *actor)
paint_clipped_rectangle (fb, self->pipeline, &rect,
&self->texture_area);
}
cairo_region_destroy (region);
}
static void

View File

@ -195,6 +195,8 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
if (klass->destroy)
{
retval = TRUE;
meta_plugin_manager_kill_window_effects (plugin_mgr,
actor);
klass->destroy (plugin, actor);
}
break;

View File

@ -492,8 +492,6 @@ set_cogl_texture (MetaShapedTexture *stex,
if (stex->create_mipmaps)
meta_texture_tower_set_base_texture (stex->paint_tower, cogl_tex);
clutter_content_invalidate (CLUTTER_CONTENT (stex));
}
static gboolean

View File

@ -2183,21 +2183,25 @@ meta_window_actor_get_image (MetaWindowActor *self,
if (clutter_actor_get_n_children (actor) == 1)
{
MetaShapedTexture *stex;
MetaRectangle surface_clip;
int geometry_scale;
MetaRectangle *surface_clip = NULL;
geometry_scale =
meta_window_actor_get_geometry_scale (self);
if (clip)
{
surface_clip = (MetaRectangle) {
.x = clip->x / geometry_scale,
.y = clip->y / geometry_scale,
.width = clip->width / geometry_scale,
.height = clip->height / geometry_scale,
};
int geometry_scale;
geometry_scale =
meta_window_actor_get_geometry_scale (self);
surface_clip = g_alloca (sizeof (MetaRectangle));
surface_clip->x = clip->x / geometry_scale,
surface_clip->y = clip->y / geometry_scale;
surface_clip->width = clip->width / geometry_scale;
surface_clip->height = clip->height / geometry_scale;
}
stex = meta_surface_actor_get_texture (priv->surface);
return meta_shaped_texture_get_image (stex, &surface_clip);
return meta_shaped_texture_get_image (stex, surface_clip);
}
clutter_actor_get_size (actor, &width, &height);

View File

@ -590,6 +590,7 @@ minimize (MetaPlugin *plugin, MetaWindowActor *window_actor)
MetaWindowType type;
MetaRectangle icon_geometry;
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
ClutterTimeline *timeline = NULL;
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
@ -602,24 +603,28 @@ minimize (MetaPlugin *plugin, MetaWindowActor *window_actor)
}
if (type == META_WINDOW_NORMAL)
{
timeline = actor_animate (actor,
CLUTTER_EASE_IN_SINE,
MINIMIZE_TIMEOUT,
"scale-x", 0.0,
"scale-y", 0.0,
"x", (double)icon_geometry.x,
"y", (double)icon_geometry.y,
NULL);
}
if (timeline)
{
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
ActorPrivate *apriv = get_actor_private (window_actor);
apriv->tml_minimize = actor_animate (actor,
CLUTTER_EASE_IN_SINE,
MINIMIZE_TIMEOUT,
"scale-x", 0.0,
"scale-y", 0.0,
"x", (double)icon_geometry.x,
"y", (double)icon_geometry.y,
NULL);
apriv->tml_minimize = timeline;
data->plugin = plugin;
data->actor = actor;
g_signal_connect (apriv->tml_minimize, "completed",
G_CALLBACK (on_minimize_effect_complete),
data);
}
else
meta_plugin_minimize_completed (plugin, window_actor);
@ -708,21 +713,27 @@ destroy (MetaPlugin *plugin, MetaWindowActor *window_actor)
MetaWindowType type;
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
ClutterTimeline *timeline = NULL;
type = meta_window_get_window_type (meta_window);
if (type == META_WINDOW_NORMAL)
{
timeline = actor_animate (actor,
CLUTTER_EASE_OUT_QUAD,
DESTROY_TIMEOUT,
"opacity", 0,
"scale-x", 0.8,
"scale-y", 0.8,
NULL);
}
if (timeline)
{
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
ActorPrivate *apriv = get_actor_private (window_actor);
apriv->tml_destroy = actor_animate (actor,
CLUTTER_EASE_OUT_QUAD,
DESTROY_TIMEOUT,
"opacity", 0,
"scale-x", 0.8,
"scale-y", 0.8,
NULL);
apriv->tml_destroy = timeline;
data->plugin = plugin;
data->actor = actor;
g_signal_connect (apriv->tml_destroy, "completed",
@ -737,9 +748,8 @@ destroy (MetaPlugin *plugin, MetaWindowActor *window_actor)
* Tile preview private data accessor
*/
static void
free_display_tile_preview (gpointer data)
free_display_tile_preview (DisplayTilePreview *preview)
{
DisplayTilePreview *preview = data;
if (G_LIKELY (preview != NULL)) {
clutter_actor_destroy (preview->actor);
@ -747,15 +757,27 @@ free_display_tile_preview (gpointer data)
}
}
static void
on_display_closing (MetaDisplay *display,
DisplayTilePreview *preview)
{
free_display_tile_preview (preview);
}
static DisplayTilePreview *
get_display_tile_preview (MetaDisplay *display)
{
DisplayTilePreview *preview = g_object_get_qdata (G_OBJECT (display), display_tile_preview_data_quark);
DisplayTilePreview *preview;
if (G_UNLIKELY (display_tile_preview_data_quark == 0))
display_tile_preview_data_quark = g_quark_from_static_string (DISPLAY_TILE_PREVIEW_DATA_KEY);
if (!display_tile_preview_data_quark)
{
display_tile_preview_data_quark =
g_quark_from_static_string (DISPLAY_TILE_PREVIEW_DATA_KEY);
}
if (G_UNLIKELY (!preview))
preview = g_object_get_qdata (G_OBJECT (display),
display_tile_preview_data_quark);
if (!preview)
{
preview = g_slice_new0 (DisplayTilePreview);
@ -764,9 +786,13 @@ get_display_tile_preview (MetaDisplay *display)
clutter_actor_set_opacity (preview->actor, 100);
clutter_actor_add_child (meta_get_window_group_for_display (display), preview->actor);
g_object_set_qdata_full (G_OBJECT (display),
display_tile_preview_data_quark, preview,
free_display_tile_preview);
g_signal_connect (display,
"closing",
G_CALLBACK (on_display_closing),
preview);
g_object_set_qdata (G_OBJECT (display),
display_tile_preview_data_quark,
preview);
}
return preview;

View File

@ -40,6 +40,7 @@
#include <X11/extensions/Xdamage.h>
#include <X11/extensions/Xfixes.h>
#include "backends/meta-backend-private.h"
#include "backends/meta-cursor-sprite-xcursor.h"
#include "backends/meta-cursor-tracker-private.h"
#include "backends/meta-idle-monitor-dbus.h"
@ -155,6 +156,7 @@ enum
SHOWING_DESKTOP_CHANGED,
RESTACKED,
WORKAREAS_CHANGED,
CLOSING,
LAST_SIGNAL
};
@ -492,6 +494,12 @@ meta_display_class_init (MetaDisplayClass *klass)
G_SIGNAL_RUN_LAST,
0, NULL, NULL, NULL,
G_TYPE_NONE, 0);
display_signals[CLOSING] =
g_signal_new ("closing",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL, NULL,
G_TYPE_NONE, 0);
g_object_class_install_property (object_class,
PROP_FOCUS_WINDOW,
@ -622,27 +630,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,
meta_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;
}
}
}
@ -974,6 +978,8 @@ meta_display_close (MetaDisplay *display,
display->closing += 1;
g_signal_emit (display, display_signals[CLOSING], 0);
meta_compositor_unmanage (display->compositor);
meta_display_unmanage_windows (display, timestamp);

View File

@ -26,6 +26,7 @@
#include <glib-object.h>
#include "backends/meta-backend-private.h"
#include "clutter/clutter.h"
#include "meta/window.h"
@ -39,14 +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

@ -858,8 +858,11 @@ static void
ensure_above (MetaWindow *above,
MetaWindow *below)
{
if (WINDOW_HAS_TRANSIENT_TYPE(above) &&
above->layer < below->layer)
gboolean is_transient;
is_transient = WINDOW_HAS_TRANSIENT_TYPE (above) ||
above->transient_for == below;
if (is_transient && above->layer < below->layer)
{
meta_topic (META_DEBUG_STACK,
"Promoting window %s from layer %u to %u due to contraint\n",

View File

@ -629,6 +629,7 @@ void meta_window_unmanage (MetaWindow *window,
void meta_window_unmanage_on_idle (MetaWindow *window);
void meta_window_queue (MetaWindow *window,
guint queuebits);
META_EXPORT_TEST
void meta_window_tile (MetaWindow *window,
MetaTileMode mode);
MetaTileMode meta_window_get_tile_mode (MetaWindow *window);

View File

@ -1306,6 +1306,7 @@ _meta_window_shared_new (MetaDisplay *display,
"Putting window %s on same workspace as parent %s\n",
window->desc, window->transient_for->desc);
g_warn_if_fail (!window->transient_for->override_redirect);
set_workspace_state (window,
should_be_on_all_workspaces (window->transient_for),
window->transient_for->workspace);
@ -3192,7 +3193,10 @@ meta_window_tile (MetaWindow *window,
/* Don't do anything if no tiling is requested */
if (window->tile_mode == META_TILE_NONE)
return;
{
window->tile_monitor_number = -1;
return;
}
if (window->tile_mode == META_TILE_MAXIMIZED)
directions = META_MAXIMIZE_BOTH;
@ -3923,11 +3927,16 @@ meta_window_update_for_monitors_changed (MetaWindow *window)
if (!new)
new = meta_monitor_manager_get_primary_logical_monitor (monitor_manager);
if (window->tile_mode != META_TILE_NONE)
{
if (new)
window->tile_monitor_number = new->number;
else
window->tile_monitor_number = -1;
}
if (new && old)
{
if (window->tile_mode != META_TILE_NONE)
window->tile_monitor_number = new->number;
/* This will eventually reach meta_window_update_monitor that
* will send leave/enter-monitor events. The old != new monitor
* check will always fail (due to the new logical_monitors set) so
@ -4817,9 +4826,12 @@ set_workspace_state (MetaWindow *window,
{
MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
/* If we're on all workspaces, then our new workspace must be NULL. */
/* If we're on all workspaces, then our new workspace must be NULL,
* otherwise it must be set, unless we're unmanaging. */
if (on_all_workspaces)
g_assert (workspace == NULL);
g_assert_null (workspace);
else
g_assert_true (window->unmanaging || workspace != NULL);
/* If this is an override-redirect window, ensure that the only
* times we're setting the workspace state is either during construction

View File

@ -62,4 +62,11 @@ META_EXPORT
void meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
gboolean visible);
META_EXPORT
gboolean meta_cursor_tracker_get_keep_focus_while_hidden (MetaCursorTracker *tracker);
META_EXPORT
void meta_cursor_tracker_set_keep_focus_while_hidden (MetaCursorTracker *tracker,
gboolean keep_focus);
#endif

View File

@ -131,6 +131,7 @@ stacking_tests = [
'mixed-windows',
'set-parent',
'override-redirect',
'set-override-redirect-parent',
'set-parent-exported',
]

View File

@ -28,6 +28,7 @@
#include "backends/meta-monitor-config-migration.h"
#include "backends/meta-monitor-config-store.h"
#include "backends/meta-output.h"
#include "core/window-private.h"
#include "meta-backend-test.h"
#include "tests/meta-monitor-manager-test.h"
#include "tests/monitor-test-utils.h"
@ -378,15 +379,22 @@ create_monitor_test_clients (void)
}
static void
check_monitor_test_clients_state (void)
check_test_client_state (TestClient *test_client)
{
GError *error = NULL;
if (!test_client_wait (wayland_monitor_test_client, &error))
g_error ("Failed to sync Wayland test client: %s", error->message);
if (!test_client_wait (test_client, &error))
{
g_error ("Failed to sync test client '%s': %s",
test_client_get_id (test_client), error->message);
}
}
if (!test_client_wait (x11_monitor_test_client, &error))
g_error ("Failed to sync X11 test client: %s", error->message);
static void
check_monitor_test_clients_state (void)
{
check_test_client_state (wayland_monitor_test_client);
check_test_client_state (x11_monitor_test_client);
}
static void
@ -5753,6 +5761,128 @@ meta_test_monitor_migrated_wiggle_discard (void)
g_error ("Failed to remove test data output file: %s", error->message);
}
static gboolean
quit_main_loop (gpointer data)
{
GMainLoop *loop = data;
g_main_loop_quit (loop);
return G_SOURCE_REMOVE;
}
static void
dispatch (void)
{
GMainLoop *loop;
loop = g_main_loop_new (NULL, FALSE);
meta_later_add (META_LATER_BEFORE_REDRAW,
quit_main_loop,
loop,
NULL);
g_main_loop_run (loop);
}
static TestClient *
create_test_window (const char *window_name)
{
TestClient *test_client;
static int client_count = 0;
g_autofree char *client_name = NULL;
g_autoptr (GError) error = NULL;
client_name = g_strdup_printf ("test_client_%d", client_count++);
test_client = test_client_new (client_name, META_WINDOW_CLIENT_TYPE_WAYLAND,
&error);
if (!test_client)
g_error ("Failed to launch test client: %s", error->message);
if (!test_client_do (test_client, &error,
"create", window_name,
NULL))
g_error ("Failed to create window: %s", error->message);
return test_client;
}
static void
meta_test_monitor_wm_tiling (void)
{
MonitorTestCase test_case = initial_test_case;
MetaMonitorTestSetup *test_setup;
g_autoptr (GError) error = NULL;
test_setup = create_monitor_test_setup (&test_case,
MONITOR_TEST_FLAG_NO_STORED);
emulate_hotplug (test_setup);
/*
* 1) Start with two monitors connected.
* 2) Tile it on the second monitor.
* 3) Unplug both monitors.
* 4) Replug in first monitor.
*/
const char *test_window_name= "window1";
TestClient *test_client = create_test_window (test_window_name);
if (!test_client_do (test_client, &error,
"show", test_window_name,
NULL))
g_error ("Failed to show the window: %s", error->message);
MetaWindow *test_window =
test_client_find_window (test_client,
test_window_name,
&error);
if (!test_window)
g_error ("Failed to find the window: %s", error->message);
test_client_wait_for_window_shown (test_client, test_window);
meta_window_tile (test_window, META_TILE_MAXIMIZED);
meta_window_move_to_monitor (test_window, 1);
check_test_client_state (test_client);
fprintf(stderr, ":::: %s:%d %s() - UNPLUGGING\n", __FILE__, __LINE__, __func__);
test_case.setup.n_outputs = 0;
test_setup = create_monitor_test_setup (&test_case,
MONITOR_TEST_FLAG_NO_STORED);
emulate_hotplug (test_setup);
test_case.setup.n_outputs = 1;
test_setup = create_monitor_test_setup (&test_case,
MONITOR_TEST_FLAG_NO_STORED);
emulate_hotplug (test_setup);
dispatch ();
/*
* 1) Start with two monitors connected.
* 2) Tile a window on the second monitor.
* 3) Untile window.
* 4) Unplug monitor.
* 5) Tile window again.
*/
test_case.setup.n_outputs = 2;
test_setup = create_monitor_test_setup (&test_case,
MONITOR_TEST_FLAG_NO_STORED);
emulate_hotplug (test_setup);
meta_window_move_to_monitor (test_window, 1);
meta_window_tile (test_window, META_TILE_NONE);
test_case.setup.n_outputs = 1;
test_setup = create_monitor_test_setup (&test_case,
MONITOR_TEST_FLAG_NO_STORED);
emulate_hotplug (test_setup);
meta_window_tile (test_window, META_TILE_MAXIMIZED);
test_client_destroy (test_client);
}
static void
meta_test_monitor_migrated_wiggle (void)
{
@ -6008,6 +6138,9 @@ init_monitor_tests (void)
meta_test_monitor_migrated_wiggle);
add_monitor_test ("/backends/monitor/migrated/wiggle-discard",
meta_test_monitor_migrated_wiggle_discard);
add_monitor_test ("/backends/monitor/wm/tiling",
meta_test_monitor_wm_tiling);
}
void

View File

@ -0,0 +1,24 @@
new_client 1 x11
create 1/1 override
show 1/1
create 1/2
set_parent 1/2 1
show 1/2
create 1/3
set_parent 1/3 2
show 1/3
new_client 2 x11
create 2/1
show 2/1
create 2/2 override
set_parent 2/2 1
show 2/2
create 2/3
set_parent 2/3 2
show 2/3

View File

@ -342,39 +342,6 @@ test_case_check_xserver_stacking (TestCase *test,
return *error == NULL;
}
typedef struct _WaitForShownData
{
GMainLoop *loop;
MetaWindow *window;
guint shown_handler_id;
} WaitForShownData;
static void
on_window_shown (MetaWindow *window,
WaitForShownData *data)
{
g_main_loop_quit (data->loop);
}
static gboolean
test_case_wait_for_showing_before_redraw (gpointer user_data)
{
WaitForShownData *data = user_data;
if (meta_window_is_hidden (data->window))
{
data->shown_handler_id = g_signal_connect (data->window, "shown",
G_CALLBACK (on_window_shown),
data);
}
else
{
g_main_loop_quit (data->loop);
}
return FALSE;
}
static gboolean
test_case_do (TestCase *test,
int argc,
@ -533,18 +500,7 @@ test_case_do (TestCase *test,
if (!window)
return FALSE;
WaitForShownData data = {
.loop = g_main_loop_new (NULL, FALSE),
.window = window,
};
meta_later_add (META_LATER_BEFORE_REDRAW,
test_case_wait_for_showing_before_redraw,
&data,
NULL);
g_main_loop_run (data.loop);
if (data.shown_handler_id)
g_signal_handler_disconnect (window, data.shown_handler_id);
g_main_loop_unref (data.loop);
test_client_wait_for_window_shown (client, window);
}
else if (strcmp (argv[0], "hide") == 0 ||
strcmp (argv[0], "activate") == 0 ||

View File

@ -359,6 +359,57 @@ test_client_find_window (TestClient *client,
return result;
}
typedef struct _WaitForShownData
{
GMainLoop *loop;
MetaWindow *window;
guint shown_handler_id;
} WaitForShownData;
static void
on_window_shown (MetaWindow *window,
WaitForShownData *data)
{
g_main_loop_quit (data->loop);
}
static gboolean
wait_for_showing_before_redraw (gpointer user_data)
{
WaitForShownData *data = user_data;
if (meta_window_is_hidden (data->window))
{
data->shown_handler_id = g_signal_connect (data->window, "shown",
G_CALLBACK (on_window_shown),
data);
}
else
{
g_main_loop_quit (data->loop);
}
return FALSE;
}
void
test_client_wait_for_window_shown (TestClient *client,
MetaWindow *window)
{
WaitForShownData data = {
.loop = g_main_loop_new (NULL, FALSE),
.window = window,
};
meta_later_add (META_LATER_BEFORE_REDRAW,
wait_for_showing_before_redraw,
&data,
NULL);
g_main_loop_run (data.loop);
if (data.shown_handler_id)
g_signal_handler_disconnect (window, data.shown_handler_id);
g_main_loop_unref (data.loop);
}
gboolean
test_client_alarm_filter (MetaX11Display *x11_display,
XSyncAlarmNotifyEvent *event,

View File

@ -70,6 +70,9 @@ MetaWindow * test_client_find_window (TestClient *client,
const char *window_id,
GError **error);
void test_client_wait_for_window_shown (TestClient *client,
MetaWindow *window);
gboolean test_client_quit (TestClient *client,
GError **error);

View File

@ -38,6 +38,8 @@ struct _MetaWaylandActorSurfacePrivate
MetaSurfaceActor *actor;
gulong actor_destroyed_handler_id;
struct wl_list frame_callback_list;
};
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaWaylandActorSurface,
@ -78,6 +80,7 @@ meta_wayland_actor_surface_dispose (GObject *object)
MetaWaylandActorSurface *actor_surface = META_WAYLAND_ACTOR_SURFACE (object);
MetaWaylandActorSurfacePrivate *priv =
meta_wayland_actor_surface_get_instance_private (actor_surface);
MetaWaylandFrameCallback *cb, *next;
if (priv->actor)
{
@ -85,6 +88,9 @@ meta_wayland_actor_surface_dispose (GObject *object)
clear_surface_actor (actor_surface);
}
wl_list_for_each_safe (cb, next, &priv->frame_callback_list, link)
wl_resource_destroy (cb->resource);
G_OBJECT_CLASS (meta_wayland_actor_surface_parent_class)->dispose (object);
}
@ -113,6 +119,9 @@ meta_wayland_actor_surface_queue_frame_callbacks (MetaWaylandActorSurface *actor
if (!priv->actor)
return;
meta_surface_actor_wayland_add_frame_callbacks (surface_actor_wayland,
&priv->frame_callback_list);
wl_list_init (&priv->frame_callback_list);
meta_surface_actor_wayland_add_frame_callbacks (surface_actor_wayland,
&pending->frame_callback_list);
wl_list_init (&pending->frame_callback_list);
@ -239,7 +248,12 @@ meta_wayland_actor_surface_commit (MetaWaylandSurfaceRole *surface_role,
meta_wayland_actor_surface_get_instance_private (actor_surface);
if (!priv->actor)
return;
{
wl_list_insert_list (&priv->frame_callback_list,
&pending->frame_callback_list);
wl_list_init (&pending->frame_callback_list);
return;
}
if (!wl_list_empty (&pending->frame_callback_list) &&
cairo_region_is_empty (pending->surface_damage) &&
@ -292,8 +306,12 @@ meta_wayland_actor_surface_is_on_logical_monitor (MetaWaylandSurfaceRole *surfac
}
static void
meta_wayland_actor_surface_init (MetaWaylandActorSurface *role)
meta_wayland_actor_surface_init (MetaWaylandActorSurface *actor_surface)
{
MetaWaylandActorSurfacePrivate *priv =
meta_wayland_actor_surface_get_instance_private (actor_surface);
wl_list_init (&priv->frame_callback_list);
}
static void

View File

@ -571,12 +571,7 @@ destroy_data_offer (struct wl_resource *resource)
WL_DATA_OFFER_ACTION_SINCE_VERSION)
meta_wayland_data_source_notify_finish (offer->source);
else
{
if (seat->data_device.dnd_data_source == offer->source)
unset_selection_source (&seat->data_device, META_SELECTION_DND);
meta_wayland_data_source_cancel (offer->source);
meta_wayland_data_source_set_current_offer (offer->source, NULL);
}
meta_wayland_data_source_set_current_offer (offer->source, NULL);
}
g_object_remove_weak_pointer (G_OBJECT (offer->source),
@ -1036,6 +1031,7 @@ drag_grab_button (MetaWaylandPointerGrab *grab,
gboolean success;
if (drag_grab->drag_focus && source &&
meta_wayland_data_source_get_current_offer (source) &&
meta_wayland_data_source_has_target (source) &&
meta_wayland_data_source_get_current_action (source))
{
@ -1059,7 +1055,6 @@ drag_grab_button (MetaWaylandPointerGrab *grab,
}
else
{
meta_wayland_data_source_cancel (source);
meta_wayland_data_source_set_current_offer (source, NULL);
meta_wayland_data_device_set_dnd_source (&seat->data_device, NULL);
unset_selection_source (&seat->data_device, META_SELECTION_DND);
@ -1134,8 +1129,6 @@ drag_grab_data_source_destroyed (gpointer data, GObject *where_the_object_was)
MetaWaylandDragGrab *drag_grab = data;
drag_grab->drag_data_source = NULL;
meta_wayland_data_device_set_dnd_source (&drag_grab->seat->data_device, NULL);
unset_selection_source (&drag_grab->seat->data_device, META_SELECTION_DND);
data_device_end_drag_grab (drag_grab);
}
@ -1318,7 +1311,6 @@ selection_data_source_destroyed (gpointer data, GObject *object_was_here)
wl_data_device_send_selection (data_device_resource, NULL);
}
wl_signal_emit (&data_device->selection_ownership_signal, NULL);
unset_selection_source (data_device, META_SELECTION_CLIPBOARD);
}
@ -1598,6 +1590,16 @@ meta_wayland_data_device_get_drag_dest_funcs (void)
return &meta_wayland_drag_dest_funcs;
}
static void
dnd_data_source_destroyed (gpointer data,
GObject *object_was_here)
{
MetaWaylandDataDevice *data_device = data;
data_device->dnd_data_source = NULL;
unset_selection_source (data_device, META_SELECTION_DND);
}
void
meta_wayland_data_device_set_dnd_source (MetaWaylandDataDevice *data_device,
MetaWaylandDataSource *source)
@ -1606,16 +1608,20 @@ meta_wayland_data_device_set_dnd_source (MetaWaylandDataDevice *data_device,
return;
if (data_device->dnd_data_source)
g_object_remove_weak_pointer (G_OBJECT (data_device->dnd_data_source),
(gpointer *)&data_device->dnd_data_source);
{
g_object_weak_unref (G_OBJECT (data_device->dnd_data_source),
dnd_data_source_destroyed,
data_device);
}
data_device->dnd_data_source = source;
if (source)
g_object_add_weak_pointer (G_OBJECT (data_device->dnd_data_source),
(gpointer *)&data_device->dnd_data_source);
wl_signal_emit (&data_device->dnd_ownership_signal, source);
{
g_object_weak_ref (G_OBJECT (source),
dnd_data_source_destroyed,
data_device);
}
}
void
@ -1673,8 +1679,6 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
wl_data_device_send_selection (data_device_resource, offer);
}
}
wl_signal_emit (&data_device->selection_ownership_signal, source);
}
static void
@ -1735,7 +1739,6 @@ primary_source_destroyed (gpointer data,
gtk_primary_selection_device_send_selection (data_device_resource, NULL);
}
wl_signal_emit (&data_device->primary_ownership_signal, NULL);
unset_selection_source (data_device, META_SELECTION_PRIMARY);
}
@ -1804,8 +1807,6 @@ meta_wayland_data_device_set_primary (MetaWaylandDataDevice *data_device,
gtk_primary_selection_device_send_selection (data_device_resource, offer);
}
}
wl_signal_emit (&data_device->primary_ownership_signal, source);
}
static void
@ -2022,9 +2023,6 @@ meta_wayland_data_device_init (MetaWaylandDataDevice *data_device)
{
wl_list_init (&data_device->resource_list);
wl_list_init (&data_device->primary_resource_list);
wl_signal_init (&data_device->selection_ownership_signal);
wl_signal_init (&data_device->primary_ownership_signal);
wl_signal_init (&data_device->dnd_ownership_signal);
}
static struct wl_resource *

View File

@ -67,10 +67,6 @@ struct _MetaWaylandDataDevice
MetaWaylandDragGrab *current_grab;
struct wl_client *focus_client;
struct wl_signal selection_ownership_signal;
struct wl_signal dnd_ownership_signal;
struct wl_signal primary_ownership_signal;
guint selection_owner_signal_id;
MetaSelectionSource *owners[META_N_SELECTION_TYPES];

View File

@ -228,7 +228,8 @@ sync_focus_surface (MetaWaylandPointer *pointer)
MetaBackend *backend = meta_get_backend ();
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
if (!meta_cursor_tracker_get_pointer_visible (cursor_tracker))
if (!meta_cursor_tracker_get_pointer_visible (cursor_tracker) &&
!meta_cursor_tracker_get_keep_focus_while_hidden (cursor_tracker))
{
meta_wayland_pointer_set_focus (pointer, NULL);
return;
@ -433,7 +434,8 @@ default_grab_focus (MetaWaylandPointerGrab *grab,
if (!meta_wayland_seat_has_pointer (seat))
return;
if (!meta_cursor_tracker_get_pointer_visible (cursor_tracker))
if (!meta_cursor_tracker_get_pointer_visible (cursor_tracker) &&
!meta_cursor_tracker_get_keep_focus_while_hidden (cursor_tracker))
return;
if (pointer->button_count > 0)
@ -898,7 +900,8 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
g_return_if_fail (meta_cursor_tracker_get_pointer_visible (cursor_tracker) ||
surface == NULL);
meta_cursor_tracker_get_keep_focus_while_hidden (cursor_tracker) ||
surface == NULL);
if (pointer->focus_surface == surface)
return;

View File

@ -504,9 +504,17 @@ gboolean
meta_wayland_seat_can_popup (MetaWaylandSeat *seat,
uint32_t serial)
{
MetaWaylandCompositor *compositor;
MetaWaylandTabletSeat *tablet_seat;
compositor = meta_wayland_compositor_get_default ();
tablet_seat =
meta_wayland_tablet_manager_ensure_seat (compositor->tablet_manager, seat);
return (meta_wayland_pointer_can_popup (seat->pointer, serial) ||
meta_wayland_keyboard_can_popup (seat->keyboard, serial) ||
meta_wayland_touch_can_popup (seat->touch, serial));
meta_wayland_touch_can_popup (seat->touch, serial) ||
meta_wayland_tablet_seat_can_popup (tablet_seat, serial));
}
gboolean

View File

@ -401,7 +401,7 @@ static void
pending_buffer_resource_destroyed (MetaWaylandBuffer *buffer,
MetaWaylandPendingState *pending)
{
g_signal_handler_disconnect (buffer, pending->buffer_destroy_handler_id);
g_clear_signal_handler (&pending->buffer_destroy_handler_id, buffer);
pending->buffer = NULL;
}
@ -1647,8 +1647,8 @@ meta_wayland_surface_get_absolute_coordinates (MetaWaylandSurface *surface,
ClutterActor *actor =
CLUTTER_ACTOR (meta_wayland_surface_get_actor (surface));
ClutterVertex sv = {
.x = sx * surface->scale,
.y = sy * surface->scale,
.x = sx,
.y = sy,
};
ClutterVertex v = { 0 };

View File

@ -552,3 +552,20 @@ meta_wayland_tablet_seat_set_pad_focus (MetaWaylandTabletSeat *tablet_seat,
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &pad))
meta_wayland_tablet_pad_set_focus (pad, surface);
}
gboolean
meta_wayland_tablet_seat_can_popup (MetaWaylandTabletSeat *tablet_seat,
uint32_t serial)
{
MetaWaylandTabletTool *tool;
GHashTableIter iter;
g_hash_table_iter_init (&iter, tablet_seat->tools);
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &tool))
{
if (meta_wayland_tablet_tool_can_popup (tool, serial))
return TRUE;
}
return FALSE;
}

View File

@ -75,5 +75,7 @@ MetaWaylandTablet *meta_wayland_tablet_seat_lookup_paired_tablet (MetaWaylan
MetaWaylandTabletPad *pad);
GList *meta_wayland_tablet_seat_lookup_paired_pads (MetaWaylandTabletSeat *tablet_seat,
MetaWaylandTablet *tablet);
gboolean meta_wayland_tablet_seat_can_popup (MetaWaylandTabletSeat *tablet_seat,
uint32_t serial);
#endif /* META_WAYLAND_TABLET_SEAT_H */

View File

@ -1018,3 +1018,10 @@ meta_wayland_tablet_tool_can_grab_surface (MetaWaylandTabletTool *tool,
return ((tool->down_serial == serial || tool->button_serial == serial) &&
tablet_tool_can_grab_surface (tool, surface));
}
gboolean
meta_wayland_tablet_tool_can_popup (MetaWaylandTabletTool *tool,
uint32_t serial)
{
return tool->down_serial == serial || tool->button_serial == serial;
}

View File

@ -85,5 +85,7 @@ void meta_wayland_tablet_tool_set_cursor_position (MetaWaylandTabletTool *t
gboolean meta_wayland_tablet_tool_can_grab_surface (MetaWaylandTabletTool *tool,
MetaWaylandSurface *surface,
uint32_t serial);
gboolean meta_wayland_tablet_tool_can_popup (MetaWaylandTabletTool *tool,
uint32_t serial);
#endif /* META_WAYLAND_TABLET_TOOL_H */

View File

@ -1928,10 +1928,15 @@ meta_x11_display_set_input_focus_xwindow (MetaX11Display *x11_display,
{
gulong serial;
meta_display_unset_input_focus (x11_display->display, timestamp);
if (meta_display_timestamp_too_old (x11_display->display, &timestamp))
return;
serial = XNextRequest (x11_display->xdisplay);
meta_x11_display_set_input_focus_internal (x11_display, window, timestamp);
meta_x11_display_update_focus_window (x11_display, window, serial, TRUE);
meta_display_update_focus_window (x11_display->display, NULL);
meta_display_remove_autoraise_callback (x11_display->display);
x11_display->display->last_focus_time = timestamp;
}
static MetaX11DisplayLogicalMonitorData *

View File

@ -1625,6 +1625,22 @@ reload_wm_hints (MetaWindow *window,
meta_window_queue (window, META_QUEUE_UPDATE_ICON | META_QUEUE_MOVE_RESIZE);
}
static gboolean
check_xtransient_for_loop (MetaWindow *window,
MetaWindow *parent)
{
while (parent)
{
if (parent == window)
return TRUE;
parent = meta_x11_display_lookup_x_window (parent->display->x11_display,
parent->xtransient_for);
}
return FALSE;
}
static void
reload_transient_for (MetaWindow *window,
MetaPropValue *value,
@ -1645,20 +1661,22 @@ reload_transient_for (MetaWindow *window,
transient_for, window->desc);
transient_for = None;
}
else if (parent->override_redirect)
{
meta_warning ("WM_TRANSIENT_FOR window %s for top-level %s is an "
"override-redirect window and this is not correct "
"according to the standard, so we'll fallback to "
"the root window.\n", parent->desc, window->desc);
transient_for = parent->display->x11_display->xroot;
parent = NULL;
}
/* Make sure there is not a loop */
while (parent)
if (check_xtransient_for_loop (window, parent))
{
if (parent == window)
{
meta_warning ("WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n",
transient_for, window->desc);
transient_for = None;
break;
}
parent = meta_x11_display_lookup_x_window (parent->display->x11_display,
parent->xtransient_for);
meta_warning ("WM_TRANSIENT_FOR window 0x%lx for %s would create a "
"loop.\n", transient_for, window->desc);
transient_for = None;
}
}
else
@ -1679,8 +1697,6 @@ reload_transient_for (MetaWindow *window,
meta_window_set_transient_for (window, NULL);
else
{
parent = meta_x11_display_lookup_x_window (window->display->x11_display,
window->xtransient_for);
meta_window_set_transient_for (window, parent);
}
}