Compare commits

...

50 Commits
main ... 3.28.2

Author SHA1 Message Date
41303bc01b Bump version to 3.28.2
Update NEWS.
2018-05-07 22:29:42 +02:00
0d188c3898 build: Adjust to filename changes
The meta-stage and meta-window-group headers got split into a public
and private part, but the Makefiles still reference the old files.
2018-05-07 22:29:42 +02:00
28eff93143 build: Introspect some more types
While MetaStage, MetaWindowGroup and MetaDBusDisplayConfigSkeleton don't
appear explicitly in the public API, their gtypes are still exposed via
meta_get_stage_for_screen(), meta_get_*window_group_for_screen() and
MetaMonitorManager's parent type. Newer versions of gjs will warn about
undefined properties if it encounters a gtype without introspection
information, so expose those types to shut up the warnings.

https://bugzilla.gnome.org/show_bug.cgi?id=781471
2018-05-07 22:06:02 +02:00
b380aa72aa window-group: Remove undefined function declaration
Ever since the function has been made public, its name has been
meta_actor_is_untransformed() ...

https://bugzilla.gnome.org/show_bug.cgi?id=781471
2018-05-07 22:06:02 +02:00
920dc9e5a1 clutter: Don't reference invalid pc in gir
Cally is built into clutter itself rather than exposed as a separate
library.

https://bugzilla.gnome.org/show_bug.cgi?id=781471
2018-05-07 22:06:02 +02:00
32f02010ae screen-cast: Handle PipeWire errors more gracefully
Various code assumed PipeWire function calls would never fail. Some can
actually fail for real reasons, and some currently can only fail due to
OOM situations, but we should still not assume that will always be the
case.

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


(cherry picked from commit 0f9c6aef99)
2018-05-07 19:28:27 +00:00
889c56c776 wayland/xdg-foreign: Fix child surface validation check
The role type should be either an xdg-shell toplevel, or a
xdg-shell unstable v6 toplevel.

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


(cherry picked from commit 332d55f7f6)
2018-05-07 19:20:56 +00:00
67a4cd898e wayland/xdg-foreign: Send immediate destroy event to correct resource
The destroyed signal that was emitted if an imported surface was not
available when created, for example if the handle was invalid or
already unexported, was emitted on the wrong resource.


(cherry picked from commit 98d7024288)
2018-05-07 19:20:09 +00:00
43d6c0ea61 build: Don't fail immediately when logind is missing
We require logind for the native backend, but the backend itself is
optional. However since commit 06c357d78, we will always throw an
error if neither logind nor elogind are available, even when the
backend is disabled.

As we still support "auto" - that is, whether the native backend is
enabled depends on whether its dependencies are available - the
easiest option is to make sure we always include either elogind or
libsystemd in the dependency check rather than erring out explicitly
if neither is found.

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


(cherry picked from commit 82564772dc)
2018-05-07 19:14:11 +00:00
2872bb1f2a wayland: Check if state and size changed before calling move_resize()
The current implementation of the XdgSurface v6 protocol does not check
if the window changed before calling meta_window_wayland_move_resize().

The problem with this approach is that calling this function is a costly
operation since we enter the compositor side. In GNOME Shell case, it is
in JavaScript, which triggers a GJS trampoline. Calling this function on
every mouse movement is naturally as terrible as it could be - and is
exactly what happens now.

This commit adds the necessary checks to only call move_resize() when
the window actually changed, or when it needs to be updated.

https://bugzilla.gnome.org/show_bug.cgi?id=780292
Issue: #78
2018-05-04 15:57:57 -03:00
1c00cd5ca3 wayland: Add function to query if window needs move or resize
This will be used by the next commit to determine when a window
geometry change should be ignored or not. Normally, it would be
enough to just check if the position and sizes changed.

The position, in this case, is relative to the client buffer, not
the global position. But because it is not global, there is one,
admitedly unlikely, situation where the window state is updated
while the client size and relative positions don't change.

One can trigger this by e.g. tiling the window to the half-left of
the monitor, then immediately tile it to half-right. In this case,
the window didn't change, just it's state, but nonetheless we need
to notify the compositor and run the full move/resize routines.

When that case happens, though, the MetaWindowWayland is tracking
the pending state change or a move. And this is what we need to
expose.

https://bugzilla.gnome.org/show_bug.cgi?id=780292
Issue: #78
2018-05-04 15:57:50 -03:00
2919a7f25f window: Let implementations finish state changes
In the old, synchronous X.org world, we could assume that
a state change always meant a synchronizing the window
geometry right after. After firing an operation that
would change the window state, such as maximizing or
tiling the window,

With Wayland, however, this is not valid anymore, since
Wayland is asynchronous. In this scenario, we call
meta_window_move_resize_internal() twice: when the user
executes an state-changing operation, and when the server
ACKs this operation. This breaks the previous assumptions,
and as a consequence, it breaks the GNOME Shell animations
in Wayland.

The solution is giving the MetaWindow control over the time
when the window geometry is synchronized with the compositor.
That is done by introducing a new result flag. Wayland asks
for a compositor sync after receiving an ACK from the server,
while X11 asks for it right away.

Fixes #78
2018-05-04 15:57:43 -03:00
ca0d56a3a4 wayland: avoid a crash in is_effectively_synchronized()
To check if a subsurface is effectively synchronized, we walk the
subsurface hierarchy to look for a non-subsurface parent or a subsurface
being synchronized.

However, when client is closing, the parent surface might already be
gone, in which case we end up with a surface being NULL which causes a
NULL pointer dereference and a crash.

Check if the parent surface is NULL to avoid the crash, and consider
it's already synchronized if it is NULL to avoid further updates.

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


(cherry picked from commit 52fdd24467)
2018-05-03 17:49:26 +00:00
a89baa44ab native: Restore previous EGL state after blitting onto secondary GPU
Before we just set it to "none", but this was not enough since various
calls will depend on not just the context being active, but the main
rendering surface.

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


(cherry picked from commit ae26cd0774)
2018-04-25 15:24:14 +00:00
7076a48bcf cogl: Do not unref a NULL object
Add return-if-fail statement to avoid deferencing NULL object


(cherry picked from commit 3104d697c0)
2018-04-25 09:09:04 +00:00
1b439c42d1 monitor-manager: Find active monitor when deriving global scale
When deriving the global scale directly from the current hardware state
(as done when using the X11 backend) we are inspecting the logical
state they had prior to the most recent hot plug. That means that a
primary monitor might have been disabled, and a new primary monitor may
not have been assigned yet.

Stop assuming a primary monitor has an active mode before having
reconstructed the logical state by finding some active monitor if the
old primary monitor was disabled. This avoids a crash when trying to
derive the global scale from a disabled monitor.

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


(cherry picked from commit 0b3a1c9c31)
2018-04-25 08:58:15 +00:00
928a40f328 wayland: Let IM events go through
These paths implicitly relied on the forwarded IM key events having
a source_device backed by a real HW device. This assumption is no
longer held true since commit b5328c977.

Explicitly check the INPUT_METHOD flag so they are handled as they
should despite not being "real HW" events.
2018-04-24 23:59:21 +02:00
59397266ed backend: Don't center the pointers on monitor changes
As a follow up to the patch from a95cbd0a, we need to make sure
that the pointer is out of the way as well when monitors changed,
since that's the event that will prevail in some cases. Besides,
this is also consistent with what the code before a95cbd0a was,
which initialized the pointer position in the same way both in
this case and in the real_post_init() function.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/157
2018-04-24 23:14:38 +02:00
d0147591b3 backends: Don't center the pointer on initialization
Centering the pointer at startup causes undesired behaviour if
it ends up hovering over reactive elements, that might react
to that positioning, causing confusion. This is the case of
the login dialog when a list of different users is shown, as
centering the pointer at startup in that case will get the
user in the center of the screen pre-selected, which is not
the expected behaviour (i.e. pre-selecting the first one).

Fix this by simply moving the pointer out of the way, close
to the bottom-right corner, during initialization.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/157
2018-04-24 23:14:37 +02:00
25c7e52ada xwayland: Don't abort if Xwayland crashes
Right now if Xwayland crashes, we crash, too.

On some level that makes sense, since we're supposed to control the
lifecycle of Xwayland, and by it crashing we've lost that control.

But practically speaking, the knock-on crash adds noise to the logs,
bug trackers, and retrace servers that only makes debugging harder.
And the crash isn't something mutter can "fix", since it's
ultimately from a bug in Xwayland anyway.

This commit makes mutter exit instead of crash if Xwayland goes away
unexpectedly.


(cherry picked from commit 2d80fd02e7)
2018-04-24 05:08:22 +00:00
99d766c044 xwayland: use g_autoptr for GError in xserver_died
Right now we explicitly g_clear_error any error we find, but that
makes it tricky to return early from the function, which a
subsequent commit will want to to do.

This commit switches GError to use g_autoptr so the error clearing
happens automatically.


(cherry picked from commit bb65854065)
2018-04-24 05:07:41 +00:00
fcd4c816c4 theme, frames: Use surface device scale instead of cairo_scale
Gtk now is caching the themed cairo surfaces, then as per
commit gtk@e36b629c the surface device scale is used to figure
out the current paint scaling.

Without this when using background-image's for window buttons
the -gtk-scaled icons isn't properly resized.

Fixes #99


(cherry picked from commit 4339b23dd0)
2018-04-22 20:45:29 +00:00
2a63a47d5a wayland: Do not reset frame list when merging pending state
In the synchronized subsurface case, the destination list may
contain other elements from previous wl_surface.commit calls.
Resetting the list will leave those dangling frame callbacks
that will lead to invalid writes when those get to be destroyed
(eg. on client shutdown).
2018-04-22 12:14:37 +02:00
c80e2c9ae5 clutter: Set slave=master in IM forwarded key events
The fix is twofold. On one hand, it makes sense not to relate IM (nor
any other) generated events to a HW device. On the other hand, if we
are unfortunate that an IM event is in flight when we are switching
to another TTY, it may arrive at a time when the source device is no
longer existent.
2018-04-22 12:14:37 +02:00
d3d5eb8e1b idle-monitor: Add ResetIdletime API, for testing purposes
The ResetIdletime API can be used instead of an "XTest" binary to
programmatically reset the idle time, as if the user pressed a button on
a keyboard.

This is necessary since we stopped using the XSync extension to monitor
idletimes, as it didn't consider inhibitors as busy, and mutter's
clutter code ignores "Core Events" as generated by XTest.

This patch will require minimal changes to gnome-settings-daemon's power
test suite so that "key press" idletime resets are triggered through
this D-Bus interface rather than through XTest and a roundtrip through
the X server.

https://bugzilla.gnome.org/show_bug.cgi?id=705942
2018-04-16 16:03:56 +02:00
4837cec89f backend: Reset idle when lid is opened or resuming from suspend
There's no particular reason for this code to only ever be triggered on
Wayland, and allows removing X11-specific work-arounds from
gnome-settings-daemon.

See https://bugs.freedesktop.org/show_bug.cgi?id=59576

https://bugzilla.gnome.org/show_bug.cgi?id=705942
2018-04-16 16:03:56 +02:00
32329e6c00 idle-monitor: Take idle inhibition into account
Take idle inhibitions into account for when to fire idle watches as
requested by OS components.

This should stop gnome-session and gnome-settings-daemon considering
the session idle when they have been inhibited for longer than their
timeout, for example to avoid the screensaver activating, or the
computer suspending after watching a film.

https://bugzilla.gnome.org/show_bug.cgi?id=705942
2018-04-16 16:03:56 +02:00
89261be556 x11: Allow XTest and core events to reset idletime
Now that we've removed the X11 specific backend of the idle monitor,
add back a cut-down version of it for the explicit purpose of being
told about idle time resets when XTest events are used.

XTest events are usually used by test suites and remote display software
to inject events into an X11 session. We should consider somebody moving
the mouse remotely to be just as "active" as somebody moving it locally.

https://bugzilla.gnome.org/show_bug.cgi?id=705942
2018-04-16 16:03:56 +02:00
e3e76d658b backends: Remove X11 idle-monitor backend
And use the old "native" backend for both X11 and Wayland. This will
allow us to share fixes between implementations without having to delve
into the XSync X11 extension code.

https://bugzilla.gnome.org/show_bug.cgi?id=705942
2018-04-16 16:03:56 +02:00
34644b2133 Bump version to 3.28.1
Update NEWS.
2018-04-13 19:11:57 +02:00
7da4e8cf14 wayland: Plug surface pending state contents leak
When moving the pending state of an effectively synchronized subsurface
so it is applied together with the parent, perform a merge of the source
MetaWaylandPendingState into the destination one, instead of simply
overwriting the struct.

The other approach had 2 kind of leaks, one that would happen everytime
a wl_surface.commit happens on a sync subsurface (both surface/buffer
damage regions are leaked). The other more unlikely one would apply on
the rest of pending state data, happening whenever the compositor gets
>1 wl_surface.commit calls on the subsurface before the parent surface
gets its own.

The function has also been renamed to use the more descriptive "merge"
term.

Related: gnome-shell#64
2018-04-13 00:10:03 +02:00
23c3f8bb18 monitor-manager: fix output ids returned by GetResources
Output ID is set equal to 'i' later in the loop. But 'i' was never
incremented, so all outputs were getting the same ID (equal to
the number of CRTCs, because 'i' was reused from the previous loop).
2018-04-11 17:55:41 +00:00
60866e0f85 native: Disable the use of KMS modifiers by default
Make it re-enable:able by a hidden "experimental feature". To enable,
add "kms-modifiers" to the org.gnome.mutter.experimental-features
GSettings entry.

https://gitlab.gnome.org/GNOME/mutter/issues/81
2018-04-11 16:34:59 +02:00
45c02645f3 Updated Slovenian translation 2018-04-10 17:58:12 +02:00
e515e37a7e screen-cast: Fix compile error
Credit goes to gcc for finding this typo.


(cherry picked from commit 98dfd5b887)
2018-04-10 12:10:19 +00:00
957f4ec69d theme: Scale titlebar spacing when computing x
The value is not scaled by default so it needs to be adjusted
depending on the window scaling, as it's done in other places.

Fixes: #87


(cherry picked from commit deda7a5235)
2018-04-03 20:42:28 +00:00
a98eb107be theme: add ".appmenu" class to the appmenu button
So it does gtk headerbar, so mutter should do.


(cherry picked from commit 96141e28f9)
2018-04-03 20:22:52 +00:00
1851fa2bd0 renderer-native: Fall back to non-modifier GBM surfaces
If we attempt GBM surface allocation with a set of modifiers but the
allocation fails, fall back to non-modifier allocations. This fixes
startup on Pineview-based Atom systems, where KMS provides us a set of
modifiers but the GBM implementation doesn't support modifier use.

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


(cherry picked from commit e6109cfc22)
2018-04-03 18:18:31 +00:00
de7d7bbf3d clutter: Apply input hints/purpose on ClutterTextInputFocus focus in
And make the ClutterText-level properties independent from the input
focus, as those properties can be set anytime, not just when the
ClutterText actor is focused.

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

Closes: #66


(cherry picked from commit 3684f6b0ac)
2018-04-03 15:00:01 +00:00
7ac551cd05 input-settings: Fix a typo in tap-and-drag setting
(cherry picked from commit 31b5059068)
2018-03-29 14:54:00 +00:00
8696a79477 cursor-renderer-native: take rotation into account
Rotating an output would show duplicate cursors when the pointer is
located over an area which would be within the output if not rotated.

Make sure to swap the width/height of the output when rotated.

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


(cherry picked from commit ebff7fd7f4)
2018-03-29 06:49:14 +00:00
b2f9de98d0 renderer-native: Swap then await earlier flips.
Rendering the next frame (which mostly happens as part of the flush done
in swap buffers) is a task that the GPU can complete independently of
the CPU having to wait for previous page flips. So reverse their order
to get the GPU started earlier, with the aim of greater GPU-CPU
parallelism.


(cherry picked from commit 6e415353e3)
2018-03-29 05:41:02 +00:00
2da2489da5 window: Fix a small memory leak
(cherry picked from commit 63e2c0329f)
2018-03-29 05:24:08 +00:00
31779404f0 clutter: Avoid unnecessary relayouts in ClutterText
We can save an unnecessary relayout if the required size to fully draw the text
is equal to the currently allocated size after the underlying text buffer or
attributes that only affect the PangoLayout have changed.
2018-03-22 23:35:27 +01:00
b096c0ac33 mutter: allow building with elogind
This commit allows building mutter with elogind, which is
systemd-logind extracted into a standalone package. This
allows using mutter with its native-backend ( and consequently
wayland ) enabled on distros which use init systems other than
systemd.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/46
2018-03-21 23:07:46 +01:00
44a7f74dcd cogl: Read pixels as per the stored format
By the looks of it, commit 95e9fa10ef was taping over an Intel DRI bug
that would make it return post-swizzling pixel data on glReadPixels().
There's been reports over time of that commit resulting in wrong colors
on other drivers, and lately Mesa >17.3 started showing the same symptoms
on Intel.

But texture swizzling works by changing parameters before fragment shaders
and reading pixels from an already drawn FBO/texture doesn't involve those.
This should thus use pixel_format_to_gl_with_target(), which will result in
correctly requesting the same pixel format than the underlying texture,
while still considering it BGRA for the upper layers in the swizzling case.

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

Closes: #72
2018-03-21 20:37:34 +01:00
3832c6b607 gpu-kms: Ignore GPUs with no connectors
Mutter recently gained the ability to deal with multiple GPUs
rendering at different displays. These GPUs would have a display
connected to them, and Mutter was adapted in order to be aware
of different GPUs and their outputs.

However, one specific edge case appeared: PRIME systems. PRIME
systems have two GPUs:

 * The integrated GPU (iGPU), usually Intel, which has connectors
   and deals with the routine load.

 * The dedicated GPU (dGPU), usually AMD or NVidia, which has no
   connectors at all and are there just to aid heavy loads.

On those systems, the dGPU is aggressively put to sleep by the
kernel to avoid energy waste. Waking it up is a costly operation.

With Mutter's adaptation to deal with multiple GPUs, Mutter began
wakening the dGPU every time some rendering had to be done. This
was causing stuttering every time the dGPU was put to sleep, and
Mutter asked it to wake up again.

To fix this situation, this commit ignores GPUs with no connectors
attached.

Issue: #77
2018-03-21 18:50:14 +00:00
14b7e79d3c gpu-kms: Return NULL, not FALSE
Another small mistake spotted while working on #77. This
function returns a pointer, thus we should return NULL,
not FALSE.

Issue: #77
2018-03-21 18:50:13 +00:00
e99b0b9368 monitor-manager-kms: Don't add GPU if it fails
This is a small mistake spotted while working on a solution
for #77. When a GPU fails to initialize, we're adding them
anyway, which might have pretty bad consequences when trying
to use these NULL GPUs.

Issue: #77
2018-03-21 18:50:13 +00:00
de294f34bb monitor-manager-kms: Use g_autoptr for error
A minor code cleanup.
2018-03-21 18:50:13 +00:00
62 changed files with 1048 additions and 1040 deletions

32
NEWS
View File

@ -1,3 +1,35 @@
3.28.2
======
* Take inhibitors into account for monitoring idle [Bastien; #705942]
* Fix window animations on wayland [Georges; #780292]
* Misc. bug fixes [Mario, Jonas, Olivier, Florian; gnome-shell#157, #130,
#21, #124, !96, #138, !102, #781471]
Contributors:
Jonas Ådahl, Olivier Fourdan, Carlos Garnacho, Florian Müllner,
Georges Basile Stavracas Neto, Bastien Nocera, Mario Sanchez Prada,
Ray Strode, Marco Trevisan (Treviño)
3.28.1
======
* Fix various input-method regressions [Carlos; #65, #74, #66]
* Fix wayland build on FreeBSD [Ting-Wei; #792280, #792717]
* Fix swapped colors in screenshots (again) [Carlos; #72]
* Allow building with elogind [Rasmus; !46]
* Consider display rotation for cursor [Olivier; #85]
* Fall back to non-modifier GBM surfaces [Daniel; #84]
* Disable KMS modifiers by default [Jonas; #81]
* Misc bug fixes [handsome-feng; !45]
Contributors:
Jonas Ådahl, Olivier Fourdan, Carlos Garnacho, handsome-feng, Yussuf Khalil,
Ting-Wei Lan, Aleksandr Mezin, Alberts Muktupāvels,
Georges Basile Stavracas Neto, Benjamin Otte, Daniel Stone, Rasmus Thomsen,
Marco Trevisan (Treviño), Daniel van Vugt
Translators:
Emin Tufan Çetin [tr], Dušan Kazik [sk], Matej Urbančič [sl]
3.28.0
======
* Fix xdg-foreign regression [Carlos; #63]

View File

@ -692,7 +692,7 @@ Cally_@LIBMUTTER_API_VERSION@_gir_CFLAGS = $(AM_CPPFLAGS) $(CLUTTER_CFLAGS)
Cally_@LIBMUTTER_API_VERSION@_gir_SCANNERFLAGS = \
--warn-all \
--c-include='cally/cally.h' \
--pkg-export=mutter-cally-@LIBMUTTER_API_VERSION@ \
--pkg-export=mutter-clutter-@LIBMUTTER_API_VERSION@ \
--include-uninstalled=$(top_builddir)/clutter/Clutter-@LIBMUTTER_API_VERSION@.gir
INTROSPECTION_GIRS += Cally-@LIBMUTTER_API_VERSION@.gir

View File

@ -353,6 +353,7 @@ clutter_input_method_notify_key_event (ClutterInputMethod *im,
copy = clutter_event_copy (event);
clutter_event_set_flags (copy, clutter_event_get_flags (event) |
CLUTTER_EVENT_FLAG_INPUT_METHOD);
clutter_event_set_source_device (copy, clutter_event_get_device (copy));
clutter_event_put (copy);
clutter_event_free (copy);
}

View File

@ -2830,6 +2830,10 @@ clutter_text_key_focus_in (ClutterActor *actor)
if (method && priv->editable)
{
clutter_input_method_focus_in (method, priv->input_focus);
clutter_input_focus_set_content_purpose (priv->input_focus,
priv->input_purpose);
clutter_input_focus_set_content_hints (priv->input_focus,
priv->input_hints);
update_cursor_location (CLUTTER_TEXT (actor));
}
@ -4511,6 +4515,27 @@ buffer_deleted_text (ClutterTextBuffer *buffer,
}
}
static void
clutter_text_queue_redraw_or_relayout (ClutterText *self)
{
ClutterActor *actor = CLUTTER_ACTOR (self);
gfloat preferred_width;
gfloat preferred_height;
clutter_text_dirty_cache (self);
/* we're using our private implementations here to avoid the caching done by ClutterActor */
clutter_text_get_preferred_width (actor, -1, NULL, &preferred_width);
clutter_text_get_preferred_height (actor, preferred_width, NULL, &preferred_height);
if (clutter_actor_has_allocation (actor) &&
(fabsf (preferred_width - clutter_actor_get_width (actor)) > 0.001 ||
fabsf (preferred_height - clutter_actor_get_height (actor)) > 0.001))
clutter_actor_queue_relayout (actor);
else
clutter_text_queue_redraw (actor);
}
static void
buffer_notify_text (ClutterTextBuffer *buffer,
GParamSpec *spec,
@ -4518,9 +4543,7 @@ buffer_notify_text (ClutterTextBuffer *buffer,
{
g_object_freeze_notify (G_OBJECT (self));
clutter_text_dirty_cache (self);
clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
clutter_text_queue_redraw_or_relayout (self);
g_signal_emit (self, text_signals[TEXT_CHANGED], 0);
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_TEXT]);
@ -4872,8 +4895,7 @@ clutter_text_set_cursor_visible (ClutterText *self,
{
priv->cursor_visible = cursor_visible;
clutter_text_dirty_cache (self);
clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
clutter_text_queue_redraw_or_relayout (self);
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_CURSOR_VISIBLE]);
}
@ -5774,9 +5796,7 @@ clutter_text_set_line_alignment (ClutterText *self,
{
priv->alignment = alignment;
clutter_text_dirty_cache (self);
clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
clutter_text_queue_redraw_or_relayout (self);
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_LINE_ALIGNMENT]);
}
@ -5831,9 +5851,7 @@ clutter_text_set_use_markup (ClutterText *self,
if (setting)
clutter_text_set_markup_internal (self, text);
clutter_text_dirty_cache (self);
clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
clutter_text_queue_redraw_or_relayout (self);
}
/**
@ -5880,9 +5898,7 @@ clutter_text_set_justify (ClutterText *self,
{
priv->justify = justify;
clutter_text_dirty_cache (self);
clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
clutter_text_queue_redraw_or_relayout (self);
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_JUSTIFY]);
}
@ -6449,8 +6465,7 @@ clutter_text_set_preedit_string (ClutterText *self,
priv->preedit_set = TRUE;
}
clutter_text_dirty_cache (self);
clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
clutter_text_queue_redraw_or_relayout (self);
}
@ -6512,7 +6527,9 @@ clutter_text_set_input_hints (ClutterText *self,
g_return_if_fail (CLUTTER_IS_TEXT (self));
self->priv->input_hints = hints;
clutter_input_focus_set_content_hints (self->priv->input_focus, hints);
if (clutter_input_focus_is_focused (self->priv->input_focus))
clutter_input_focus_set_content_hints (self->priv->input_focus, hints);
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_INPUT_HINTS]);
}
@ -6531,7 +6548,9 @@ clutter_text_set_input_purpose (ClutterText *self,
g_return_if_fail (CLUTTER_IS_TEXT (self));
self->priv->input_purpose = purpose;
clutter_input_focus_set_content_purpose (self->priv->input_focus, purpose);
if (clutter_input_focus_is_focused (self->priv->input_focus))
clutter_input_focus_set_content_purpose (self->priv->input_focus, purpose);
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_INPUT_PURPOSE]);
}

View File

@ -452,7 +452,7 @@ libmutter_cogl_@LIBMUTTER_API_VERSION@_la_LDFLAGS = \
-avoid-version \
-export-dynamic \
-rpath $(mutterlibdir) \
-export-symbols-regex "^(cogl|_cogl_debug_flags|_cogl_atlas_new|_cogl_atlas_add_reorganize_callback|_cogl_atlas_reserve_space|_cogl_callback|_cogl_util_get_eye_planes_for_screen_poly|_cogl_atlas_texture_remove_reorganize_callback|_cogl_atlas_texture_add_reorganize_callback|_cogl_texture_get_format|_cogl_texture_foreach_sub_texture_in_region|_cogl_texture_set_region|_cogl_profile_trace_message|_cogl_context_get_default|_cogl_framebuffer_get_stencil_bits|_cogl_clip_stack_push_rectangle|_cogl_framebuffer_get_modelview_stack|_cogl_object_default_unref|_cogl_pipeline_foreach_layer_internal|_cogl_clip_stack_push_primitive|_cogl_buffer_unmap_for_fill_or_fallback|_cogl_framebuffer_draw_primitive|_cogl_debug_instances|_cogl_framebuffer_get_projection_stack|_cogl_pipeline_layer_get_texture|_cogl_buffer_map_for_fill_or_fallback|_cogl_texture_can_hardware_repeat|_cogl_pipeline_prune_to_n_layers|_cogl_primitive_draw|test_|unit_test_|_cogl_winsys_glx_get_vtable|_cogl_winsys_egl_xlib_get_vtable|_cogl_winsys_egl_get_vtable|_cogl_closure_disconnect|_cogl_onscreen_notify_complete|_cogl_onscreen_notify_frame_sync|_cogl_winsys_egl_renderer_connect_common|_cogl_winsys_error_quark|_cogl_set_error|_cogl_poll_renderer_add_fd|_cogl_poll_renderer_add_idle|_cogl_framebuffer_winsys_update_size|_cogl_winsys_egl_make_current|_cogl_pixel_format_get_bytes_per_pixel).*"
-export-symbols-regex "^(cogl|_cogl_debug_flags|_cogl_atlas_new|_cogl_atlas_add_reorganize_callback|_cogl_atlas_reserve_space|_cogl_callback|_cogl_util_get_eye_planes_for_screen_poly|_cogl_atlas_texture_remove_reorganize_callback|_cogl_atlas_texture_add_reorganize_callback|_cogl_texture_get_format|_cogl_texture_foreach_sub_texture_in_region|_cogl_texture_set_region|_cogl_profile_trace_message|_cogl_context_get_default|_cogl_framebuffer_get_stencil_bits|_cogl_clip_stack_push_rectangle|_cogl_framebuffer_get_modelview_stack|_cogl_object_default_unref|_cogl_pipeline_foreach_layer_internal|_cogl_clip_stack_push_primitive|_cogl_buffer_unmap_for_fill_or_fallback|_cogl_framebuffer_draw_primitive|_cogl_debug_instances|_cogl_framebuffer_get_projection_stack|_cogl_pipeline_layer_get_texture|_cogl_buffer_map_for_fill_or_fallback|_cogl_texture_can_hardware_repeat|_cogl_pipeline_prune_to_n_layers|_cogl_primitive_draw|test_|unit_test_|_cogl_winsys_glx_get_vtable|_cogl_winsys_egl_xlib_get_vtable|_cogl_winsys_egl_get_vtable|_cogl_closure_disconnect|_cogl_onscreen_notify_complete|_cogl_onscreen_notify_frame_sync|_cogl_winsys_egl_renderer_connect_common|_cogl_winsys_error_quark|_cogl_set_error|_cogl_poll_renderer_add_fd|_cogl_poll_renderer_add_idle|_cogl_framebuffer_winsys_update_size|_cogl_winsys_egl_make_current|_cogl_winsys_egl_ensure_current|_cogl_pixel_format_get_bytes_per_pixel).*"
libmutter_cogl_@LIBMUTTER_API_VERSION@_la_SOURCES = $(cogl_sources_c)
nodist_libmutter_cogl_@LIBMUTTER_API_VERSION@_la_SOURCES = $(BUILT_SOURCES)

View File

@ -109,7 +109,11 @@ _cogl_object_default_unref (void *object)
void
cogl_object_unref (void *obj)
{
void (* unref_func) (void *) = ((CoglObject *) obj)->klass->virt_unref;
void (* unref_func) (void *);
_COGL_RETURN_IF_FAIL (obj != NULL);
unref_func = ((CoglObject *) obj)->klass->virt_unref;
unref_func (obj);
}

View File

@ -1412,22 +1412,12 @@ _cogl_framebuffer_gl_read_pixels_into_bitmap (CoglFramebuffer *framebuffer,
if (!cogl_is_offscreen (framebuffer))
y = framebuffer_height - y - height;
required_format = ctx->driver_vtable->pixel_format_to_gl (ctx,
format,
&gl_intformat,
&gl_format,
&gl_type);
#if HAVE_COGL_GL
/* As we are reading pixels, we want to consider the bitmap according to
* its real pixel format, not the swizzled channels we pretend face to the
* pipeline.
*/
if ((ctx->driver == COGL_DRIVER_GL || ctx->driver == COGL_DRIVER_GL3) &&
(format == COGL_PIXEL_FORMAT_BGRA_8888 ||
format == COGL_PIXEL_FORMAT_BGRA_8888_PRE) &&
_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_TEXTURE_SWIZZLE))
gl_format = GL_BGRA;
#endif
required_format = ctx->driver_vtable->pixel_format_to_gl_with_target (ctx,
framebuffer->internal_format,
format,
&gl_intformat,
&gl_format,
&gl_type);
/* NB: All offscreen rendering is done upside down so there is no need
* to flip in this case... */

View File

@ -181,6 +181,9 @@ _cogl_winsys_egl_make_current (CoglDisplay *display,
EGLSurface read,
EGLContext context);
EGLBoolean
_cogl_winsys_egl_ensure_current (CoglDisplay *display);
#ifdef EGL_KHR_image_base
EGLImageKHR
_cogl_egl_create_image (CoglContext *ctx,

View File

@ -309,6 +309,18 @@ _cogl_winsys_egl_make_current (CoglDisplay *display,
return ret;
}
EGLBoolean
_cogl_winsys_egl_ensure_current (CoglDisplay *display)
{
CoglDisplayEGL *egl_display = display->winsys;
CoglRendererEGL *egl_renderer = display->renderer->winsys;
return eglMakeCurrent (egl_renderer->edpy,
egl_display->current_draw_surface,
egl_display->current_read_surface,
egl_display->current_context);
}
static void
cleanup_context (CoglDisplay *display)
{

View File

@ -2,7 +2,7 @@ AC_PREREQ(2.62)
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [28])
m4_define([mutter_micro_version], [0])
m4_define([mutter_micro_version], [2])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@ -262,7 +262,19 @@ AC_SUBST(XWAYLAND_PATH)
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
MUTTER_NATIVE_BACKEND_MODULES="libdrm >= 2.4.83 libsystemd libinput >= 1.4 gudev-1.0 gbm >= 17.1"
PKG_CHECK_MODULES(ELOGIND, [libelogind], [have_elogind=yes], [have_elogind=no])
if test x$have_elogind = xyes; then
logind_provider="libelogind"
fi
PKG_CHECK_MODULES(SYSTEMD, [libsystemd], [have_systemd=yes], [have_systemd=no])
if test x$have_systemd = xyes -o -z "$logind_provider"; then
logind_provider="libsystemd"
fi
MUTTER_NATIVE_BACKEND_MODULES="libdrm $logind_provider libinput >= 1.4 gudev-1.0 gbm >= 10.3"
AC_ARG_ENABLE(native-backend,
AS_HELP_STRING([--disable-native-backend], [disable mutter native (KMS) backend]),,

View File

@ -10,8 +10,8 @@ msgid ""
msgstr ""
"Project-Id-Version: mutter master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n"
"POT-Creation-Date: 2018-03-05 19:32+0000\n"
"PO-Revision-Date: 2018-03-06 22:02+0100\n"
"POT-Creation-Date: 2018-04-03 20:43+0000\n"
"PO-Revision-Date: 2018-04-09 20:28+0200\n"
"Last-Translator: Matej Urbančič <mateju@svn.gnome.org>\n"
"Language-Team: Slovenian GNOME Translation Team <gnome-si@googlegroups.com>\n"
"Language: sl_SI\n"
@ -21,7 +21,7 @@ msgstr ""
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n"
"%100==4 ? 3 : 0);\n"
"X-Poedit-SourceCharset: utf-8\n"
"X-Generator: Poedit 2.0.4\n"
"X-Generator: Poedit 2.0.6\n"
#: data/50-mutter-navigation.xml:6
msgid "Navigation"
@ -481,7 +481,7 @@ msgstr "Ponovno omogoči tipkovne bližnjice"
#: data/org.gnome.mutter.wayland.gschema.xml.in:64
msgid "Allow grabs with Xwayland"
msgstr ""
msgstr "Dovoli zajemanje z XWayland"
#: data/org.gnome.mutter.wayland.gschema.xml.in:65
msgid ""
@ -491,10 +491,14 @@ msgid ""
"window or be among the applications white-listed in key “xwayland-grab-"
"access-rules”."
msgstr ""
"Upošteva zajeme s tipkovnico, ki jih sprožijo programi X11, zagnani v okolju "
"Xwayland. Če naj se programski zajem upošteva, mora odjemalec ali poslati "
"specifično sporočilo X11 na korensko okno ali pa mora biti zaveden na "
"seznamu programov v ključu »xwayland-garb-access-rules«."
#: data/org.gnome.mutter.wayland.gschema.xml.in:77
msgid "Xwayland applications allowed to issue keyboard grabs"
msgstr ""
msgstr "Program XWayland ima dovoljenje za zajemanje s tipkovnico"
#: data/org.gnome.mutter.wayland.gschema.xml.in:78
msgid ""
@ -509,6 +513,15 @@ msgid ""
"using the specific keyboard shortcut defined by the keybinding key “restore-"
"shortcuts”."
msgstr ""
"Seznam imen ali razredov virov oken X11, ki lahko sprožijo zajeme v okolju "
"Xwayland. Ime oziroma razred vira podanega okna X11 je mogoče pridobiti z "
"ukazom »xprop WM_CLASS«. Uporaba pomožnih znakov » * « in » ? « je podprta. "
"Vrednosti, ki se začnejo z znakom » ! « so uvrščeni na črni seznam. Ta "
"seznam je obravnavan prednostno pred belim seznamom in prekliče zajeme na "
"seznamu sistema. Privzeti seznam vključuje ključ: "
"»@XWAYLAND_GRAB_DEFAULT_ACCESS_RULES@« Uporabniki lahko prekinejo obstoječi "
"zajem z uporabo posebne tipkovne bližnjice, določene s tipkovnim ključem "
"»restore-shortcuts«."
#. TRANSLATORS: This string refers to a button that switches between
#. * different modes.

View File

@ -153,7 +153,7 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \
backends/meta-pointer-constraint.h \
backends/meta-settings.c \
backends/meta-settings-private.h \
backends/meta-stage.h \
backends/meta-stage-private.h \
backends/meta-stage.c \
backends/meta-renderer.c \
backends/meta-renderer.h \
@ -161,6 +161,7 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \
backends/meta-renderer-view.h \
backends/edid-parse.c \
backends/edid.h \
backends/gsm-inhibitor-flag.h \
backends/x11/meta-backend-x11.c \
backends/x11/meta-backend-x11.h \
backends/x11/meta-barrier-x11.c \
@ -183,8 +184,6 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \
backends/x11/nested/meta-cursor-renderer-x11-nested.h \
backends/x11/nested/meta-renderer-x11-nested.c \
backends/x11/nested/meta-renderer-x11-nested.h \
backends/x11/meta-idle-monitor-xsync.c \
backends/x11/meta-idle-monitor-xsync.h \
backends/x11/meta-input-settings-x11.c \
backends/x11/meta-input-settings-x11.h \
backends/x11/meta-monitor-manager-xrandr.c \
@ -247,7 +246,7 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \
compositor/meta-window-actor.c \
compositor/meta-window-actor-private.h \
compositor/meta-window-group.c \
compositor/meta-window-group.h \
compositor/meta-window-group-private.h \
compositor/meta-window-shape.c \
compositor/region-utils.c \
compositor/region-utils.h \
@ -487,8 +486,6 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES += \
backends/native/meta-default-modes.h \
backends/native/meta-gpu-kms.c \
backends/native/meta-gpu-kms.h \
backends/native/meta-idle-monitor-native.c \
backends/native/meta-idle-monitor-native.h \
backends/native/meta-input-settings-native.c \
backends/native/meta-input-settings-native.h \
backends/native/meta-monitor-manager-kms.c \
@ -546,7 +543,9 @@ libmutterinclude_headers = \
meta/meta-settings.h \
meta/meta-shaped-texture.h \
meta/meta-shadow-factory.h \
meta/meta-stage.h \
meta/meta-window-actor.h \
meta/meta-window-group.h \
meta/meta-window-shape.h \
meta/prefs.h \
meta/screen.h \

View File

@ -0,0 +1,36 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSM_INHIBITOR_FLAG_H__
#define __GSM_INHIBITOR_FLAG_H__
#include <glib-object.h>
G_BEGIN_DECLS
typedef enum {
GSM_INHIBITOR_FLAG_LOGOUT = 1 << 0,
GSM_INHIBITOR_FLAG_SWITCH_USER = 1 << 1,
GSM_INHIBITOR_FLAG_SUSPEND = 1 << 2,
GSM_INHIBITOR_FLAG_IDLE = 1 << 3,
GSM_INHIBITOR_FLAG_AUTOMOUNT = 1 << 4
} GsmInhibitorFlag;
G_END_DECLS
#endif /* __GSM_INHIBITOR_FLAG_H__ */

View File

@ -59,8 +59,6 @@ struct _MetaBackendClass
void (* post_init) (MetaBackend *backend);
MetaIdleMonitor * (* create_idle_monitor) (MetaBackend *backend,
int device_id);
MetaMonitorManager * (* create_monitor_manager) (MetaBackend *backend,
GError **error);
MetaCursorRenderer * (* create_cursor_renderer) (MetaBackend *backend);

View File

@ -34,7 +34,7 @@
#include "meta-input-settings-private.h"
#include "backends/x11/meta-backend-x11.h"
#include "meta-cursor-tracker-private.h"
#include "meta-stage.h"
#include "meta-stage-private.h"
#ifdef HAVE_REMOTE_DESKTOP
#include "backends/meta-dbus-session-watcher.h"
@ -110,6 +110,11 @@ struct _MetaBackendPrivate
MetaPointerConstraint *client_pointer_constraint;
MetaDnd *dnd;
UpClient *up_client;
guint sleep_signal_id;
GCancellable *cancellable;
GDBusConnection *system_bus;
};
typedef struct _MetaBackendPrivate MetaBackendPrivate;
@ -136,6 +141,13 @@ meta_backend_finalize (GObject *object)
g_clear_object (&priv->dbus_session_watcher);
#endif
g_object_unref (priv->up_client);
if (priv->sleep_signal_id)
g_dbus_connection_signal_unsubscribe (priv->system_bus, priv->sleep_signal_id);
g_cancellable_cancel (priv->cancellable);
g_clear_object (&priv->cancellable);
g_clear_object (&priv->system_bus);
if (priv->device_update_idle_id)
g_source_remove (priv->device_update_idle_id);
@ -158,7 +170,7 @@ meta_backend_sync_screen_size (MetaBackend *backend)
}
static void
center_pointer (MetaBackend *backend)
reset_pointer_position (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
MetaMonitorManager *monitor_manager = priv->monitor_manager;
@ -167,9 +179,11 @@ center_pointer (MetaBackend *backend)
primary =
meta_monitor_manager_get_primary_logical_monitor (monitor_manager);
/* Move the pointer out of the way to avoid hovering over reactive
* elements (e.g. users list at login) causing undesired behaviour. */
meta_backend_warp_pointer (backend,
primary->rect.x + primary->rect.width / 2,
primary->rect.y + primary->rect.height / 2);
primary->rect.x + primary->rect.width * 0.9,
primary->rect.y + primary->rect.height * 0.9);
}
void
@ -192,7 +206,7 @@ meta_backend_monitors_changed (MetaBackend *backend)
!priv->is_pointer_position_initialized) &&
!meta_monitor_manager_is_headless (monitor_manager))
{
center_pointer (backend);
reset_pointer_position (backend);
priv->is_pointer_position_initialized = TRUE;
}
}
@ -222,7 +236,9 @@ static MetaIdleMonitor *
meta_backend_create_idle_monitor (MetaBackend *backend,
int device_id)
{
return META_BACKEND_GET_CLASS (backend)->create_idle_monitor (backend, device_id);
return g_object_new (META_TYPE_IDLE_MONITOR,
"device-id", device_id,
NULL);
}
static void
@ -465,7 +481,7 @@ meta_backend_real_post_init (MetaBackend *backend)
if (!meta_monitor_manager_is_headless (priv->monitor_manager))
{
center_pointer (backend);
reset_pointer_position (backend);
priv->is_pointer_position_initialized = TRUE;
}
}
@ -590,6 +606,61 @@ meta_backend_create_renderer (MetaBackend *backend,
return META_BACKEND_GET_CLASS (backend)->create_renderer (backend, error);
}
static void
lid_is_closed_changed_cb (UpClient *client,
GParamSpec *pspec,
gpointer user_data)
{
if (up_client_get_lid_is_closed (client))
return;
meta_idle_monitor_reset_idletime (meta_idle_monitor_get_core ());
}
static void
prepare_for_sleep_cb (GDBusConnection *connection,
const gchar *sender_name,
const gchar *object_path,
const gchar *interface_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
gboolean suspending;
g_variant_get (parameters, "(b)", &suspending);
if (suspending)
return;
meta_idle_monitor_reset_idletime (meta_idle_monitor_get_core ());
}
static void
system_bus_gotten_cb (GObject *object,
GAsyncResult *res,
gpointer user_data)
{
MetaBackendPrivate *priv;
GDBusConnection *bus;
bus = g_bus_get_finish (res, NULL);
if (!bus)
return;
priv = meta_backend_get_instance_private (user_data);
priv->system_bus = bus;
priv->sleep_signal_id =
g_dbus_connection_signal_subscribe (priv->system_bus,
"org.freedesktop.login1",
"org.freedesktop.login1.Manager",
"PrepareForSleep",
"/org/freedesktop/login1",
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
prepare_for_sleep_cb,
NULL,
NULL);
}
static gboolean
meta_backend_initable_init (GInitable *initable,
GCancellable *cancellable,
@ -619,6 +690,16 @@ meta_backend_initable_init (GInitable *initable,
priv->dnd = g_object_new (META_TYPE_DND, NULL);
priv->up_client = up_client_new ();
g_signal_connect (priv->up_client, "notify::lid-is-closed",
G_CALLBACK (lid_is_closed_changed_cb), NULL);
priv->cancellable = g_cancellable_new ();
g_bus_get (G_BUS_TYPE_SYSTEM,
priv->cancellable,
system_bus_gotten_cb,
backend);
return TRUE;
}

View File

@ -33,7 +33,7 @@
#include <cogl/cogl.h>
#include <clutter/clutter.h>
#include "meta-stage.h"
#include "meta-stage-private.h"
struct _MetaCursorRendererPrivate
{

View File

@ -24,6 +24,7 @@
#include "meta-idle-monitor-dbus.h"
#include <meta/meta-idle-monitor.h>
#include <backends/meta-idle-monitor-private.h>
#include "meta-dbus-idle-monitor.h"
#include <clutter/clutter.h>
@ -43,6 +44,26 @@ handle_get_idletime (MetaDBusIdleMonitor *skeleton,
return TRUE;
}
static gboolean
handle_reset_idletime (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
MetaIdleMonitor *monitor)
{
if (!g_getenv ("MUTTER_DEBUG_RESET_IDLETIME"))
{
g_dbus_method_invocation_return_error_literal (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_UNKNOWN_METHOD,
"No such method");
return FALSE;
}
meta_idle_monitor_reset_idletime (meta_idle_monitor_get_core ());
meta_dbus_idle_monitor_complete_reset_idletime (skeleton, invocation);
return TRUE;
}
typedef struct {
MetaDBusIdleMonitor *dbus_monitor;
MetaIdleMonitor *monitor;
@ -173,6 +194,8 @@ create_monitor_skeleton (GDBusObjectManagerServer *manager,
G_CALLBACK (handle_add_user_active_watch), monitor, 0);
g_signal_connect_object (skeleton, "handle-remove-watch",
G_CALLBACK (handle_remove_watch), monitor, 0);
g_signal_connect_object (skeleton, "handle-reset-idletime",
G_CALLBACK (handle_reset_idletime), monitor, 0);
g_signal_connect_object (skeleton, "handle-get-idletime",
G_CALLBACK (handle_get_idletime), monitor, 0);

View File

@ -26,9 +26,6 @@
#include <meta/meta-idle-monitor.h>
#include "display-private.h"
#include <X11/Xlib.h>
#include <X11/extensions/sync.h>
typedef struct
{
MetaIdleMonitor *monitor;
@ -38,28 +35,26 @@ typedef struct
GDestroyNotify notify;
guint64 timeout_msec;
int idle_source_id;
GSource *timeout_source;
} MetaIdleMonitorWatch;
struct _MetaIdleMonitor
{
GObject parent_instance;
GDBusProxy *session_proxy;
gboolean inhibited;
GHashTable *watches;
int device_id;
guint64 last_event_time;
};
struct _MetaIdleMonitorClass
{
GObjectClass parent_class;
gint64 (*get_idletime) (MetaIdleMonitor *monitor);
MetaIdleMonitorWatch * (*make_watch) (MetaIdleMonitor *monitor,
guint64 timeout_msec,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify);
};
void _meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch);
void meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor);
#endif /* META_IDLE_MONITOR_PRIVATE_H */

View File

@ -36,6 +36,7 @@
#include <meta/util.h>
#include <meta/main.h>
#include <meta/meta-idle-monitor.h>
#include "gsm-inhibitor-flag.h"
#include "meta-idle-monitor-private.h"
#include "meta-idle-monitor-dbus.h"
#include "meta-backend-private.h"
@ -87,6 +88,7 @@ meta_idle_monitor_dispose (GObject *object)
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
g_clear_pointer (&monitor->watches, g_hash_table_destroy);
g_clear_object (&monitor->session_proxy);
G_OBJECT_CLASS (meta_idle_monitor_parent_class)->dispose (object);
}
@ -151,9 +153,117 @@ meta_idle_monitor_class_init (MetaIdleMonitorClass *klass)
g_object_class_install_property (object_class, PROP_DEVICE_ID, obj_props[PROP_DEVICE_ID]);
}
static void
free_watch (gpointer data)
{
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) data;
MetaIdleMonitor *monitor = watch->monitor;
g_object_ref (monitor);
if (watch->idle_source_id)
{
g_source_remove (watch->idle_source_id);
watch->idle_source_id = 0;
}
if (watch->notify != NULL)
watch->notify (watch->user_data);
if (watch->timeout_source != NULL)
g_source_destroy (watch->timeout_source);
g_object_unref (monitor);
g_slice_free (MetaIdleMonitorWatch, watch);
}
static void
update_inhibited_watch (gpointer key,
gpointer value,
gpointer user_data)
{
MetaIdleMonitor *monitor = user_data;
MetaIdleMonitorWatch *watch = value;
if (!watch->timeout_source)
return;
if (monitor->inhibited)
{
g_source_set_ready_time (watch->timeout_source, -1);
}
else
{
g_source_set_ready_time (watch->timeout_source,
monitor->last_event_time +
watch->timeout_msec * 1000);
}
}
static void
update_inhibited (MetaIdleMonitor *monitor,
gboolean inhibited)
{
if (inhibited == monitor->inhibited)
return;
g_hash_table_foreach (monitor->watches,
update_inhibited_watch,
monitor);
}
static void
meta_idle_monitor_inhibited_actions_changed (GDBusProxy *session,
GVariant *changed,
char **invalidated,
gpointer user_data)
{
MetaIdleMonitor *monitor = user_data;
GVariant *v;
v = g_variant_lookup_value (changed, "InhibitedActions", G_VARIANT_TYPE_UINT32);
if (v)
{
gboolean inhibited;
inhibited = g_variant_get_uint32 (v) & GSM_INHIBITOR_FLAG_IDLE;
g_variant_unref (v);
if (!inhibited)
monitor->last_event_time = g_get_monotonic_time ();
update_inhibited (monitor, inhibited);
}
}
static void
meta_idle_monitor_init (MetaIdleMonitor *monitor)
{
GVariant *v;
monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch);
monitor->last_event_time = g_get_monotonic_time ();
/* Monitor inhibitors */
monitor->session_proxy =
g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
NULL,
"org.gnome.SessionManager",
"/org/gnome/SessionManager",
"org.gnome.SessionManager",
NULL,
NULL);
if (!monitor->session_proxy)
return;
g_signal_connect (monitor->session_proxy, "g-properties-changed",
G_CALLBACK (meta_idle_monitor_inhibited_actions_changed),
monitor);
v = g_dbus_proxy_get_cached_property (monitor->session_proxy,
"InhibitedActions");
monitor->inhibited = g_variant_get_uint32 (v) & GSM_INHIBITOR_FLAG_IDLE;
g_variant_unref (v);
}
/**
@ -185,6 +295,36 @@ meta_idle_monitor_get_for_device (int device_id)
return meta_backend_get_idle_monitor (backend, device_id);
}
static guint32
get_next_watch_serial (void)
{
static guint32 serial = 0;
g_atomic_int_inc (&serial);
return serial;
}
static gboolean
idle_monitor_dispatch_timeout (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) user_data;
_meta_idle_monitor_watch_fire (watch);
g_source_set_ready_time (watch->timeout_source, -1);
return TRUE;
}
static GSourceFuncs idle_monitor_source_funcs = {
.prepare = NULL,
.check = NULL,
.dispatch = idle_monitor_dispatch_timeout,
.finalize = NULL,
};
static MetaIdleMonitorWatch *
make_watch (MetaIdleMonitor *monitor,
guint64 timeout_msec,
@ -194,11 +334,32 @@ make_watch (MetaIdleMonitor *monitor,
{
MetaIdleMonitorWatch *watch;
watch = META_IDLE_MONITOR_GET_CLASS (monitor)->make_watch (monitor,
timeout_msec,
callback,
user_data,
notify);
watch = g_slice_new0 (MetaIdleMonitorWatch);
watch->monitor = monitor;
watch->id = get_next_watch_serial ();
watch->callback = callback;
watch->user_data = user_data;
watch->notify = notify;
watch->timeout_msec = timeout_msec;
if (timeout_msec != 0)
{
GSource *source = g_source_new (&idle_monitor_source_funcs,
sizeof (GSource));
g_source_set_callback (source, NULL, watch, NULL);
if (!monitor->inhibited)
{
g_source_set_ready_time (source,
monitor->last_event_time +
timeout_msec * 1000);
}
g_source_attach (source, NULL);
g_source_unref (source);
watch->timeout_source = source;
}
g_hash_table_insert (monitor->watches,
GUINT_TO_POINTER (watch->id),
@ -314,5 +475,39 @@ meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor,
gint64
meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor)
{
return META_IDLE_MONITOR_GET_CLASS (monitor)->get_idletime (monitor);
return (g_get_monotonic_time () - monitor->last_event_time) / 1000;
}
void
meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor)
{
GList *node, *watch_ids;
monitor->last_event_time = g_get_monotonic_time ();
watch_ids = g_hash_table_get_keys (monitor->watches);
for (node = watch_ids; node != NULL; node = node->next)
{
guint watch_id = GPOINTER_TO_UINT (node->data);
MetaIdleMonitorWatch *watch;
watch = g_hash_table_lookup (monitor->watches,
GUINT_TO_POINTER (watch_id));
if (!watch)
continue;
if (watch->timeout_msec == 0)
{
_meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch);
}
else
{
g_source_set_ready_time (watch->timeout_source,
monitor->last_event_time +
watch->timeout_msec * 1000);
}
}
g_list_free (watch_ids);
}

View File

@ -1088,7 +1088,7 @@ meta_input_settings_changed_cb (GSettings *settings,
update_device_natural_scroll (input_settings, NULL);
else if (strcmp (key, "tap-to-click") == 0)
update_touchpad_tap_enabled (input_settings, NULL);
else if (strcmp (key, "tap-and_drag") == 0)
else if (strcmp (key, "tap-and-drag") == 0)
update_touchpad_tap_and_drag_enabled (input_settings, NULL);
else if (strcmp(key, "disable-while-typing") == 0)
update_touchpad_disable_while_typing (input_settings, NULL);

View File

@ -89,6 +89,9 @@ static gboolean
meta_monitor_manager_is_config_complete (MetaMonitorManager *manager,
MetaMonitorsConfig *config);
static MetaMonitor *
meta_monitor_manager_get_active_monitor (MetaMonitorManager *manager);
MetaBackend *
meta_monitor_manager_get_backend (MetaMonitorManager *manager)
{
@ -198,13 +201,17 @@ calculate_monitor_scale (MetaMonitorManager *manager,
static float
derive_calculated_global_scale (MetaMonitorManager *manager)
{
MetaMonitor *primary_monitor;
MetaMonitor *monitor = NULL;
primary_monitor = meta_monitor_manager_get_primary_monitor (manager);
if (!primary_monitor)
monitor = meta_monitor_manager_get_primary_monitor (manager);
if (!monitor || !meta_monitor_is_active (monitor))
monitor = meta_monitor_manager_get_active_monitor (manager);
if (!monitor)
return 1.0;
return calculate_monitor_scale (manager, primary_monitor);
return calculate_monitor_scale (manager, monitor);
}
static float
@ -578,8 +585,6 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
&error))
{
g_clear_object (&config);
g_warning ("Failed to use linear monitor configuration: %s",
error->message);
g_clear_error (&error);
}
else
@ -597,8 +602,6 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
&error))
{
g_clear_object (&config);
g_warning ("Failed to use fallback monitor configuration: %s",
error->message);
g_clear_error (&error);
}
else
@ -1032,7 +1035,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
NULL /* properties */);
}
for (l = combined_outputs; l; l = l->next)
for (l = combined_outputs, i = 0; l; l = l->next, i++)
{
MetaOutput *output = l->data;
GVariantBuilder crtcs, modes, clones, properties;
@ -2382,6 +2385,12 @@ meta_monitor_manager_get_laptop_panel (MetaMonitorManager *manager)
return find_monitor (manager, meta_monitor_is_laptop_panel);
}
static MetaMonitor *
meta_monitor_manager_get_active_monitor (MetaMonitorManager *manager)
{
return find_monitor (manager, meta_monitor_is_active);
}
MetaMonitor *
meta_monitor_manager_get_monitor_from_connector (MetaMonitorManager *manager,
const char *connector)

View File

@ -153,6 +153,11 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
return;
buffer = pw_stream_peek_buffer (priv->pipewire_stream, buffer_id);
if (!buffer)
{
g_warning ("Failed to peek at PipeWire buffer");
return;
}
if (buffer->datas[0].type == priv->pipewire_type->data.MemFd)
{
@ -327,10 +332,18 @@ create_pipewire_stream (MetaScreenCastStreamSrc *src,
struct spa_fraction max_framerate;
struct spa_fraction min_framerate;
const struct spa_pod *params[1];
int result;
pipewire_stream = pw_stream_new (priv->pipewire_remote,
"meta-screen-cast-src",
NULL);
if (!pipewire_stream)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Failed to create PipeWire stream: %s",
strerror (errno));
return NULL;
}
meta_screen_cast_stream_src_get_specs (src, &width, &height, &frame_rate);
frame_rate_fraction = meta_fraction_from_double (frame_rate);
@ -356,14 +369,15 @@ create_pipewire_stream (MetaScreenCastStreamSrc *src,
&stream_events,
src);
if (pw_stream_connect (pipewire_stream,
PW_DIRECTION_OUTPUT,
NULL,
PW_STREAM_FLAG_NONE,
params, G_N_ELEMENTS (&params)) != 0)
result = pw_stream_connect (pipewire_stream,
PW_DIRECTION_OUTPUT,
NULL,
PW_STREAM_FLAG_NONE,
params, G_N_ELEMENTS (params));
if (result != 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Could not connect");
"Could not connect: %s", spa_strerror (result));
return NULL;
}
@ -466,6 +480,12 @@ create_pipewire_source (void)
(MetaPipeWireSource *) g_source_new (&pipewire_source_funcs,
sizeof (MetaPipeWireSource));
pipewire_source->pipewire_loop = pw_loop_new (NULL);
if (!pipewire_source->pipewire_loop)
{
g_source_destroy ((GSource *) pipewire_source);
return NULL;
}
g_source_add_unix_fd (&pipewire_source->base,
pw_loop_get_fd (pipewire_source->pipewire_loop),
G_IO_IN | G_IO_ERR);
@ -491,6 +511,13 @@ meta_screen_cast_stream_src_initable_init (GInitable *initable,
meta_screen_cast_stream_src_get_instance_private (src);
priv->pipewire_source = create_pipewire_source ();
if (!priv->pipewire_source)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Failed to create PipeWire source");
return FALSE;
}
priv->pipewire_core = pw_core_new (priv->pipewire_source->pipewire_loop,
NULL);
if (!priv->pipewire_core)

View File

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

View File

@ -267,6 +267,8 @@ experimental_features_handler (GVariant *features_variant,
features |= META_EXPERIMENTAL_FEATURE_SCREEN_CAST;
else if (g_str_equal (feature, "remote-desktop"))
features |= META_EXPERIMENTAL_FEATURE_REMOTE_DESKTOP;
else if (g_str_equal (feature, "kms-modifiers"))
features |= META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS;
else
g_info ("Unknown experimental feature '%s'\n", feature);
}

View File

@ -17,39 +17,23 @@
* 02111-1307, USA.
*/
#ifndef META_STAGE_H
#define META_STAGE_H
#ifndef META_STAGE_PRIVATE_H
#define META_STAGE_PRIVATE_H
#include <clutter/clutter.h>
#include <meta/meta-stage.h>
#include "meta-cursor.h"
#include <meta/boxes.h>
G_BEGIN_DECLS
#define META_TYPE_STAGE (meta_stage_get_type ())
#define META_STAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_STAGE, MetaStage))
#define META_STAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_STAGE, MetaStageClass))
#define META_IS_STAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_STAGE))
#define META_IS_STAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_STAGE))
#define META_STAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_STAGE, MetaStageClass))
typedef struct _MetaStage MetaStage;
typedef struct _MetaStageClass MetaStageClass;
typedef struct _MetaOverlay MetaOverlay;
struct _MetaStageClass
{
ClutterStageClass parent_class;
};
struct _MetaStage
{
ClutterStage parent;
};
GType meta_stage_get_type (void) G_GNUC_CONST;
ClutterActor *meta_stage_new (void);
MetaOverlay *meta_stage_create_cursor_overlay (MetaStage *stage);
@ -68,4 +52,4 @@ void meta_stage_update_view_layout (MetaStage *stage);
G_END_DECLS
#endif /* META_STAGE_H */
#endif /* META_STAGE_PRIVATE_H */

View File

@ -22,7 +22,7 @@
#include <config.h>
#include "meta-stage.h"
#include "meta-stage-private.h"
#include <meta/meta-backend.h>
#include <meta/meta-monitor-manager.h>

View File

@ -35,15 +35,15 @@
#include "clutter/evdev/clutter-evdev.h"
#include "meta-barrier-native.h"
#include "meta-border.h"
#include "meta-idle-monitor-native.h"
#include "meta-monitor-manager-kms.h"
#include "meta-cursor-renderer-native.h"
#include "meta-launcher.h"
#include "backends/meta-cursor-tracker-private.h"
#include "backends/meta-idle-monitor-private.h"
#include "backends/meta-logical-monitor.h"
#include "backends/meta-monitor-manager-private.h"
#include "backends/meta-pointer-constraint.h"
#include "backends/meta-stage.h"
#include "backends/meta-stage-private.h"
#include "backends/native/meta-clutter-backend-native.h"
#include "backends/native/meta-input-settings-native.h"
#include "backends/native/meta-renderer-native.h"
@ -60,10 +60,6 @@ struct _MetaBackendNativePrivate
{
MetaLauncher *launcher;
MetaBarrierManagerNative *barrier_manager;
UpClient *up_client;
guint sleep_signal_id;
GCancellable *cancellable;
GDBusConnection *system_bus;
};
typedef struct _MetaBackendNativePrivate MetaBackendNativePrivate;
@ -85,69 +81,9 @@ meta_backend_native_finalize (GObject *object)
meta_launcher_free (priv->launcher);
g_object_unref (priv->up_client);
if (priv->sleep_signal_id)
g_dbus_connection_signal_unsubscribe (priv->system_bus, priv->sleep_signal_id);
g_cancellable_cancel (priv->cancellable);
g_clear_object (&priv->cancellable);
g_clear_object (&priv->system_bus);
G_OBJECT_CLASS (meta_backend_native_parent_class)->finalize (object);
}
static void
prepare_for_sleep_cb (GDBusConnection *connection,
const gchar *sender_name,
const gchar *object_path,
const gchar *interface_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
gboolean suspending;
g_variant_get (parameters, "(b)", &suspending);
if (suspending)
return;
meta_idle_monitor_native_reset_idletime (meta_idle_monitor_get_core ());
}
static void
system_bus_gotten_cb (GObject *object,
GAsyncResult *res,
gpointer user_data)
{
MetaBackendNativePrivate *priv;
GDBusConnection *bus;
bus = g_bus_get_finish (res, NULL);
if (!bus)
return;
priv = meta_backend_native_get_instance_private (META_BACKEND_NATIVE (user_data));
priv->system_bus = bus;
priv->sleep_signal_id = g_dbus_connection_signal_subscribe (priv->system_bus,
"org.freedesktop.login1",
"org.freedesktop.login1.Manager",
"PrepareForSleep",
"/org/freedesktop/login1",
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
prepare_for_sleep_cb,
NULL,
NULL);
}
static void
lid_is_closed_changed_cb (UpClient *client,
GParamSpec *pspec,
gpointer user_data)
{
if (up_client_get_lid_is_closed (client))
return;
meta_idle_monitor_native_reset_idletime (meta_idle_monitor_get_core ());
}
static void
constrain_to_barriers (ClutterInputDevice *device,
guint32 time,
@ -398,15 +334,6 @@ meta_backend_native_post_init (MetaBackend *backend)
meta_backend_get_monitor_manager (backend));
}
static MetaIdleMonitor *
meta_backend_native_create_idle_monitor (MetaBackend *backend,
int device_id)
{
return g_object_new (META_TYPE_IDLE_MONITOR_NATIVE,
"device-id", device_id,
NULL);
}
static MetaMonitorManager *
meta_backend_native_create_monitor_manager (MetaBackend *backend,
GError **error)
@ -604,7 +531,6 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass)
backend_class->post_init = meta_backend_native_post_init;
backend_class->create_idle_monitor = meta_backend_native_create_idle_monitor;
backend_class->create_monitor_manager = meta_backend_native_create_monitor_manager;
backend_class->create_cursor_renderer = meta_backend_native_create_cursor_renderer;
backend_class->create_renderer = meta_backend_native_create_renderer;
@ -637,16 +563,6 @@ meta_backend_native_init (MetaBackendNative *native)
}
priv->barrier_manager = meta_barrier_manager_native_new ();
priv->up_client = up_client_new ();
g_signal_connect (priv->up_client, "notify::lid-is-closed",
G_CALLBACK (lid_is_closed_changed_cb), NULL);
priv->cancellable = g_cancellable_new ();
g_bus_get (G_BUS_TYPE_SYSTEM,
priv->cancellable,
system_bus_gotten_cb,
native);
}
MetaLauncher *
@ -747,5 +663,5 @@ void meta_backend_native_resume (MetaBackendNative *native)
meta_cursor_renderer_native_force_update (cursor_renderer_native);
idle_monitor = meta_backend_get_idle_monitor (backend, 0);
meta_idle_monitor_native_reset_idletime (idle_monitor);
meta_idle_monitor_reset_idletime (idle_monitor);
}

View File

@ -291,9 +291,11 @@ update_monitor_crtc_cursor (MetaMonitor *monitor,
data->in_cursor_renderer_native;
MetaCursorRendererNativePrivate *priv =
meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);
MetaMonitorTransform transform;
ClutterRect scaled_crtc_rect;
float scale;
int crtc_x, crtc_y;
int crtc_width, crtc_height;
if (meta_is_stage_views_scaled ())
scale = meta_logical_monitor_get_scale (data->in_logical_monitor);
@ -305,14 +307,26 @@ update_monitor_crtc_cursor (MetaMonitor *monitor,
META_MONITOR_TRANSFORM_NORMAL,
&crtc_x, &crtc_y);
transform = meta_logical_monitor_get_transform (data->in_logical_monitor);
if (meta_monitor_transform_is_rotated (transform))
{
crtc_width = monitor_crtc_mode->crtc_mode->height;
crtc_height = monitor_crtc_mode->crtc_mode->width;
}
else
{
crtc_width = monitor_crtc_mode->crtc_mode->width;
crtc_height = monitor_crtc_mode->crtc_mode->height;
}
scaled_crtc_rect = (ClutterRect) {
.origin = {
.x = crtc_x / scale,
.y = crtc_y / scale
},
.size = {
.width = monitor_crtc_mode->crtc_mode->width / scale,
.height = monitor_crtc_mode->crtc_mode->height / scale
.width = crtc_width / scale,
.height = crtc_height / scale
},
};

View File

@ -64,6 +64,7 @@ struct _MetaGpuKms
gboolean page_flips_not_supported;
};
G_DEFINE_QUARK (MetaGpuKmsError, meta_gpu_kms_error)
G_DEFINE_TYPE (MetaGpuKms, meta_gpu_kms, META_TYPE_GPU)
static gboolean
@ -751,6 +752,8 @@ meta_gpu_kms_read_current (MetaGpu *gpu,
are freed by the platform-independent layer. */
free_resources (gpu_kms);
g_assert (resources.resources->count_connectors > 0);
init_connectors (gpu_kms, resources.resources);
init_modes (gpu_kms, resources.resources);
init_crtcs (gpu_kms, &resources);
@ -774,11 +777,39 @@ meta_gpu_kms_new (MetaMonitorManagerKms *monitor_manager_kms,
GSource *source;
MetaKmsSource *kms_source;
MetaGpuKms *gpu_kms;
drmModeRes *drm_resources;
guint n_connectors;
int kms_fd;
kms_fd = meta_launcher_open_restricted (launcher, kms_file_path, error);
if (kms_fd == -1)
return FALSE;
return NULL;
/* Some GPUs might have no connectors, for example dedicated GPUs on PRIME (hybrid) laptops.
* These GPUs cannot render anything on separate screens, and they are aggressively switched
* off by the kernel.
*
* If we add these PRIME GPUs to the GPU list anyway, Mutter keeps awakening the secondary GPU,
* and doing this causes a considerable stuttering. These GPUs are usually put to sleep again
* after ~2s without a workload.
*
* For now, to avoid this situation, only create the MetaGpuKms when the GPU has any connectors.
*/
drm_resources = drmModeGetResources (kms_fd);
n_connectors = drm_resources->count_connectors;
drmModeFreeResources (drm_resources);
if (n_connectors == 0)
{
g_set_error (error,
META_GPU_KMS_ERROR,
META_GPU_KMS_ERROR_NO_CONNECTORS,
"No connectors available in this GPU. This is probably a dedicated GPU in a hybrid setup.");
meta_launcher_close_restricted (launcher, kms_fd);
return NULL;
}
gpu_kms = g_object_new (META_TYPE_GPU_KMS,
"monitor-manager", monitor_manager_kms,

View File

@ -29,6 +29,14 @@
#include "backends/meta-gpu.h"
#include "backends/native/meta-monitor-manager-kms.h"
typedef enum
{
META_GPU_KMS_ERROR_NO_CONNECTORS,
} MetaGpuKmsError;
#define META_GPU_KMS_ERROR (meta_gpu_kms_error_quark ())
GQuark meta_gpu_kms_error_quark (void);
#define META_TYPE_GPU_KMS (meta_gpu_kms_get_type ())
G_DECLARE_FINAL_TYPE (MetaGpuKms, meta_gpu_kms, META, GPU_KMS, MetaGpu)

View File

@ -1,200 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
#include "config.h"
#include "meta-idle-monitor-native.h"
#include "meta-idle-monitor-private.h"
#include <meta/util.h>
#include "display-private.h"
#include <string.h>
struct _MetaIdleMonitorNative
{
MetaIdleMonitor parent;
guint64 last_event_time;
};
struct _MetaIdleMonitorNativeClass
{
MetaIdleMonitorClass parent_class;
};
typedef struct {
MetaIdleMonitorWatch base;
GSource *timeout_source;
} MetaIdleMonitorWatchNative;
G_DEFINE_TYPE (MetaIdleMonitorNative, meta_idle_monitor_native, META_TYPE_IDLE_MONITOR)
static gint64
meta_idle_monitor_native_get_idletime (MetaIdleMonitor *monitor)
{
MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor);
return (g_get_monotonic_time () - monitor_native->last_event_time) / 1000;
}
static guint32
get_next_watch_serial (void)
{
static guint32 serial = 0;
g_atomic_int_inc (&serial);
return serial;
}
static gboolean
native_dispatch_timeout (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
MetaIdleMonitorWatchNative *watch_native = user_data;
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_native;
_meta_idle_monitor_watch_fire (watch);
g_source_set_ready_time (watch_native->timeout_source, -1);
return TRUE;
}
static GSourceFuncs native_source_funcs = {
NULL, /* prepare */
NULL, /* check */
native_dispatch_timeout,
NULL, /* finalize */
};
static void
free_watch (gpointer data)
{
MetaIdleMonitorWatchNative *watch_native = data;
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_native;
MetaIdleMonitor *monitor = watch->monitor;
g_object_ref (monitor);
if (watch->idle_source_id)
{
g_source_remove (watch->idle_source_id);
watch->idle_source_id = 0;
}
if (watch->notify != NULL)
watch->notify (watch->user_data);
if (watch_native->timeout_source != NULL)
g_source_destroy (watch_native->timeout_source);
g_object_unref (monitor);
g_slice_free (MetaIdleMonitorWatchNative, watch_native);
}
static MetaIdleMonitorWatch *
meta_idle_monitor_native_make_watch (MetaIdleMonitor *monitor,
guint64 timeout_msec,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify)
{
MetaIdleMonitorWatchNative *watch_native;
MetaIdleMonitorWatch *watch;
MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor);
watch_native = g_slice_new0 (MetaIdleMonitorWatchNative);
watch = (MetaIdleMonitorWatch *) watch_native;
watch->monitor = monitor;
watch->id = get_next_watch_serial ();
watch->callback = callback;
watch->user_data = user_data;
watch->notify = notify;
watch->timeout_msec = timeout_msec;
if (timeout_msec != 0)
{
GSource *source = g_source_new (&native_source_funcs, sizeof (GSource));
g_source_set_callback (source, NULL, watch, NULL);
g_source_set_ready_time (source, monitor_native->last_event_time + timeout_msec * 1000);
g_source_attach (source, NULL);
g_source_unref (source);
watch_native->timeout_source = source;
}
return watch;
}
static void
meta_idle_monitor_native_class_init (MetaIdleMonitorNativeClass *klass)
{
MetaIdleMonitorClass *idle_monitor_class = META_IDLE_MONITOR_CLASS (klass);
idle_monitor_class->get_idletime = meta_idle_monitor_native_get_idletime;
idle_monitor_class->make_watch = meta_idle_monitor_native_make_watch;
}
static void
meta_idle_monitor_native_init (MetaIdleMonitorNative *monitor_native)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (monitor_native);
monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch);
monitor_native->last_event_time = g_get_monotonic_time ();
}
void
meta_idle_monitor_native_reset_idletime (MetaIdleMonitor *monitor)
{
MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor);
GList *node, *watch_ids;
monitor_native->last_event_time = g_get_monotonic_time ();
watch_ids = g_hash_table_get_keys (monitor->watches);
for (node = watch_ids; node != NULL; node = node->next)
{
guint watch_id = GPOINTER_TO_UINT (node->data);
MetaIdleMonitorWatchNative *watch;
watch = g_hash_table_lookup (monitor->watches, GUINT_TO_POINTER (watch_id));
if (!watch)
continue;
if (watch->base.timeout_msec == 0)
{
_meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch);
}
else
{
g_source_set_ready_time (watch->timeout_source,
monitor_native->last_event_time +
watch->base.timeout_msec * 1000);
}
}
g_list_free (watch_ids);
}

View File

@ -1,43 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
#ifndef META_IDLE_MONITOR_NATIVE_H
#define META_IDLE_MONITOR_NATIVE_H
#include <glib-object.h>
#include <meta/meta-idle-monitor.h>
#define META_TYPE_IDLE_MONITOR_NATIVE (meta_idle_monitor_native_get_type ())
#define META_IDLE_MONITOR_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_IDLE_MONITOR_NATIVE, MetaIdleMonitorNative))
#define META_IDLE_MONITOR_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_IDLE_MONITOR_NATIVE, MetaIdleMonitorNativeClass))
#define META_IS_IDLE_MONITOR_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_IDLE_MONITOR_NATIVE))
#define META_IS_IDLE_MONITOR_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_IDLE_MONITOR_NATIVE))
#define META_IDLE_MONITOR_NATIVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_IDLE_MONITOR_NATIVE, MetaIdleMonitorNativeClass))
typedef struct _MetaIdleMonitorNative MetaIdleMonitorNative;
typedef struct _MetaIdleMonitorNativeClass MetaIdleMonitorNativeClass;
GType meta_idle_monitor_native_get_type (void);
void meta_idle_monitor_native_reset_idletime (MetaIdleMonitor *monitor);
#endif /* META_IDLE_MONITOR_NATIVE_H */

View File

@ -44,7 +44,6 @@
#include "backends/meta-backend-private.h"
#include "backends/native/meta-backend-native.h"
#include "meta-cursor-renderer-native.h"
#include "meta-idle-monitor-native.h"
#include "meta-renderer-native.h"
struct _MetaLauncher

View File

@ -674,16 +674,19 @@ meta_monitor_manager_kms_initable_init (GInitable *initable,
gpu_paths = get_gpu_paths (manager_kms, GPU_TYPE_SECONDARY, primary_gpu_path);
for (l = gpu_paths; l; l = l->next)
{
GError *secondary_error = NULL;
g_autoptr (GError) secondary_error = NULL;
char *gpu_path = l->data;
MetaGpuKms *gpu_kms;
gpu_kms = meta_gpu_kms_new (manager_kms, gpu_path, &secondary_error);
if (!gpu_kms)
{
g_warning ("Failed to open secondary gpu '%s': %s",
gpu_path, secondary_error->message);
g_error_free (secondary_error);
if (g_error_matches (secondary_error, META_GPU_KMS_ERROR, META_GPU_KMS_ERROR_NO_CONNECTORS))
g_message ("Ignoring GPU %s due to the lack of connectors", gpu_path);
else
g_warning ("Failed to open secondary gpu '%s': %s", gpu_path, secondary_error->message);
continue;
}
meta_monitor_manager_add_gpu (META_MONITOR_MANAGER (manager_kms),

View File

@ -193,6 +193,8 @@ struct _MetaRendererNative
MetaMonitorManagerKms *monitor_manager_kms;
MetaGles3 *gles3;
gboolean use_modifiers;
GHashTable *gpu_datas;
CoglClosure *swap_notify_idle;
@ -1586,6 +1588,7 @@ gbm_get_next_fb_id (MetaGpuKms *gpu_kms,
struct gbm_bo **out_next_bo,
uint32_t *out_next_fb_id)
{
MetaRendererNative *renderer_native = meta_renderer_native_from_gpu (gpu_kms);
struct gbm_bo *next_bo;
uint32_t next_fb_id;
int kms_fd;
@ -1608,7 +1611,8 @@ gbm_get_next_fb_id (MetaGpuKms *gpu_kms,
kms_fd = meta_gpu_kms_get_fd (gpu_kms);
if (modifiers[0] != DRM_FORMAT_MOD_INVALID)
if (renderer_native->use_modifiers &&
modifiers[0] != DRM_FORMAT_MOD_INVALID)
{
if (drmModeAddFB2WithModifiers (kms_fd,
gbm_bo_get_width (next_bo),
@ -1854,18 +1858,18 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
frame_info = g_queue_peek_tail (&onscreen->pending_frame_infos);
frame_info->global_frame_counter = renderer_native->frame_counter;
/*
* Wait for the flip callback before continuing, as we might have started the
* animation earlier due to the animation being driven by some other monitor.
*/
wait_for_pending_flips (onscreen);
update_secondary_gpu_state_pre_swap_buffers (onscreen);
parent_vtable->onscreen_swap_buffers_with_damage (onscreen,
rectangles,
n_rectangles);
/*
* Wait for the flip callback before continuing, as we might have started the
* animation earlier due to the animation being driven by some other monitor.
*/
wait_for_pending_flips (onscreen);
renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
render_gpu);
switch (renderer_gpu_data->mode)
@ -1907,12 +1911,7 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
* context.
*/
if (egl_context_changed)
{
_cogl_winsys_egl_make_current (cogl_display,
EGL_NO_SURFACE,
EGL_NO_SURFACE,
EGL_NO_CONTEXT);
}
_cogl_winsys_egl_ensure_current (cogl_display);
}
static gboolean
@ -1996,7 +1995,7 @@ meta_renderer_native_create_surface_gbm (CoglOnscreen *onscreen,
CoglRenderer *cogl_renderer = cogl_display->renderer;
CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys;
MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform;
struct gbm_surface *new_gbm_surface;
struct gbm_surface *new_gbm_surface = NULL;
EGLNativeWindowType egl_native_window;
EGLSurface new_egl_surface;
uint32_t format = GBM_FORMAT_XRGB8888;
@ -2006,7 +2005,10 @@ meta_renderer_native_create_surface_gbm (CoglOnscreen *onscreen,
meta_renderer_native_get_gpu_data (renderer_native,
onscreen_native->render_gpu);
modifiers = get_supported_modifiers (onscreen, format);
if (renderer_native->use_modifiers)
modifiers = get_supported_modifiers (onscreen, format);
else
modifiers = NULL;
if (modifiers)
{
@ -2017,7 +2019,8 @@ meta_renderer_native_create_surface_gbm (CoglOnscreen *onscreen,
modifiers->len);
g_array_free (modifiers, TRUE);
}
else
if (!new_gbm_surface)
{
uint32_t flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
@ -3389,6 +3392,22 @@ meta_renderer_native_finalize (GObject *object)
G_OBJECT_CLASS (meta_renderer_native_parent_class)->finalize (object);
}
static void
meta_renderer_native_constructed (GObject *object)
{
MetaRendererNative *renderer_native = META_RENDERER_NATIVE (object);
MetaMonitorManager *monitor_manager =
META_MONITOR_MANAGER (renderer_native->monitor_manager_kms);
MetaBackend *backend = meta_monitor_manager_get_backend (monitor_manager);
MetaSettings *settings = meta_backend_get_settings (backend);
if (meta_settings_is_experimental_feature_enabled (
settings, META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS))
renderer_native->use_modifiers = TRUE;
G_OBJECT_CLASS (meta_renderer_native_parent_class)->constructed (object);
}
static void
meta_renderer_native_init (MetaRendererNative *renderer_native)
{
@ -3407,6 +3426,7 @@ meta_renderer_native_class_init (MetaRendererNativeClass *klass)
object_class->get_property = meta_renderer_native_get_property;
object_class->set_property = meta_renderer_native_set_property;
object_class->finalize = meta_renderer_native_finalize;
object_class->constructed = meta_renderer_native_constructed;
renderer_class->create_cogl_renderer = meta_renderer_native_create_cogl_renderer;
renderer_class->create_view = meta_renderer_native_create_view;

View File

@ -37,8 +37,7 @@
#include <X11/Xlib-xcb.h>
#include <xkbcommon/xkbcommon-x11.h>
#include "meta-idle-monitor-xsync.h"
#include "backends/meta-stage.h"
#include "backends/meta-stage-private.h"
#include "backends/x11/meta-clutter-backend-x11.h"
#include "backends/x11/meta-renderer-x11.h"
#include "meta/meta-cursor-tracker.h"
@ -47,6 +46,7 @@
#include "display-private.h"
#include "compositor/compositor-private.h"
#include "backends/meta-dnd-private.h"
#include "backends/meta-idle-monitor-private.h"
struct _MetaBackendX11Private
{
@ -57,6 +57,8 @@ struct _MetaBackendX11Private
int xsync_event_base;
int xsync_error_base;
XSyncAlarm user_active_alarm;
XSyncCounter counter;
int xinput_opcode;
int xinput_event_base;
@ -83,13 +85,77 @@ G_DEFINE_TYPE_WITH_CODE (MetaBackendX11, meta_backend_x11, META_TYPE_BACKEND,
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
initable_iface_init));
static void
handle_alarm_notify (MetaBackend *backend,
XEvent *event)
uint64_to_xsync_value (uint64_t value,
XSyncValue *xsync_value)
{
meta_backend_foreach_device_monitor (backend,
(GFunc) meta_idle_monitor_xsync_handle_xevent,
event);
XSyncIntsToValue (xsync_value, value & 0xffffffff, value >> 32);
}
static XSyncAlarm
xsync_user_active_alarm_set (MetaBackendX11Private *priv)
{
XSyncAlarmAttributes attr;
XSyncValue delta;
unsigned long flags;
flags = (XSyncCACounter | XSyncCAValueType | XSyncCATestType |
XSyncCAValue | XSyncCADelta | XSyncCAEvents);
XSyncIntToValue (&delta, 0);
attr.trigger.counter = priv->counter;
attr.trigger.value_type = XSyncAbsolute;
attr.delta = delta;
attr.events = TRUE;
uint64_to_xsync_value (1, &attr.trigger.wait_value);
attr.trigger.test_type = XSyncNegativeTransition;
return XSyncCreateAlarm (priv->xdisplay, flags, &attr);
}
static XSyncCounter
find_idletime_counter (MetaBackendX11Private *priv)
{
int i;
int n_counters;
XSyncSystemCounter *counters;
XSyncCounter counter = None;
counters = XSyncListSystemCounters (priv->xdisplay, &n_counters);
for (i = 0; i < n_counters; i++)
{
if (g_strcmp0 (counters[i].name, "IDLETIME") == 0)
{
counter = counters[i].counter;
break;
}
}
XSyncFreeSystemCounterList (counters);
return counter;
}
static void
handle_alarm_notify (MetaBackend *backend,
XSyncAlarmNotifyEvent *alarm_event)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
MetaIdleMonitor *idle_monitor;
XSyncAlarmAttributes attr;
if (alarm_event->state != XSyncAlarmActive ||
alarm_event->alarm != priv->user_active_alarm)
return;
attr.events = TRUE;
XSyncChangeAlarm (priv->xdisplay, priv->user_active_alarm,
XSyncCAEvents, &attr);
idle_monitor = meta_backend_get_idle_monitor (backend, 0);
meta_idle_monitor_reset_idletime (idle_monitor);
}
static void
@ -275,7 +341,7 @@ handle_host_xevent (MetaBackend *backend,
bypass_clutter);
if (event->type == (priv->xsync_event_base + XSyncAlarmNotify))
handle_alarm_notify (backend, event);
handle_alarm_notify (backend, (XSyncAlarmNotifyEvent *) event);
if (event->type == priv->xkb_event_base)
{
@ -423,6 +489,12 @@ meta_backend_x11_post_init (MetaBackend *backend)
!XSyncInitialize (priv->xdisplay, &major, &minor))
meta_fatal ("Could not initialize XSync");
priv->counter = find_idletime_counter (priv);
if (priv->counter == None)
meta_fatal ("Could not initialize XSync counter");
priv->user_active_alarm = xsync_user_active_alarm_set (priv);
if (XQueryExtension (priv->xdisplay,
"XInputExtension",
&priv->xinput_opcode,
@ -464,15 +536,6 @@ meta_backend_x11_create_clutter_backend (MetaBackend *backend)
return g_object_new (META_TYPE_CLUTTER_BACKEND_X11, NULL);
}
static MetaIdleMonitor *
meta_backend_x11_create_idle_monitor (MetaBackend *backend,
int device_id)
{
return g_object_new (META_TYPE_IDLE_MONITOR_XSYNC,
"device-id", device_id,
NULL);
}
static gboolean
meta_backend_x11_grab_device (MetaBackend *backend,
int device_id,
@ -679,14 +742,30 @@ initable_iface_init (GInitableIface *initable_iface)
initable_iface->init = meta_backend_x11_initable_init;
}
static void
meta_backend_x11_finalize (GObject *object)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (object);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
if (priv->user_active_alarm != None)
{
XSyncDestroyAlarm (priv->xdisplay, priv->user_active_alarm);
priv->user_active_alarm = None;
}
G_OBJECT_CLASS (meta_backend_x11_parent_class)->finalize (object);
}
static void
meta_backend_x11_class_init (MetaBackendX11Class *klass)
{
MetaBackendClass *backend_class = META_BACKEND_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_backend_x11_finalize;
backend_class->create_clutter_backend = meta_backend_x11_create_clutter_backend;
backend_class->post_init = meta_backend_x11_post_init;
backend_class->create_idle_monitor = meta_backend_x11_create_idle_monitor;
backend_class->grab_device = meta_backend_x11_grab_device;
backend_class->ungrab_device = meta_backend_x11_ungrab_device;
backend_class->warp_pointer = meta_backend_x11_warp_pointer;

View File

@ -29,7 +29,7 @@
#include <X11/extensions/Xfixes.h>
#include "meta-backend-x11.h"
#include "meta-stage.h"
#include "meta-stage-private.h"
struct _MetaCursorRendererX11Private
{

View File

@ -1,373 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
#include "config.h"
#include "meta-idle-monitor-xsync.h"
#include "meta-idle-monitor-private.h"
#include "meta-backend-x11.h"
#include <string.h>
struct _MetaIdleMonitorXSync
{
MetaIdleMonitor parent;
GHashTable *alarms;
Display *display;
XSyncCounter counter;
XSyncAlarm user_active_alarm;
};
struct _MetaIdleMonitorXSyncClass
{
MetaIdleMonitorClass parent_class;
};
typedef struct {
MetaIdleMonitorWatch base;
XSyncAlarm xalarm;
} MetaIdleMonitorWatchXSync;
G_DEFINE_TYPE (MetaIdleMonitorXSync, meta_idle_monitor_xsync, META_TYPE_IDLE_MONITOR)
static gint64
_xsyncvalue_to_int64 (XSyncValue value)
{
return ((guint64) XSyncValueHigh32 (value)) << 32
| (guint64) XSyncValueLow32 (value);
}
#define GUINT64_TO_XSYNCVALUE(value, ret) XSyncIntsToValue (ret, (value) & 0xFFFFFFFF, ((guint64)(value)) >> 32)
static XSyncAlarm
_xsync_alarm_set (MetaIdleMonitorXSync *monitor_xsync,
XSyncTestType test_type,
guint64 interval,
gboolean want_events)
{
XSyncAlarmAttributes attr;
XSyncValue delta;
guint flags;
flags = XSyncCACounter | XSyncCAValueType | XSyncCATestType |
XSyncCAValue | XSyncCADelta | XSyncCAEvents;
XSyncIntToValue (&delta, 0);
attr.trigger.counter = monitor_xsync->counter;
attr.trigger.value_type = XSyncAbsolute;
attr.delta = delta;
attr.events = want_events;
GUINT64_TO_XSYNCVALUE (interval, &attr.trigger.wait_value);
attr.trigger.test_type = test_type;
return XSyncCreateAlarm (monitor_xsync->display, flags, &attr);
}
static void
ensure_alarm_rescheduled (Display *dpy,
XSyncAlarm alarm)
{
XSyncAlarmAttributes attr;
/* Some versions of Xorg have an issue where alarms aren't
* always rescheduled. Calling XSyncChangeAlarm, even
* without any attributes, will reschedule the alarm. */
XSyncChangeAlarm (dpy, alarm, 0, &attr);
}
static void
set_alarm_enabled (Display *dpy,
XSyncAlarm alarm,
gboolean enabled)
{
XSyncAlarmAttributes attr;
attr.events = enabled;
XSyncChangeAlarm (dpy, alarm, XSyncCAEvents, &attr);
}
static char *
counter_name_for_device (int device_id)
{
if (device_id > 0)
return g_strdup_printf ("DEVICEIDLETIME %d", device_id);
return g_strdup ("IDLETIME");
}
static XSyncCounter
find_idletime_counter (MetaIdleMonitorXSync *monitor_xsync)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (monitor_xsync);
int i;
int ncounters;
XSyncSystemCounter *counters;
XSyncCounter counter = None;
char *counter_name;
counter_name = counter_name_for_device (monitor->device_id);
counters = XSyncListSystemCounters (monitor_xsync->display, &ncounters);
for (i = 0; i < ncounters; i++)
{
if (counters[i].name != NULL && strcmp (counters[i].name, counter_name) == 0)
{
counter = counters[i].counter;
break;
}
}
XSyncFreeSystemCounterList (counters);
g_free (counter_name);
return counter;
}
static void
init_xsync (MetaIdleMonitorXSync *monitor_xsync)
{
monitor_xsync->counter = find_idletime_counter (monitor_xsync);
/* IDLETIME counter not found? */
if (monitor_xsync->counter == None)
{
g_warning ("IDLETIME counter not found\n");
return;
}
monitor_xsync->user_active_alarm = _xsync_alarm_set (monitor_xsync, XSyncNegativeTransition, 1, FALSE);
}
static void
meta_idle_monitor_xsync_dispose (GObject *object)
{
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (object);
if (monitor_xsync->user_active_alarm != None)
{
XSyncDestroyAlarm (monitor_xsync->display, monitor_xsync->user_active_alarm);
monitor_xsync->user_active_alarm = None;
}
g_clear_pointer (&monitor_xsync->alarms, g_hash_table_destroy);
G_OBJECT_CLASS (meta_idle_monitor_xsync_parent_class)->dispose (object);
}
static void
meta_idle_monitor_xsync_constructed (GObject *object)
{
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (object);
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
monitor_xsync->display = meta_backend_x11_get_xdisplay (backend);
init_xsync (monitor_xsync);
G_OBJECT_CLASS (meta_idle_monitor_xsync_parent_class)->constructed (object);
}
static gint64
meta_idle_monitor_xsync_get_idletime (MetaIdleMonitor *monitor)
{
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor);
XSyncValue value;
if (!XSyncQueryCounter (monitor_xsync->display, monitor_xsync->counter, &value))
return -1;
return _xsyncvalue_to_int64 (value);
}
static gboolean
fire_watch_idle (gpointer data)
{
MetaIdleMonitorWatch *watch = data;
watch->idle_source_id = 0;
_meta_idle_monitor_watch_fire (watch);
return FALSE;
}
static guint32
get_next_watch_serial (void)
{
static guint32 serial = 0;
g_atomic_int_inc (&serial);
return serial;
}
static void
free_watch (gpointer data)
{
MetaIdleMonitorWatchXSync *watch_xsync = data;
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_xsync;
MetaIdleMonitor *monitor = watch->monitor;
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor);
g_object_ref (monitor);
if (watch->idle_source_id)
{
g_source_remove (watch->idle_source_id);
watch->idle_source_id = 0;
}
if (watch->notify != NULL)
watch->notify (watch->user_data);
if (watch_xsync->xalarm != monitor_xsync->user_active_alarm &&
watch_xsync->xalarm != None)
{
XSyncDestroyAlarm (monitor_xsync->display, watch_xsync->xalarm);
g_hash_table_remove (monitor_xsync->alarms, (gpointer) watch_xsync->xalarm);
}
g_object_unref (monitor);
g_slice_free (MetaIdleMonitorWatchXSync, watch_xsync);
}
static MetaIdleMonitorWatch *
meta_idle_monitor_xsync_make_watch (MetaIdleMonitor *monitor,
guint64 timeout_msec,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify)
{
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor);
MetaIdleMonitorWatchXSync *watch_xsync;
MetaIdleMonitorWatch *watch;
watch_xsync = g_slice_new0 (MetaIdleMonitorWatchXSync);
watch = (MetaIdleMonitorWatch *) watch_xsync;
watch->monitor = monitor;
watch->id = get_next_watch_serial ();
watch->callback = callback;
watch->user_data = user_data;
watch->notify = notify;
watch->timeout_msec = timeout_msec;
if (monitor_xsync->user_active_alarm != None)
{
if (timeout_msec != 0)
{
watch_xsync->xalarm = _xsync_alarm_set (monitor_xsync, XSyncPositiveTransition, timeout_msec, TRUE);
g_hash_table_add (monitor_xsync->alarms, (gpointer) watch_xsync->xalarm);
if (meta_idle_monitor_get_idletime (monitor) > (gint64)timeout_msec)
{
watch->idle_source_id = g_idle_add (fire_watch_idle, watch);
g_source_set_name_by_id (watch->idle_source_id, "[mutter] fire_watch_idle");
}
}
else
{
watch_xsync->xalarm = monitor_xsync->user_active_alarm;
set_alarm_enabled (monitor_xsync->display, monitor_xsync->user_active_alarm, TRUE);
}
}
return watch;
}
static void
meta_idle_monitor_xsync_class_init (MetaIdleMonitorXSyncClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
MetaIdleMonitorClass *idle_monitor_class = META_IDLE_MONITOR_CLASS (klass);
object_class->dispose = meta_idle_monitor_xsync_dispose;
object_class->constructed = meta_idle_monitor_xsync_constructed;
idle_monitor_class->get_idletime = meta_idle_monitor_xsync_get_idletime;
idle_monitor_class->make_watch = meta_idle_monitor_xsync_make_watch;
}
static void
meta_idle_monitor_xsync_init (MetaIdleMonitorXSync *monitor_xsync)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (monitor_xsync);
monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch);
monitor_xsync->alarms = g_hash_table_new (NULL, NULL);
}
static void
check_x11_watches (MetaIdleMonitor *monitor,
XSyncAlarm alarm)
{
GList *node, *watch_ids;
/* we get the keys and do explicit look ups in case
* an early iteration of the loop ends up leading
* to watches from later iterations getting invalidated
*/
watch_ids = g_hash_table_get_keys (monitor->watches);
for (node = watch_ids; node != NULL; node = node->next)
{
guint watch_id = GPOINTER_TO_UINT (node->data);
MetaIdleMonitorWatchXSync *watch;
watch = g_hash_table_lookup (monitor->watches, GUINT_TO_POINTER (watch_id));
if (watch && watch->xalarm == alarm)
_meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch);
}
g_list_free (watch_ids);
}
void
meta_idle_monitor_xsync_handle_xevent (MetaIdleMonitor *monitor,
XSyncAlarmNotifyEvent *alarm_event)
{
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor);
XSyncAlarm alarm;
gboolean has_alarm;
if (alarm_event->state != XSyncAlarmActive)
return;
alarm = alarm_event->alarm;
has_alarm = FALSE;
if (alarm == monitor_xsync->user_active_alarm)
{
set_alarm_enabled (monitor_xsync->display,
alarm,
FALSE);
has_alarm = TRUE;
}
else if (g_hash_table_contains (monitor_xsync->alarms, (gpointer) alarm))
{
ensure_alarm_rescheduled (monitor_xsync->display,
alarm);
has_alarm = TRUE;
}
if (has_alarm)
check_x11_watches (monitor, alarm);
}

View File

@ -1,47 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
#ifndef META_IDLE_MONITOR_XSYNC_H
#define META_IDLE_MONITOR_XSYNC_H
#include <glib-object.h>
#include <meta/meta-idle-monitor.h>
#include <X11/Xlib.h>
#include <X11/extensions/sync.h>
#define META_TYPE_IDLE_MONITOR_XSYNC (meta_idle_monitor_xsync_get_type ())
#define META_IDLE_MONITOR_XSYNC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_IDLE_MONITOR_XSYNC, MetaIdleMonitorXSync))
#define META_IDLE_MONITOR_XSYNC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_IDLE_MONITOR_XSYNC, MetaIdleMonitorXSyncClass))
#define META_IS_IDLE_MONITOR_XSYNC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_IDLE_MONITOR_XSYNC))
#define META_IS_IDLE_MONITOR_XSYNC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_IDLE_MONITOR_XSYNC))
#define META_IDLE_MONITOR_XSYNC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_IDLE_MONITOR_XSYNC, MetaIdleMonitorXSyncClass))
typedef struct _MetaIdleMonitorXSync MetaIdleMonitorXSync;
typedef struct _MetaIdleMonitorXSyncClass MetaIdleMonitorXSyncClass;
GType meta_idle_monitor_xsync_get_type (void);
void meta_idle_monitor_xsync_handle_xevent (MetaIdleMonitor *monitor,
XSyncAlarmNotifyEvent *xevent);
#endif /* META_IDLE_MONITOR_XSYNC_H */

View File

@ -67,7 +67,7 @@
#include <meta/meta-background-group.h>
#include <meta/meta-shadow-factory.h>
#include "meta-window-actor-private.h"
#include "meta-window-group.h"
#include "meta-window-group-private.h"
#include "window-private.h" /* to check window->hidden */
#include "display-private.h" /* for meta_display_lookup_x_window() and meta_display_cancel_touch() */
#include "util-private.h"

View File

@ -0,0 +1,24 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#ifndef META_WINDOW_GROUP_PRIVATE_H
#define META_WINDOW_GROUP_PRIVATE_H
#include <meta/meta-window-group.h>
#include <meta/screen.h>
/**
* MetaWindowGroup:
*
* This class is a subclass of ClutterActor with special handling for
* #MetaCullable when painting children. It uses code similar to
* meta_cullable_cull_out_children(), but also has additional special
* cases for the undirected window, and similar.
*/
typedef struct _MetaWindowGroupPrivate MetaWindowGroupPrivate;
ClutterActor *meta_window_group_new (MetaScreen *screen);
#endif /* META_WINDOW_GROUP_PRIVATE_H */

View File

@ -10,7 +10,7 @@
#include "clutter-utils.h"
#include "compositor-private.h"
#include "meta-window-actor-private.h"
#include "meta-window-group.h"
#include "meta-window-group-private.h"
#include "window-private.h"
#include "meta-cullable.h"

View File

@ -1,37 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#ifndef META_WINDOW_GROUP_H
#define META_WINDOW_GROUP_H
#include <clutter/clutter.h>
#include <meta/screen.h>
/**
* MetaWindowGroup:
*
* This class is a subclass of ClutterActor with special handling for
* #MetaCullable when painting children. It uses code similar to
* meta_cullable_cull_out_children(), but also has additional special
* cases for the undirected window, and similar.
*/
#define META_TYPE_WINDOW_GROUP (meta_window_group_get_type ())
#define META_WINDOW_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_WINDOW_GROUP, MetaWindowGroup))
#define META_WINDOW_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_WINDOW_GROUP, MetaWindowGroupClass))
#define META_IS_WINDOW_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_WINDOW_GROUP))
#define META_IS_WINDOW_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_WINDOW_GROUP))
#define META_WINDOW_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_WINDOW_GROUP, MetaWindowGroupClass))
typedef struct _MetaWindowGroup MetaWindowGroup;
typedef struct _MetaWindowGroupClass MetaWindowGroupClass;
typedef struct _MetaWindowGroupPrivate MetaWindowGroupPrivate;
GType meta_window_group_get_type (void);
ClutterActor *meta_window_group_new (MetaScreen *screen);
gboolean meta_window_group_actor_is_untransformed (ClutterActor *actor,
int *x_origin,
int *y_origin);
#endif /* META_WINDOW_GROUP_H */

View File

@ -53,7 +53,7 @@
#include "backends/meta-logical-monitor.h"
#include "backends/native/meta-backend-native.h"
#include "backends/x11/meta-backend-x11.h"
#include "backends/meta-stage.h"
#include "backends/meta-stage-private.h"
#include "backends/meta-input-settings-private.h"
#include <clutter/x11/clutter-x11.h>

View File

@ -32,9 +32,10 @@
#ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-backend-native.h"
#include "backends/native/meta-idle-monitor-native.h"
#endif
#include "backends/meta-idle-monitor-private.h"
#ifdef HAVE_WAYLAND
#include "wayland/meta-wayland-private.h"
#endif
@ -92,46 +93,38 @@ get_window_for_event (MetaDisplay *display,
static void
handle_idletime_for_event (const ClutterEvent *event)
{
#ifdef HAVE_NATIVE_BACKEND
/* This is handled by XSync under X11. */
MetaBackend *backend = meta_get_backend ();
ClutterInputDevice *device, *source_device;
MetaIdleMonitor *core_monitor, *device_monitor;
int device_id;
if (META_IS_BACKEND_NATIVE (backend))
device = clutter_event_get_device (event);
if (device == NULL)
return;
if (event->any.flags & CLUTTER_EVENT_FLAG_SYNTHETIC ||
event->type == CLUTTER_ENTER ||
event->type == CLUTTER_LEAVE ||
event->type == CLUTTER_STAGE_STATE ||
event->type == CLUTTER_DESTROY_NOTIFY ||
event->type == CLUTTER_CLIENT_MESSAGE ||
event->type == CLUTTER_DELETE)
return;
device_id = clutter_input_device_get_device_id (device);
core_monitor = meta_idle_monitor_get_core ();
device_monitor = meta_idle_monitor_get_for_device (device_id);
meta_idle_monitor_reset_idletime (core_monitor);
meta_idle_monitor_reset_idletime (device_monitor);
source_device = clutter_event_get_source_device (event);
if (source_device != device)
{
ClutterInputDevice *device, *source_device;
MetaIdleMonitor *core_monitor, *device_monitor;
int device_id;
device = clutter_event_get_device (event);
if (device == NULL)
return;
if (event->any.flags & CLUTTER_EVENT_FLAG_SYNTHETIC ||
event->type == CLUTTER_ENTER ||
event->type == CLUTTER_LEAVE ||
event->type == CLUTTER_STAGE_STATE ||
event->type == CLUTTER_DESTROY_NOTIFY ||
event->type == CLUTTER_CLIENT_MESSAGE ||
event->type == CLUTTER_DELETE)
return;
device_id = clutter_input_device_get_device_id (device);
core_monitor = meta_idle_monitor_get_core ();
device_monitor = meta_idle_monitor_get_for_device (device_id);
meta_idle_monitor_native_reset_idletime (core_monitor);
meta_idle_monitor_native_reset_idletime (device_monitor);
source_device = clutter_event_get_source_device (event);
if (source_device != device)
{
device_id = clutter_input_device_get_device_id (device);
device_monitor = meta_idle_monitor_get_for_device (device_id);
meta_idle_monitor_native_reset_idletime (device_monitor);
}
meta_idle_monitor_reset_idletime (device_monitor);
}
#endif /* HAVE_NATIVE_BACKEND */
}
static gboolean

View File

@ -81,6 +81,7 @@ typedef enum
META_MOVE_RESIZE_STATE_CHANGED = 1 << 5,
META_MOVE_RESIZE_UNMAXIMIZE = 1 << 6,
META_MOVE_RESIZE_FORCE_MOVE = 1 << 7,
META_MOVE_RESIZE_WAYLAND_STATE_CHANGED = 1 << 8,
} MetaMoveResizeFlags;
typedef enum
@ -88,6 +89,7 @@ typedef enum
META_MOVE_RESIZE_RESULT_MOVED = 1 << 0,
META_MOVE_RESIZE_RESULT_RESIZED = 1 << 1,
META_MOVE_RESIZE_RESULT_FRAME_SHAPE_CHANGED = 1 << 2,
META_MOVE_RESIZE_RESULT_STATE_CHANGED = 1 << 3,
} MetaMoveResizeResultFlags;
typedef enum

View File

@ -3997,7 +3997,7 @@ meta_window_move_resize_internal (MetaWindow *window,
if ((moved_or_resized ||
did_placement ||
(flags & META_MOVE_RESIZE_STATE_CHANGED) != 0) &&
(result & META_MOVE_RESIZE_RESULT_STATE_CHANGED) != 0) &&
window->known_to_compositor)
{
meta_compositor_sync_window_geometry (window->display->compositor,
@ -5268,7 +5268,7 @@ static cairo_surface_t *
load_default_window_icon (int size)
{
GtkIconTheme *theme = gtk_icon_theme_get_default ();
GdkPixbuf *pixbuf;
g_autoptr (GdkPixbuf) pixbuf = NULL;
const char *icon_name;
if (gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME))

View File

@ -54,4 +54,7 @@ MetaMonitorSwitchConfigType meta_monitor_manager_get_switch_config (MetaMonitorM
gint meta_monitor_manager_get_display_configuration_timeout (void);
/* Re-declaration of parent type for introspection */
GType meta_dbus_display_config_skeleton_get_type (void) G_GNUC_CONST;
#endif /* META_MONITOR_MANAGER_H */

32
src/meta/meta-stage.h Normal file
View File

@ -0,0 +1,32 @@
/*
* Copyright (C) 2012 Intel Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_STAGE_H
#define META_STAGE_H
#include "clutter/clutter.h"
G_BEGIN_DECLS
#define META_TYPE_STAGE (meta_stage_get_type ())
G_DECLARE_FINAL_TYPE (MetaStage, meta_stage, META, STAGE, ClutterStage)
G_END_DECLS
#endif /* META_STAGE_H */

View File

@ -0,0 +1,11 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#ifndef META_WINDOW_GROUP_H
#define META_WINDOW_GROUP_H
#include "clutter/clutter.h"
#define META_TYPE_WINDOW_GROUP (meta_window_group_get_type())
G_DECLARE_FINAL_TYPE (MetaWindowGroup, meta_window_group, META, WINDOW_GROUP, ClutterActor)
#endif /* META_WINDOW_GROUP_H */

View File

@ -28,6 +28,8 @@
<arg name="id" direction="in" type="u" />
</method>
<method name="ResetIdletime"/>
<signal name="WatchFired">
<arg name="id" direction="out" type="u" />
</signal>

View File

@ -1330,7 +1330,9 @@ meta_ui_frame_get_mask (MetaUIFrame *frame,
MetaFrameBorders borders;
MetaFrameFlags flags;
MetaRectangle frame_rect;
int scale = meta_theme_get_window_scaling_factor ();
cairo_surface_t *surface;
double xscale, yscale;
int scale;
meta_window_get_frame_rect (frame->meta_window, &frame_rect);
@ -1340,7 +1342,11 @@ meta_ui_frame_get_mask (MetaUIFrame *frame,
meta_ui_frame_get_borders (frame, &borders);
/* See comment in meta_frame_layout_draw_with_style() for details on HiDPI handling */
cairo_scale (cr, scale, scale);
scale = meta_theme_get_window_scaling_factor ();
surface = cairo_get_target (cr);
cairo_surface_get_device_scale (surface, &xscale, &yscale);
cairo_surface_set_device_scale (surface, scale, scale);
gtk_render_background (frame->style_info->styles[META_STYLE_ELEMENT_FRAME], cr,
borders.invisible.left / scale,
borders.invisible.top / scale,
@ -1349,6 +1355,8 @@ meta_ui_frame_get_mask (MetaUIFrame *frame,
borders.invisible.left / scale,
borders.invisible.top / scale,
frame_rect.width / scale, borders.total.top / scale);
cairo_surface_set_device_scale (surface, xscale, yscale);
}
/* XXX -- this is disgusting. Find a better approach here.

View File

@ -580,7 +580,7 @@ meta_frame_layout_calc_geometry (MetaFrameLayout *layout,
x = rect->visible.x - layout->button_margin.left * scale;
if (i > 0)
x -= layout->titlebar_spacing;
x -= layout->titlebar_spacing * scale;
--i;
}
@ -712,6 +712,8 @@ get_class_from_button_type (MetaButtonType type)
return "maximize";
case META_BUTTON_TYPE_MINIMIZE:
return "minimize";
case META_BUTTON_TYPE_APPMENU:
return "appmenu";
default:
return NULL;
}
@ -734,7 +736,9 @@ meta_frame_layout_draw_with_style (MetaFrameLayout *layout,
GdkRectangle titlebar_rect;
GdkRectangle button_rect;
const MetaFrameBorders *borders;
int scale = meta_theme_get_window_scaling_factor ();
cairo_surface_t *frame_surface;
double xscale, yscale;
int scale;
/* We opt out of GTK+/Clutter's HiDPI handling, so we have to do the scaling
* ourselves; the nitty-gritty is a bit confusing, so here is an overview:
@ -746,8 +750,14 @@ meta_frame_layout_draw_with_style (MetaFrameLayout *layout,
* - for drawing, we scale the canvas to have GTK+ render elements (borders,
* radii, ...) at the correct scale - as a result, we have to "unscale"
* the geometry again to not apply the scaling twice
* - As per commit e36b629c GTK expects the device scale to be set and match
* the final scaling or the surface caching won't take this in account
* breaking -gtk-scaled items.
*/
cairo_scale (cr, scale, scale);
scale = meta_theme_get_window_scaling_factor ();
frame_surface = cairo_get_target (cr);
cairo_surface_get_device_scale (frame_surface, &xscale, &yscale);
cairo_surface_set_device_scale (frame_surface, scale, scale);
borders = &fgeom->borders;
@ -903,6 +913,8 @@ meta_frame_layout_draw_with_style (MetaFrameLayout *layout,
gtk_style_context_remove_class (style, button_class);
gtk_style_context_set_state (style, state);
}
cairo_surface_set_device_scale (frame_surface, xscale, yscale);
}
/**

View File

@ -585,6 +585,17 @@ is_new_size_hints_valid (MetaWindow *window,
(new_max_height == 0 || new_min_height <= new_max_height));
}
static inline gboolean
did_geometry_change (MetaWaylandZxdgSurfaceV6 *xdg_surface,
MetaWaylandPendingState *pending)
{
MetaWaylandZxdgSurfaceV6Private *priv =
meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface);
return pending->has_new_geometry &&
!meta_rectangle_equal (&priv->geometry, &pending->new_geometry);
}
static void
meta_wayland_zxdg_toplevel_v6_commit (MetaWaylandSurfaceRole *surface_role,
MetaWaylandPendingState *pending)
@ -600,6 +611,11 @@ meta_wayland_zxdg_toplevel_v6_commit (MetaWaylandSurfaceRole *surface_role,
meta_wayland_surface_role_get_surface (surface_role);
MetaWindow *window = surface->window;
MetaRectangle window_geometry;
gboolean geometry_changed;
/* This check must happen before chaining up, otherwise the new geometry
* is applied and it'll always return FALSE. */
geometry_changed = did_geometry_change (xdg_surface, pending);
surface_role_class =
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_zxdg_toplevel_v6_parent_class);
@ -618,7 +634,7 @@ meta_wayland_zxdg_toplevel_v6_commit (MetaWaylandSurfaceRole *surface_role,
if (!window)
return;
if (pending->has_new_geometry)
if (geometry_changed || meta_window_wayland_needs_move_resize (window))
{
window_geometry =
meta_wayland_zxdg_surface_v6_get_window_geometry (xdg_surface);

View File

@ -325,7 +325,8 @@ void
meta_wayland_seat_update (MetaWaylandSeat *seat,
const ClutterEvent *event)
{
if (!event_from_supported_hardware_device (seat, event) &&
if (!(clutter_event_get_flags (event) & CLUTTER_EVENT_FLAG_INPUT_METHOD) &&
!event_from_supported_hardware_device (seat, event) &&
!event_is_synthesized_crossing (event))
return;
@ -363,7 +364,8 @@ gboolean
meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
const ClutterEvent *event)
{
if (!event_from_supported_hardware_device (seat, event))
if (!(clutter_event_get_flags (event) & CLUTTER_EVENT_FLAG_INPUT_METHOD) &&
!event_from_supported_hardware_device (seat, event))
return FALSE;
switch (event->type)

View File

@ -392,6 +392,7 @@ pending_state_init (MetaWaylandPendingState *state)
{
state->newly_attached = FALSE;
state->buffer = NULL;
state->buffer_destroy_handler_id = 0;
state->dx = 0;
state->dy = 0;
state->scale = 0;
@ -421,8 +422,11 @@ pending_state_destroy (MetaWaylandPendingState *state)
g_clear_pointer (&state->opaque_region, cairo_region_destroy);
if (state->buffer)
g_signal_handler_disconnect (state->buffer,
state->buffer_destroy_handler_id);
{
g_signal_handler_disconnect (state->buffer,
state->buffer_destroy_handler_id);
state->buffer_destroy_handler_id = 0;
}
wl_list_for_each_safe (cb, next, &state->frame_callback_list, link)
wl_resource_destroy (cb->resource);
}
@ -435,36 +439,84 @@ pending_state_reset (MetaWaylandPendingState *state)
}
static void
move_pending_state (MetaWaylandPendingState *from,
MetaWaylandPendingState *to)
merge_pending_state (MetaWaylandPendingState *from,
MetaWaylandPendingState *to)
{
if (from->buffer)
g_signal_handler_disconnect (from->buffer, from->buffer_destroy_handler_id);
if (from->newly_attached)
{
if (to->buffer)
{
g_signal_handler_disconnect (to->buffer,
to->buffer_destroy_handler_id);
to->buffer_destroy_handler_id = 0;
}
to->newly_attached = from->newly_attached;
to->buffer = from->buffer;
to->dx = from->dx;
to->dy = from->dy;
to->scale = from->scale;
to->surface_damage = from->surface_damage;
to->buffer_damage = from->buffer_damage;
to->input_region = from->input_region;
to->input_region_set = from->input_region_set;
to->opaque_region = from->opaque_region;
to->opaque_region_set = from->opaque_region_set;
to->new_geometry = from->new_geometry;
to->has_new_geometry = from->has_new_geometry;
to->has_new_min_size = from->has_new_min_size;
to->new_min_width = from->new_min_width;
to->new_min_height = from->new_min_height;
to->has_new_max_size = from->has_new_max_size;
to->new_max_width = from->new_max_width;
to->new_max_height = from->new_max_height;
if (from->buffer)
{
g_signal_handler_disconnect (from->buffer,
from->buffer_destroy_handler_id);
from->buffer_destroy_handler_id = 0;
}
to->newly_attached = TRUE;
to->buffer = from->buffer;
to->dx = from->dx;
to->dy = from->dy;
}
wl_list_init (&to->frame_callback_list);
wl_list_insert_list (&to->frame_callback_list, &from->frame_callback_list);
if (to->buffer)
cairo_region_union (to->surface_damage, from->surface_damage);
cairo_region_union (to->buffer_damage, from->buffer_damage);
cairo_region_destroy (from->surface_damage);
cairo_region_destroy (from->buffer_damage);
if (from->input_region_set)
{
if (to->input_region)
cairo_region_union (to->input_region, from->input_region);
else
to->input_region = cairo_region_reference (from->input_region);
to->input_region_set = TRUE;
cairo_region_destroy (from->input_region);
}
if (from->opaque_region_set)
{
if (to->opaque_region)
cairo_region_union (to->opaque_region, from->opaque_region);
else
to->opaque_region = cairo_region_reference (from->opaque_region);
to->opaque_region_set = TRUE;
cairo_region_destroy (from->opaque_region);
}
if (from->has_new_geometry)
{
to->new_geometry = from->new_geometry;
to->has_new_geometry = TRUE;
}
if (from->has_new_min_size)
{
to->new_min_width = from->new_min_width;
to->new_min_height = from->new_min_height;
to->has_new_min_size = TRUE;
}
if (from->has_new_max_size)
{
to->new_max_width = from->new_max_width;
to->new_max_height = from->new_max_height;
to->has_new_max_size = TRUE;
}
if (from->scale > 0)
to->scale = from->scale;
if (to->buffer && to->buffer_destroy_handler_id == 0)
{
to->buffer_destroy_handler_id =
g_signal_connect (to->buffer, "resource-destroyed",
@ -528,7 +580,10 @@ meta_wayland_surface_is_effectively_synchronized (MetaWaylandSurface *surface)
{
MetaWaylandSurface *parent = surface->sub.parent;
return meta_wayland_surface_is_effectively_synchronized (parent);
if (parent)
return meta_wayland_surface_is_effectively_synchronized (parent);
return TRUE;
}
}
}
@ -712,7 +767,7 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface)
* surface is in effective desynchronized mode.
*/
if (meta_wayland_surface_is_effectively_synchronized (surface))
move_pending_state (surface->pending, surface->sub.pending);
merge_pending_state (surface->pending, surface->sub.pending);
else
meta_wayland_surface_apply_pending_state (surface, surface->pending);
}

View File

@ -252,10 +252,8 @@ is_valid_child (MetaWaylandSurface *surface)
if (!surface->role)
return FALSE;
if (!META_IS_WAYLAND_XDG_SURFACE (surface->role))
return FALSE;
if (!META_IS_WAYLAND_ZXDG_SURFACE_V6 (surface->role))
if (!META_IS_WAYLAND_XDG_TOPLEVEL (surface->role) &&
!META_IS_WAYLAND_ZXDG_TOPLEVEL_V6 (surface->role))
return FALSE;
if (!surface->window)
@ -384,7 +382,7 @@ xdg_importer_import (struct wl_client *client,
(!META_IS_WAYLAND_XDG_SURFACE (exported->surface->role) &&
!META_IS_WAYLAND_ZXDG_SURFACE_V6 (exported->surface->role)))
{
zxdg_imported_v1_send_destroyed (resource);
zxdg_imported_v1_send_destroyed (xdg_imported_resource);
return;
}

View File

@ -608,6 +608,17 @@ is_new_size_hints_valid (MetaWindow *window,
(new_max_height == 0 || new_min_height <= new_max_height));
}
static inline gboolean
did_geometry_change (MetaWaylandXdgSurface *xdg_surface,
MetaWaylandPendingState *pending)
{
MetaWaylandXdgSurfacePrivate *priv =
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
return pending->has_new_geometry &&
!meta_rectangle_equal (&priv->geometry, &pending->new_geometry);
}
static void
meta_wayland_xdg_toplevel_commit (MetaWaylandSurfaceRole *surface_role,
MetaWaylandPendingState *pending)
@ -621,6 +632,7 @@ meta_wayland_xdg_toplevel_commit (MetaWaylandSurfaceRole *surface_role,
meta_wayland_surface_role_get_surface (surface_role);
MetaWindow *window;
MetaRectangle window_geometry;
gboolean geometry_changed;
if (!surface->buffer_ref.buffer && xdg_surface_priv->first_buffer_attached)
{
@ -630,6 +642,10 @@ meta_wayland_xdg_toplevel_commit (MetaWaylandSurfaceRole *surface_role,
window = surface->window;
/* This check must happen before chaining up, otherwise the new geometry
* is applied and it'll always return FALSE. */
geometry_changed = did_geometry_change (xdg_surface, pending);
surface_role_class =
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_xdg_toplevel_parent_class);
surface_role_class->commit (surface_role, pending);
@ -643,7 +659,7 @@ meta_wayland_xdg_toplevel_commit (MetaWaylandSurfaceRole *surface_role,
if (!pending->newly_attached)
return;
if (pending->has_new_geometry)
if (geometry_changed || meta_window_wayland_needs_move_resize (window))
{
window_geometry = meta_wayland_xdg_surface_get_window_geometry (xdg_surface);
meta_window_wayland_move_resize (window,

View File

@ -48,6 +48,7 @@ struct _MetaWindowWayland
int geometry_scale;
MetaWaylandSerial pending_configure_serial;
gboolean has_pending_state_change;
gboolean has_pending_move;
int pending_move_x;
int pending_move_y;
@ -324,6 +325,9 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
window->buffer_rect.x = new_buffer_x;
window->buffer_rect.y = new_buffer_y;
}
if (flags & META_MOVE_RESIZE_WAYLAND_STATE_CHANGED)
*result |= META_MOVE_RESIZE_RESULT_STATE_CHANGED;
}
else
{
@ -336,6 +340,8 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
wl_window->pending_move_x = new_x;
wl_window->pending_move_y = new_y;
}
wl_window->has_pending_state_change = (flags & META_MOVE_RESIZE_STATE_CHANGED) != 0;
}
}
@ -629,12 +635,9 @@ meta_window_wayland_new (MetaDisplay *display,
}
static gboolean
should_do_pending_move (MetaWindowWayland *wl_window,
MetaWaylandSerial *acked_configure_serial)
is_pending_ack_configure (MetaWindowWayland *wl_window,
MetaWaylandSerial *acked_configure_serial)
{
if (!wl_window->has_pending_move)
return FALSE;
if (wl_window->pending_configure_serial.set)
{
/* If we're waiting for a configure and this isn't an ACK for
@ -677,6 +680,7 @@ meta_window_wayland_move_resize (MetaWindow *window,
int gravity;
MetaRectangle rect;
MetaMoveResizeFlags flags;
gboolean pending_ack_configure;
/* new_geom is in the logical pixel coordinate space, but MetaWindow wants its
* rects to represent what in turn will end up on the stage, i.e. we need to
@ -700,10 +704,12 @@ meta_window_wayland_move_resize (MetaWindow *window,
flags = META_MOVE_RESIZE_WAYLAND_RESIZE;
pending_ack_configure = is_pending_ack_configure (wl_window, acked_configure_serial);
/* x/y are ignored when we're doing interactive resizing */
if (!meta_grab_op_is_resizing (window->display->grab_op))
{
if (wl_window->has_pending_move && should_do_pending_move (wl_window, acked_configure_serial))
if (wl_window->has_pending_move && pending_ack_configure)
{
rect.x = wl_window->pending_move_x;
rect.y = wl_window->pending_move_y;
@ -724,6 +730,12 @@ meta_window_wayland_move_resize (MetaWindow *window,
}
}
if (wl_window->has_pending_state_change && pending_ack_configure)
{
flags |= META_MOVE_RESIZE_WAYLAND_STATE_CHANGED;
wl_window->has_pending_state_change = FALSE;
}
wl_window->pending_configure_serial.set = FALSE;
rect.width = new_geom.width;
@ -903,3 +915,10 @@ meta_window_wayland_get_max_size (MetaWindow *window,
scale_size (width, height, scale);
}
gboolean
meta_window_wayland_needs_move_resize (MetaWindow *window)
{
MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window);
return wl_window->has_pending_state_change || wl_window->has_pending_move;
}

View File

@ -78,5 +78,6 @@ void meta_window_wayland_get_max_size (MetaWindow *window,
int *width,
int *height);
gboolean meta_window_wayland_needs_move_resize (MetaWindow *window);
#endif

View File

@ -26,6 +26,8 @@
#include "meta-xwayland.h"
#include "meta-xwayland-private.h"
#include <meta/main.h>
#include <glib.h>
#include <glib-unix.h>
#include <errno.h>
@ -393,30 +395,34 @@ xserver_died (GObject *source,
gpointer user_data)
{
GSubprocess *proc = G_SUBPROCESS (source);
GError *error = NULL;
g_autoptr (GError) error = NULL;
if (!g_subprocess_wait_finish (proc, result, &error))
{
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
g_error ("Failed to finish waiting for Xwayland: %s", error->message);
g_clear_error (&error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
g_warning ("Failed to finish waiting for Xwayland: %s", error->message);
}
else if (!g_subprocess_get_successful (proc))
g_error ("X Wayland crashed; aborting");
g_warning ("X Wayland crashed; exiting");
else
{
/* For now we simply abort if we see the server exit.
*
* In the future X will only be loaded lazily for legacy X support
* but for now it's a hard requirement. */
g_error ("Spurious exit of X Wayland server");
g_warning ("Spurious exit of X Wayland server");
}
meta_exit (META_EXIT_ERROR);
}
static int
x_io_error (Display *display)
{
g_error ("Connection to xwayland lost");
g_warning ("Connection to xwayland lost");
meta_exit (META_EXIT_ERROR);
return 0;
}

View File

@ -1282,6 +1282,8 @@ meta_window_x11_move_resize_internal (MetaWindow *window,
*result |= META_MOVE_RESIZE_RESULT_MOVED;
if (need_resize_client || need_resize_frame)
*result |= META_MOVE_RESIZE_RESULT_RESIZED;
if (flags & META_MOVE_RESIZE_STATE_CHANGED)
*result |= META_MOVE_RESIZE_RESULT_STATE_CHANGED;
update_gtk_edge_constraints (window);
}