Compare commits

..

100 Commits

Author SHA1 Message Date
liushuyu
b1b46f196c Update zh_CN translation 2016-10-30 02:19:33 +08:00
Florian Müllner
3082504d1b Bump version to 3.18.4
Update NEWS.
2016-04-21 12:10:30 +02:00
Florian Müllner
8a529123be Shut up some compiler warnings 2016-04-21 12:10:30 +02:00
Florian Müllner
54a680266c Do not skip CoglError parameters
While CoglError is a define to GError, it doesn't follow the convention
of ignoring errors when NULL is passed, but rather treats the error as
fatal :-(
That's clearly unwanted for a compositor, so make sure to always pass
an error parameter where a runtime error is possible (i.e. any CoglError
that is not a malformed blend string).

https://bugzilla.gnome.org/show_bug.cgi?id=765058
2016-04-20 17:18:14 +02:00
Florian Müllner
e6d414edfc Do not try to unref NULL CoglObjects
https://bugzilla.gnome.org/show_bug.cgi?id=765058
2016-04-20 17:18:14 +02:00
Rui Matos
70f20c90bd Handle meta_screen_get_monitor_for_point() returning NULL
On the X11 backend we don't track the pointer position in
priv->current_x/y which remain set to zero. That means we never set
the clutter stage cursor if point 0,0 isn't covered by any monitor
since we return early.

Commit 4bebc5e5fa introduced this to
avoid crashing on the prepare-at handlers when the cursor position
doesn't fall inside any monitor area but we can handle that higher up
in the stack. In that case, the sprite's scale doesn't matter since
the cursor won't be shown anyway so we can skip setting it.

https://bugzilla.gnome.org/show_bug.cgi?id=763159
2016-03-10 16:07:58 +01:00
Cédric Valmary
b5f7005b88 Updated Occitan translation 2016-03-03 20:11:38 +00:00
Florian Müllner
f0e2e238f3 Bump version to 3.18.3
Update NEWS.
2016-02-22 16:42:44 +01:00
Jasper St. Pierre
0c48a2633f window-x11: Fix checks for a bounding region input region
When cleaning up the logic in commit c408cf7, I forgot to properly apply
de Morgan's laws to an inverse.

Reported by ricotz on IRC.

(cherry picked from commit 6fc51e3723)
2016-01-23 14:58:56 +01:00
Rui Matos
26a18e8312 x11/window: Ensure we send a ConfigureNotify to just mapped windows
When managing a non-OR window we're required by the ICCCM to behave as
if we received a ConfigureRequest which means that we must generate a
synthetic ConfigureNotify even if the window isn't moved or resized
from its current (initial) geometry.

During MetaWindow's x11/wayland split a slight behavior change for x11
windows crept in. Before the code split, MetaWindow->rect was
initialized with the X window's geometry, but now we're not
initializing MetaWindowX11Private->client_rect which causes the checks
for whether it's necessary to move/resize the window in
meta_window_x11_move_resize_internal() to tell us that we do need to
move/resize which means we do an XConfigureWindow() call and don't
send the sythetic ConfigureNotify. But since the X window isn't really
moving, the XConfigureWindow() call doesn't cause the X server to
generate a ConfigureNotify which breaks some clients such as Java's
AWT.

We can fix this by setting MetaWindowX11Privatew->client_rect for both
OR and non-OR windows. We can set buffer_rect for non-OR windows as
well to simplify the code since it will be assigned the correct value
in meta_window_x11_move_resize_internal() .

https://bugzilla.gnome.org/show_bug.cgi?id=759492
2015-12-16 19:49:05 +01:00
Marek Chalupa
2ea121a186 wayland: bind wayland socket after xwayland is initialized
During xwayland initialization we run main loop and dispatch wayland
events, so that xwayland can initialize. If some client during this
phase connects and creates surface, mutter crashes because
it is not initialized yet. If we bind wayland socket after xwayland
is initialized and main loop is not running anymore, no client can
connect to mutter during initialization and that is what we want.

https://bugzilla.gnome.org/show_bug.cgi?id=751845
2015-12-16 19:49:02 +01:00
Rui Matos
958cdd5117 monitor-manager: Fix the max potential number of logical monitors
The max potential number of logical monitors (i.e. MetaMonitorInfos)
is the number of CRTCs, not the number of outputs.

In cases where we have more enabled CRTCs than connected outputs we
would end up appending more MetaMonitorInfos to the GArray than the
size it was initialized with which means the array would get
re-allocated rendering invalid some MetaCRTC->logical_monitor pointers
assigned previously and thus ending in crashes later on.

https://bugzilla.gnome.org/show_bug.cgi?id=751638
2015-11-29 19:19:12 +01:00
Marek Chalupa
58d2bd0581 cursor-renderer: do not update cursor if it is out of monitor
if the cursor coordinates are out of monitor, just don't render the
cursor

https://bugzilla.gnome.org/show_bug.cgi?id=756698
2015-11-29 19:19:08 +01:00
Rui Matos
e5067368f5 x11/window-props: Initialize bypass compositor hint
If a client only ever sets the hint on window creation we'd never pick
the value. Also, include override redirect windows since the hint is
relevant to them too.

https://bugzilla.gnome.org/show_bug.cgi?id=758544
2015-11-23 19:55:55 +01:00
Florian Müllner
c89918a339 Bump version to 3.18.2
Update NEWS.
2015-11-12 16:11:47 +01:00
Florian Müllner
15b5e6717f backend: Add missing include 2015-11-12 16:11:47 +01:00
Owen W. Taylor
3b977f18b3 Exit, not abort, when we fail to initialize Clutter
Failing to initialize Clutter isn't something it's useful to report
into automatic bug tracking systems or get a backtrace for - in fact,
the most common case is that DISPLAY is unset or points to a
non-existent X server. So simply exit rather than calling g_error().

https://bugzilla.gnome.org/show_bug.cgi?id=757311
2015-11-06 17:02:03 -05:00
Owen W. Taylor
233c148c16 MetaLauncher: Don't g_error() on failure
g_error() is the wrong thing to do when, for example, we can't find the
DRM device, since Mutter should just fail to start rather than reporting
a bug into automatic bug tracking systems. Rather than trying to decipher
which errors are "expected" and which not, just make all failure paths
in meta_launcher_new() return a GError out to the caller - which we make
exit(1).

https://bugzilla.gnome.org/show_bug.cgi?id=757311
2015-11-06 17:02:03 -05:00
Rui Matos
8c561a9075 monitor-manager-xrandr: Skip outputs with no crtcs
Outputs with no crtcs shouldn't happen, but if it does we should
ignore them, instead of possibly crashing later.

https://bugzilla.gnome.org/show_bug.cgi?id=756796
2015-10-30 18:08:07 +01:00
Rui Matos
eb1df05570 monitor-manager-xrandr: Skip outputs with no modes
If we can't find any valid modes for an output we need to unwind and
skip the output because trying to use a modeless output later will
crash us.

https://bugzilla.gnome.org/show_bug.cgi?id=756796
2015-10-30 18:08:06 +01:00
Rui Matos
ffa8c0039d Revert "monitor-manager-xrandr: Ignore outputs without modes"
This reverts commit 86a913d37a. It
introduced a memory leak, so we'll go for a cleaner approach.

https://bugzilla.gnome.org/show_bug.cgi?id=756796
2015-10-30 18:08:04 +01:00
Rui Matos
379044c069 monitor-manager: Expose a few helpers to clear structs
These are useful for child classes to unwind cleanly when constructing
their structures.

https://bugzilla.gnome.org/show_bug.cgi?id=756796
2015-10-30 18:08:03 +01:00
Rui Matos
c5f40f7481 window: Properly update window->monitor for the desktop window
We don't want to move the desktop window but we still need to update
window->monitor or otherwise we'll be left with a pointer to invalid
memory.

https://bugzilla.gnome.org/show_bug.cgi?id=757148
2015-10-27 15:04:04 +01:00
Rui Matos
c9b0d04503 monitor-manager-xrandr: Ignore outputs without modes
In some cases we get outputs without any valid mode. We need to ignore
them or we'll crash later.

https://bugzilla.gnome.org/show_bug.cgi?id=756796
2015-10-23 14:17:00 +02:00
Alberts Muktupāvels
0d41399fed backend-x11: Ensure the Xkb group index remains properly set
Ubuntu ships a patch in the X server that makes the group switch
keybindings only work on key release, i.e. the X server internal group
locking happens on key release which means that mutter gets the
XKB_KEY_ISO_Next_Group key press event, does its XLockGroup() call
with a new index and then, on key release, the X server moves the
index further again.

We can work around this without affecting our behavior in unpatched X
servers by doing a XLockGroup() every time we're notified of the
locked group changing if it doesn't match what we requested.

https://bugzilla.gnome.org/show_bug.cgi?id=756543
2015-10-23 14:16:59 +02:00
Daniel Șerbănescu
5d695c674e Updated Romanian Translation 2015-10-22 19:12:28 +02:00
Rui Matos
7717725270 monitor-manager-xrandr: Be more robust when reading XRROutputInfos
We might get modes in XRROutputInfos that aren't in the
XRRScreenResources we get earlier. This always seems to be transient,
i.e. when it happens, the X server will usually send us a follow up
RRScreenChangeNotify where we then get a "stable" view of the world
again.

In any case, when these glitches happen, we end up with NULL pointers
in the MetaOutput->modes array which makes us crash later on. This
patch ensures that doesn't happen.

https://bugzilla.gnome.org/show_bug.cgi?id=756660
2015-10-16 13:59:11 +02:00
Jonas Ådahl
6542ef2970 wayland: Set the xdg_popup pointer even when not mapping
If we immediately dismiss the popup, we still need to set the
surface->xdg_popup pointer field in order for the destructor to
properly clean up the state. Not doing this may cause a crash if the
xdg_popup resource that was immediately dismissed is destoryed after
wl_surface during client destruction.

https://bugzilla.gnome.org/show_bug.cgi?id=756675
2015-10-16 13:59:08 +02:00
Florian Müllner
83d19c8ae2 iconcache: Mark surfaces as dirty after changing data
This is required to tell cairo to update its cached areas.
2015-10-16 04:13:45 +02:00
Florian Müllner
9c81b718f9 Bump version to 3.18.1
Update NEWS.
2015-10-15 19:06:54 +02:00
Florian Müllner
3a63d58d9e events: Don't use XIEvent serial numbers
XInput2 uses the raw sequence number for XIEvent serials[0], which only
matches the serial number in XEvents up to 16 bits[1]. So in order to
be able to make reliable comparisons with serials from other events or
calls to XNextRequest(), always use the field from the original XEvent
rather than the XIEvent serial (at least until we can get libXi fixed).

This (partially) reverts commit 35dd1e644d.

[0] http://cgit.freedesktop.org/xorg/lib/libXi/commit?id=5d43d4914dcabb6d
[1] http://cgit.freedesktop.org/xorg/lib/libX11/tree/src/XlibInt.c#n265

https://bugzilla.gnome.org/show_bug.cgi?id=756649
2015-10-15 18:50:51 +02:00
Florian Müllner
a95ae4d178 session: Fix crash when saving sticky windows
Since commit 527c53a2a0, window->workspace is set to %NULL when
the window is sticky (see comment[0]), so don't try to save the
workspace index in that case.

[0] https://git.gnome.org/browse/mutter/tree/src/core/window.c#n4307

https://bugzilla.gnome.org/show_bug.cgi?id=756642
2015-10-15 16:30:43 +02:00
Cosimo Cecchi
a692fd3808 compositor: add hooks for fullscreen and unfullscreen animations
https://bugzilla.gnome.org/show_bug.cgi?id=707248
2015-10-12 22:28:30 -04:00
Cosimo Cecchi
377ecdb864 compositor: pass correct parameter to meta_window_actor_size_change()
We were always passing the parameter for a maximize animation.
2015-10-12 15:39:51 -04:00
Owen W. Taylor
d7f544f42e META_DEBUG_STACK: Fix message about the dumped window order
A change in the code made the windows list bottom-to-top instead
of top-to-bottom, but the message printed out still said
"Top to bottom."
2015-10-12 09:52:25 -04:00
Owen W. Taylor
1ab8b854df Improve debug logging of Wayland windows
Displaying all Wayland windows with the XID of 0x0 makes it hard
to figure out what is going on ... use the recently-added
window->stamp to show Wayland windows as W1/W2/W3...
2015-10-12 09:52:25 -04:00
Owen W. Taylor
ae7aabd5de Protect against stray calls to meta_display_end_grab_op()
If end_grab_op() is called when there's a "compositor grab"
rather than a grab op is in effect, silently return.

https://bugzilla.gnome.org/show_bug.cgi?id=745785
2015-10-12 09:50:48 -04:00
Jasper St. Pierre
b975676c5d window-actor: Draw shadows around some CSD windows
Some windows, like Chromium and Steam, are technically CSD in that they
don't want a system titlebar and draw their own, but we should still
provide them with a shadow.
2015-10-07 12:09:30 -07:00
Florian Müllner
86d8c3954f theme: Stop hiding titlebar buttons in dialogs
As design patterns have evolved, dialogs that use CSD do use titlebar
buttons, so it's time to re-enable them for SSD as well.

https://bugzilla.gnome.org/show_bug.cgi?id=641630
2015-10-07 16:09:17 +02:00
Rui Matos
54557f062e xprops: Fix reading Window and XSyncCounter properties
Both Window and XSyncCounter are XIDs which on 64 bit X clients are 8
bytes wide. But the values on the wire are 32 bit so, for these types,
we always copy 4 bytes into results->prop. As such copying them out
with a cast such as *(Window *) means that we are actually reading 8
bytes which depending on whether the higher addressed 4 bytes are zero
means that sometimes this works while others it gives us a bogus
value.

https://bugzilla.gnome.org/show_bug.cgi?id=756074
2015-10-06 22:33:42 +02:00
Jonas Ådahl
130807a308 wayland: Don't pre-multiply root cursor sizes with primary monitor scale
We cannot use the XSETTINGS value for cursor theme size because
gnome-settings-daemon already multiplies it by the primary monitor's
scale.

https://bugzilla.gnome.org/show_bug.cgi?id=755099
2015-10-04 14:17:14 +08:00
Jonas Ådahl
e84f694668 wayland: Don't scale XWayland pointer cursor sprites
We don't have any way of knowing what the intended size of a XWayland
cursor is supposed to be, so lets do what we do with regular XWayland
surfaces and don't scale them. The result is that cursor sprites of
HiDPI aware X11 clients will show correctly, but non-aware clients may
have tiny cursor sprites.

https://bugzilla.gnome.org/show_bug.cgi?id=755099
2015-10-04 14:17:14 +08:00
Carlos Garnacho
b18542f2b6 wayland: Avoid resending new data offers on intra-client focus changes
Each keyboard focus change ends up calling the MetaWaylandDataDevice
counterpart, we don't need though to notify the current selection
again. In order to fix this, keep track of the current client, and
only emit the relevant signals when the focus switches to another
client.

The situations where wl_data_device.selection were emitted during
focus changes between surfaces of the same client was inocuous most
of the times, although it's prone to inducing confusing behavior
on context menu clipboard actions, as the closing menu triggers a
focus change, which triggers a whole new wl_data_offer being created
and given on wl_data_device.selection, at a time where there's already
ongoing requests on the previous data offer.

https://bugzilla.gnome.org/show_bug.cgi?id=754357
2015-10-02 12:21:17 +02:00
Carlos Garnacho
da0aac665f xwayland: Protect against crash on x11->wayland transfer cancellation
If the transfer is cancelled, the X11SelectionData will be cleared from
the MetaSelectionBridge, although x11_data_write_cb() was invariably
expecting it to be non-NULL.

If the write was cancelled, all the actions done in x11_data_write_cb()
are moot, so just return early. If there's other errors happening
(eg. "connection closed" if the target client happens to crash), we
should still attempt at clearing the data anyway.

https://bugzilla.gnome.org/show_bug.cgi?id=754357
2015-10-02 12:21:17 +02:00
Jonas Ådahl
8b0b0cf028 MetaWaylandSurface: Don't assume a toplevel always have a MetaWindow
When committing a toplevel surface we might no longer have a MetaWindow
associated with it. The reason may vary but some are: a popup was
dismissed, the client attached and committed a NULL buffer to a
wl_surface with the wl_shell_surface role, the client committed a
buffer to a wl_surface which previously had an toplevel window role
which extension object was destroyed.

https://bugzilla.gnome.org/show_bug.cgi?id=755490
2015-09-29 09:09:57 +08:00
Carlos Garnacho
6f64d6b0aa wayland: Check the drag focus before processing XDND dest-side messages
If the drag dest surface suddenly disappears, we may find ourselves
processing an XdndPosition message that was sent before the X11 drag
source had an opportunity to find out.

In that case mutter does know, so double check before processing the
messages.
2015-09-28 16:22:54 +02:00
Carlos Garnacho
ebeca983c7 wayland: Improve transformation of the UTF8_STRING atom to mimetype
We try to translate the atom with its corresponding mimetype both back
and forth, which actually breaks if the X11 client chose to announce the
mimetype atom. To do the translation properly, keep track on whether the
source announced the UTF8_STRING atom, and reply back with this only if
that happened.
2015-09-28 16:22:43 +02:00
Carlos Garnacho
cf88675807 wayland: Fix weak ref tracking on data sources
We may get a NULL one here, and we're wrongly attempting to remove
the old weak ref from the new data source object.
2015-09-28 16:22:32 +02:00
Carlos Garnacho
405f1ce3d0 wayland: Avoid use of struct data after destruction
data_device_end_drag_grab() will destroy the MetaWaylandDragGrab struct,
so we definitely must not use it after destruction.
2015-09-28 16:22:18 +02:00
Colin Walters
6190ae3873 window: Remove invalid (transfer) annnotations
This tripped a new g-i warning; see
https://bugzilla.gnome.org/show_bug.cgi?id=752047
2015-09-27 16:42:01 -04:00
Rui Matos
69c267b142 xwayland: Fix windows disappearing on reparenting
If the wayland surface isn't available yet when we process the
WL_SURFACE_ID ClientMessage, we schedule a later function to try the
association again after we get a chance to process wayland requests.

This works fine except on cases where the MetaWindow already had a
previous surface attached (i.e. when the xwindow is reparented) since
we only break the existing association on the later function which
means that when processing the old surface's destruction we destroy
the MetaWindow and cancel the pending later function leaving us
without a MetaWindow and an invisible surface.

Fix this by detaching the old surface as soon as possible so that the
MetaWindow survives.

https://bugzilla.gnome.org/show_bug.cgi?id=743339
2015-09-25 19:09:48 +02:00
Rui Matos
9abc071283 backend-x11: Fallback to a default keymap if getting it from X fails
This shouldn't fail but apparently sometimes it does and in that case
having a possibly wrong idea of the keymap is still better than
crashing.

https://bugzilla.gnome.org/show_bug.cgi?id=754979
2015-09-25 19:09:48 +02:00
Jonas Ådahl
a9df4bb81a wayland: Scale saved rect changing monitor scale
The saved rect is used to restore a saved window size. We need to
update this when the window is moved to a monitor with different scale,
so that if we unmaximize a window which was moved to a different
monitor while maximized (for example when unplugged) will restore to
the correct size.

https://bugzilla.gnome.org/show_bug.cgi?id=755097
2015-09-24 11:39:37 +08:00
Jonas Ådahl
bc9e63d3db wayland: Scale unconstrained rect changing monitor scale
When a window is moved across monitors with different scales, its
rectangle is scaled accordingly. We also need to scale the
unconstrained_rect rectangle, so that moving a window via
meta_window_move_resize() which uses the unconstrained_rect.

https://bugzilla.gnome.org/show_bug.cgi?id=755097
2015-09-24 11:39:37 +08:00
Florian Müllner
5b5ceede2b wayland: Fix variable declaration
Storage class always goes first.
2015-09-24 03:08:23 +02:00
Florian Müllner
4e63c95c02 testboxes: Don't avoid parameter list 2015-09-24 03:08:23 +02:00
Florian Müllner
67d3a7a2d7 meta-monitor-manager: Remove bogus condition from check
An unsigned number is never smaller than 0, so we don't have to
check for it.
2015-09-24 03:08:23 +02:00
Florian Müllner
bc00f118f3 Avoid shadowing existing variables 2015-09-24 03:08:22 +02:00
Florian Müllner
5801b5518f Annotate functions to improve compiler diagnostics 2015-09-24 03:01:51 +02:00
Florian Müllner
25a796afc6 Fix constness warnings 2015-09-24 03:01:51 +02:00
Florian Müllner
27b37407d0 Don't duplicate declarations from G_DEFINE_TYPE 2015-09-24 03:01:51 +02:00
Jonas Ådahl
e23e697043 wayland: Fix output destroyed callback vfunc type
It is not a callback on a parameter signal, and get no GParamSpec passed
to it. This fixes a crash when a surface is on a destroyed output.

https://bugzilla.gnome.org/show_bug.cgi?id=755096
2015-09-24 08:08:41 +08:00
Florian Müllner
35729e8659 Bump version to 3.18.0
Update NEWS.
2015-09-21 21:52:14 +02:00
Rūdolfs Mazurs
dc7e665de9 Updated Latvian translation 2015-09-20 18:53:28 +03:00
Rūdolfs Mazurs
2e3bfd1a11 Updated Latvian translation 2015-09-20 18:51:51 +03:00
Jonas Ådahl
b7aca07844 Revert "launcher: simplify getting session dbus proxy"
Signals are sent to a specific ID, so we can't use "self" here. After
this revert, VT switching works again.

This reverts commit 8e22bf5bc9.

https://bugzilla.gnome.org/show_bug.cgi?id=753434
2015-09-17 12:17:45 +08:00
Florian Müllner
dc780d2c44 launcher: Don't pass variable as format string
We know the variable only contains one or another string literal,
but keep compilers happy as well.
2015-09-16 17:38:10 +02:00
Florian Müllner
c49b284643 Bump version to 3.17.92
Update NEWS.
2015-09-16 17:19:56 +02:00
Jonas Ådahl
0373b854c1 MetaCursorRenderer: Rely on update_cursor for redrawing
Calling queue_redraw() in _force_update() is not needed because
update_cursor() will do this when needed, i.e. when switching between
hardware cursor and texture cursor, or when drawing with texture cursor.

There is also no need to force _native_force_update() because
update_cursor() will cover this as well when needed. When not changing
cursor but only the gbm_bo, the "dirty" boolean on the gbm_bo will
trigger a redraw.

https://bugzilla.gnome.org/show_bug.cgi?id=744932
2015-09-13 21:26:22 +08:00
Jonas Ådahl
5d837a5c85 wayland: Support sending wl_surface.enter/leave to cursor surfaces
Support notifying clients about what outputs their cursor surfaces are
on so that they can attach appropriately scaled buffers to them.

https://bugzilla.gnome.org/show_bug.cgi?id=744932
2015-09-13 21:26:22 +08:00
Jonas Ådahl
79c86ae890 Support scaling of cursor sprites given what output they are on
This commits refactors cursor handling code and plugs in logic so that
cursor sprites changes appearance as it moves across the screen.
Renderers are adapted to handle the necessary functionality.

The logic for changing the cursor sprite appearance is done outside of
MetaCursorSprite, and actually where depends on what type of cursor it
is. In mutter we now have two types of cursors that may have their
appearance changed:

 - Themed cursors (aka root cursors)
 - wl_surface cursors

Themed cursors are created by MetaScreen and when created, when
applicable(*), it will extend the cursor via connecting to a signal
which is emitted everytime the cursor is moved. The signal handler will
calculate the expected scale given the monitor it is on and reload the
theme in a correct size when needed.

wl_surface cursors are created when a wl_surface is assigned the
"cursor" role, i.e. when a client calls wl_pointer.set_cursor. A
cursor role object is created which is connected to the cursor object
by the position signal, and will set a correct texture scale given what
monitor the cursor is on and what scale the wl_surface's active buffer
is in. It will also push new buffers to the same to the cursor object
when new ones are committed to the surface.

This commit also makes texture loading lazy, since the renderer doesn't
calculate a rectangle when the cursor position changes.

The native backend is refactored to be triple-buffered; see the comment
in meta-cursor-renderer-native.c for further explanations.

* when we are running as a Wayland compositor

https://bugzilla.gnome.org/show_bug.cgi?id=744932
2015-09-13 21:26:22 +08:00
Jonas Ådahl
7c7cf91c32 wayland: Move cursor surface role to meta-wayland-pointer.c
The wl_pointer assigns a role to a wl_surface, so it makes sense to put
the related logic there.

https://bugzilla.gnome.org/show_bug.cgi?id=744932
2015-09-13 21:26:22 +08:00
Jonas Ådahl
e407f5bbae MetaCursorSprite: Squash MetaCurorImage into MetaCursorSprite
It fills little purpose on separating into a MetaCursorImage struct, so
lets squash in the three fields into the MetaCursorSprite object.

https://bugzilla.gnome.org/show_bug.cgi?id=744932
2015-09-13 21:26:22 +08:00
Jonas Ådahl
8900bd2f5c backends/x11: Draw our own cursor sprite when running nested
Use a specialized cursor renderer when running as a nested Wayand
compositor. This new renderer sets an empty X11 cursor and draws the
cursor as part of the stage using the generic cursor renderer drawing
path.

https://bugzilla.gnome.org/show_bug.cgi?id=744932
2015-09-13 21:26:22 +08:00
Jonas Ådahl
83c17134f1 wayland: GObject:ify surface roles
Make a surface roles into objects with vfuncs for things where there
before was a big switch statement. The declaration and definition
boilerplate is hidden behind C macros.

https://bugzilla.gnome.org/show_bug.cgi?id=744932
2015-09-13 21:24:58 +08:00
Jonas Ådahl
8e5fb03611 MetaWaylandSurface: Don't respond to frame callback when role unassigned
If a surface doesn't have a role, the compositor will not know how, if
or when it will be painted. By adding it to the compositor frame
callback list, the compositor will respond to the client that the
surface has been drawn already which might not be true.

Instead, queue the frame callback in a list that is then processed when
the surface gets a role assigned. The compositor may then, given the
role the surface got, queue the frame callback accordingly.

https://bugzilla.gnome.org/show_bug.cgi?id=744932
2015-09-13 21:24:58 +08:00
Jonas Ådahl
dece49b53d wayland: Introduce XWayland surface role
Being a "XWayland window" should be considered equivalent to a role,
even though it is not part of any protocol anywhere. The commit doesn't
have any functional difference, but just makes it clear that an
wl_surface managed by XWayland have the same type of special casing as
surface roles as defined by the Wayland protocol.

As the semantics are more explicit given the role is defined, a comment
explaining why the semantics need to be how they are was added.

https://bugzilla.gnome.org/show_bug.cgi?id=744932
2015-09-13 21:24:58 +08:00
Olivier Fourdan
443d579d40 wayland: do not crash if the surface is gone
If a queued event is being processed after the surface is
destroyed, trying to access the window associated with the surface
will lead to a segmentation fault.

This patch avoids the crash by first checking if the surface is not null.

https://bugzilla.gnome.org/show_bug.cgi?id=754715
2015-09-09 09:30:14 +02:00
Ting-Wei Lan
5066eaf691 build: Fix non-wayland build
This fixes build error caused by commit 614d6bd. We can simply remove
the usage of meta-wayland.c functions in non-wayland build because
META_BACKEND_X11_MODE_NESTED is only used in wayland.

https://bugzilla.gnome.org/show_bug.cgi?id=753948
2015-09-08 01:50:03 +08:00
Javier Jardón
6ea7fa9973 xwayland: Add missing include
https://bugzilla.gnome.org/show_bug.cgi?id=754621
2015-09-07 14:13:48 +01:00
Marek Chalupa
79f755bf0f launcher: find the right drm device
Instead of hard-coding /dev/dri/card0, find the device
that has boot_vga flag set or has been explicitly
assigned a seat id other than seat0

https://bugzilla.gnome.org/show_bug.cgi?id=753434
2015-09-07 08:42:21 -04:00
Marek Chalupa
1845bfe1b6 launcher: refactor handling errors in meta_launcher_new
Fill in missing error checks and use g_error, since any
error in this phase would lead to crash later anyway.
This way we'll at least know what went wrong.

Although it was not the patch's original intention, it fixes
https://bugzilla.gnome.org/show_bug.cgi?id=754520

https://bugzilla.gnome.org/show_bug.cgi?id=753434
2015-09-07 08:40:49 -04:00
Marek Chalupa
8e22bf5bc9 launcher: simplify getting session dbus proxy
Use path "/org/freedesktop/login1/session/self" instead of
getting session id and building the path manually

https://bugzilla.gnome.org/show_bug.cgi?id=753434
2015-09-07 08:40:20 -04:00
Marek Chalupa
c13ddafdb8 native: remove obsolete comment
There's not weston-launch anymore

https://bugzilla.gnome.org/show_bug.cgi?id=753434
2015-09-07 08:39:38 -04:00
Jonas Ådahl
94513726de wayland: Clean up surface role assignment
Use a better name, use GNOME conventions for error handling, open code the
client error reporting and send the error to the correct resource.
wl_subcompositor doesn't have a role error yet, so continue use some
other error. The only effect of this is error received in the client will
be a bit confusing, it will still be disconnected.

https://bugzilla.gnome.org/show_bug.cgi?id=754215
2015-09-07 17:41:14 +08:00
Ting-Wei Lan
0aa4c4d43e build: Fix return value in meta-background.c
https://bugzilla.gnome.org/show_bug.cgi?id=754545
2015-09-04 11:47:34 +08:00
Owen W. Taylor
e3db4ab16a Avoid declaring variables in for loop to avoid upsetting older GCC
Older GCC only allows "for (int i" in explicit c99 mode - there's probably
no reason that we can't enable that, but avoiding the construct for
a fast fix.
2015-09-03 16:13:50 -04:00
Owen W. Taylor
614d6bd0f8 Nested X11: use KeymapNotify events to fix key state on FocusIn
If the user Alt-Tabs out of the window, we will be left thinking
the Alt key is still pressed since we don't see a release for it.

Solve this and other related issues for the nested X11 compositor
by selecting for KeymapStateMask which causes a KeymapNotify event
to be sent after each FocusIn, and when we get these events, update
the internal XKB state and send any necessary modifiers events to
clients.

https://bugzilla.gnome.org/show_bug.cgi?id=753948
2015-09-03 16:02:25 -04:00
Ray Strode
1d56d50fcd background: paint color matte for scaled and centered backgrounds
Some backgrounds don't fully fill the screen.  For those backgrounds
it's important to paint a color behind them to fill in the gaps.

This commit checks whether or not the background image textures take
up the entire monitor, and in the event they don't, draws a color
behind them (such as it would do if the background were
translucent).

https://bugzilla.gnome.org/show_bug.cgi?id=754476
2015-09-03 15:14:15 -04:00
Ray Strode
0ffd4254d9 background: simplify conditional in meta_background_get_texture
meta_background_get_texture only draws the bottom image texture
if
   1) the blend factor leaves the top image translucent
   or
   2) the top image is translucent from alpha

The latter case doesn't actually matter since we're using REPLACE
on the top image texture.

This commit drops the unnecessary check for the second case and
applies demorgans law to the conditional for clarity.

https://bugzilla.gnome.org/show_bug.cgi?id=754476
2015-09-03 15:14:15 -04:00
Florian Müllner
36eee04a21 Bump version to 3.17.91
Update NEWS.
2015-09-03 15:26:03 +02:00
Jonas Ådahl
d3fdaa3232 MetaCursorSprite: Put renderer specific code in the renderer
There were lots of code handling the native renderer specific cases;
move these parts to the renderer. Note that this causes the X11 case to
always generate the texture which is a waste of memory, but his
regression will be fixed in a following commit.

The lazy loading of the texture was removed because it was eventually
always loaded anyway indirectly by the renderer to calculate the
current rect.

https://bugzilla.gnome.org/show_bug.cgi?id=744932
2015-08-28 09:55:12 +08:00
Jonas Ådahl
165050f8f9 backends: Get rid of meta-cursor-private.h
There is nothing special about the private API which only consists of
getters for renderer specific backing buffer. Lets them to the regular
.h file and treat them as part of the normal API.

https://bugzilla.gnome.org/show_bug.cgi?id=744932
2015-08-28 09:54:57 +08:00
Jonas Ådahl
68279e8a08 MetaWaylandPointer: Don't keep our own MetaCursorTracker pointer
There is no reason to, we can just retrieve it every time we need it.

https://bugzilla.gnome.org/show_bug.cgi?id=744932
2015-08-28 09:52:30 +08:00
Jonas Ådahl
cd1ce2cb0a MetaWaylandSurface: Make it a GObject
This way we can add signals and weak references without relying on
wl_signal, wl_listener etc.

https://bugzilla.gnome.org/show_bug.cgi?id=744932
2015-08-28 09:52:30 +08:00
Jonas Ådahl
b01f95cfdd Make MetaCursorSprite a GObject
To easier track lifetime and utilize other GObject features, make
MetaCursorSprite a GObject.

https://bugzilla.gnome.org/show_bug.cgi?id=744932
2015-08-28 09:52:30 +08:00
Jonas Ådahl
4b667d1e09 Rename MetaCursorReference to MetaCursorSprite
It isn't really a reference to a MetaCursor enum, but a reference
counted cursor sprite, and enum value.

https://bugzilla.gnome.org/show_bug.cgi?id=744932
2015-08-28 09:52:30 +08:00
Piotr Drąg
fe8454d13f Updated Polish translation 2015-08-26 18:51:15 +02:00
Chao-Hsiung Liao
53a6d16891 Updated Chinese (Taiwan) translation 2015-08-26 12:50:50 +00:00
Jonas Ådahl
e76c3ecb00 wayland/pointer-gestures: Send error on protocol version mismatch
When a client binds an incompatible version, we should terminate it.
This check should only be there for the unstable version, as once it is
declared stable and renamed, future versions will be backward compatible.

https://bugzilla.gnome.org/show_bug.cgi?id=753855
2015-08-22 00:04:33 +08:00
83 changed files with 5369 additions and 8392 deletions

83
NEWS
View File

@@ -1,3 +1,86 @@
3.18.4
======
* Fix mouse cursor disappearing in some multi-monitor setups [Rui; #763159]
* Do not assert on non-fatal runtime errors [Florian; #765058]
Contributors:
Rui Matos, Florian Müllner
Translations:
Cédric Valmary [oc]
3.18.3
======
* Fix initialization of bypass compositor hint [Rui; #758544]
* Fix crash when initial cursor position is not on a monitor [Marek; #756698]
* Fix crash when more CRTs are enabled than outputs connected [Rui; #751638]
* Fix crash during XWayland initialization [Marek; #751845]
* Ensure to send a ConfigureNotify to just mapped windows [Rui; #759492]
Contributors:
Marek Chalupa, Rui Matos, Jasper St. Pierre
3.18.2
======
* Misc. crash fixes [Jonas, Rui; #756675, #756660, #757148, #756796]
* Fix modifiers-only input source switching on Ubuntu [Alberts; #756543]
* Exit cleanly on initialization errors [Owen; #757311]
Contributors:
Jonas Ådahl, Rui Matos, Alberts Muktupāvels, Florian Müllner, Owen W. Taylor
Translations:
Daniel Șerbănescu [ro]
3.18.1
======
* Misc. crash fixes [Jonas, Rui, Carlos, Owen, Florian; #755096, #754979,
#755490, #754357, #745785, #756642]
* Improve HiDPI support on wayland [Jonas; #755097]
* Fix doubly-scaled cursor on XWayland HiDPI [Jonas; #755099]
* Stop hiding titlebar buttons in dialogs [Florian; #641630]
* Add support for fullscreen/unfullscreen animations [Cosimo; #707248]
* Misc. bug fixes [Rui, Colin, Florian; #743339, #752047, #756074, #756649]
Contributors:
Jonas Ådahl, Cosimo Cecchi, Carlos Garnacho, Rui Matos, Florian Müllner,
Jasper St. Pierre, Colin Walters, Owen W. Taylor
3.18.0
======
* Misc. fixes [Florian, Jonas; #753434]
Contributors:
Jonas Ådahl, Florian Müllner
Translations:
Rūdolfs Mazurs [lv]
3.17.92
=======
* Don't omit the background color for backgrounds that don't fill the screen
[Ray; #754476]
* Fix up key state on FocusIn when running nested [Owen; #753948]
* Find the right DRM device instead of hardcoding card0 [Marek; #753434]
* Scale cursor on HiDPI screens [Jonas; #744932]
* Misc. fixes and cleanups [Lan, Jonas, Javier, Olivier; #754545, #754215,
#754621, #754715]
Contributors:
Jonas Ådahl, Marek Chalupa, Olivier Fourdan, Javier Jardón, Ting-Wei Lan,
Ray Strode, Owen W. Taylor
3.17.91
=======
* Send error on pointer-gesture protocol version mismatch [Jonas; #753855]
* Misc. cleanups [Jonas; #744932]
Contributors:
Jonas Ådahl
Translations:
Chao-Hsiung Liao [zh_TW], Piotr Drąg [pl]
3.17.90
=======
* Fix glitch with some fullscreen apps [Rui; #753020]

View File

@@ -1,8 +1,8 @@
AC_PREREQ(2.62)
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [17])
m4_define([mutter_micro_version], [90])
m4_define([mutter_minor_version], [18])
m4_define([mutter_micro_version], [4])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])

1867
po/lv.po

File diff suppressed because it is too large Load Diff

3420
po/oc.po

File diff suppressed because it is too large Load Diff

View File

@@ -15,8 +15,8 @@ msgid ""
msgstr ""
"Project-Id-Version: mutter\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-03-05 00:23+0100\n"
"PO-Revision-Date: 2015-03-05 00:24+0100\n"
"POT-Creation-Date: 2015-08-26 18:49+0200\n"
"PO-Revision-Date: 2015-08-26 18:50+0200\n"
"Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n"
"Language-Team: Polish <gnomepl@aviary.pl>\n"
"Language: pl\n"
@@ -285,9 +285,9 @@ msgid ""
"\"Windows key\" on PC hardware. It's expected that this binding either the "
"default or set to the empty string."
msgstr ""
"Ten klawisz inicjuje tryb \"overlay\", który jest połączeniem podglądu okien "
"i systemu uruchamiania programów. Domyślnie jest przeznaczony do powiązania "
"z klawiszem \"Windows\" na komputerach typu PC. Ustawienie tego powiązania "
"Ten klawisz inicjuje tryb overlay, który jest połączeniem podglądu okien i "
"systemu uruchamiania programów. Domyślnie jest przeznaczony do powiązania z "
"klawiszem Windows na komputerach typu PC. Ustawienie tego powiązania "
"powinno być domyślne lub puste."
#: ../data/org.gnome.mutter.gschema.xml.in.h:3
@@ -300,9 +300,9 @@ msgid ""
"attached to the titlebar of the parent window and are moved together with "
"the parent window."
msgstr ""
"Jeśli wynosi \"true\", to modalne okna dialogowe pojawiają się dołączone do "
"paska tytułowego okna nadrzędnego zamiast posiadać oddzielne paski tytułowe "
"i są przenoszone razem z nim."
"Jeśli wynosi wartość „true, to modalne okna dialogowe pojawiają się "
"dołączone do paska tytułowego okna nadrzędnego zamiast posiadać oddzielne "
"paski tytułowe i są przenoszone razem z nim."
#: ../data/org.gnome.mutter.gschema.xml.in.h:5
msgid "Enable edge tiling when dropping windows on screen edges"
@@ -332,7 +332,7 @@ msgid ""
"gnome.desktop.wm.preferences)."
msgstr ""
"Określa, czy obszary robocze są zarządzane dynamicznie, czy istnieje "
"statyczna liczba obszarów (określona przez klucz \"num-workspaces\" w org."
"statyczna liczba obszarów (określona przez klucz num-workspaces w org."
"gnome.desktop.wm.preferences)."
#: ../data/org.gnome.mutter.gschema.xml.in.h:9
@@ -369,9 +369,9 @@ msgid ""
"the focus will not be changed immediately when entering a window, but only "
"after the pointer stops moving."
msgstr ""
"Jeśli jest ustawione na wartość \"true\", a tryb aktywności to \"sloppy\" "
"lub \"mouse\", to aktywność nie będzie zmieniana od razu po przejściu do "
"okna, ale dopiero po zatrzymaniu ruchu kursora."
"Jeśli jest ustawione na wartość true, a tryb aktywności to sloppy” lub "
"mouse, to aktywność nie będzie zmieniana od razu po przejściu do okna, ale "
"dopiero po zatrzymaniu ruchu kursora."
#: ../data/org.gnome.mutter.gschema.xml.in.h:15
msgid "Draggable border width"
@@ -409,7 +409,7 @@ msgid ""
"When true, the new windows will always be put in the center of the active "
"screen of the monitor."
msgstr ""
"Jeśli wynosi \"true\", to nowe okna będą zawsze umieszczane na środku "
"Jeśli wynosi wartość „true, to nowe okna będą zawsze umieszczane na środku "
"aktywnego ekranu monitora."
#: ../data/org.gnome.mutter.gschema.xml.in.h:21
@@ -468,22 +468,22 @@ msgstr "Przełączenie na 11. konsolę wirtualną"
msgid "Switch to VT 12"
msgstr "Przełączenie na 12. konsolę wirtualną"
#: ../src/backends/meta-monitor-manager.c:364
#: ../src/backends/meta-monitor-manager.c:500
msgid "Built-in display"
msgstr "Wbudowany ekran"
#: ../src/backends/meta-monitor-manager.c:391
#: ../src/backends/meta-monitor-manager.c:526
msgid "Unknown"
msgstr "Nieznany"
#: ../src/backends/meta-monitor-manager.c:393
#: ../src/backends/meta-monitor-manager.c:528
msgid "Unknown Display"
msgstr "Nieznany ekran"
#. TRANSLATORS: this is a monitor vendor name, followed by a
#. * size in inches, like 'Dell 15"'
#.
#: ../src/backends/meta-monitor-manager.c:401
#: ../src/backends/meta-monitor-manager.c:536
#, c-format
msgid "%s %s"
msgstr "%s %s"
@@ -496,7 +496,7 @@ msgid ""
"Another compositing manager is already running on screen %i on display \"%s"
"\"."
msgstr ""
"Inny menedżer składania jest już uruchomiony na podekranie %i ekranu \"%s\"."
"Inny menedżer składania jest już uruchomiony na podekranie %i ekranu „%s”."
#: ../src/core/bell.c:185
msgid "Bell event"
@@ -505,7 +505,7 @@ msgstr "Zdarzenie sygnału dźwiękowego"
#: ../src/core/delete.c:127
#, c-format
msgid "“%s” is not responding."
msgstr "Okno \"%s\" nie odpowiada."
msgstr "Okno „%s” nie odpowiada."
#: ../src/core/delete.c:129
msgid "Application is not responding."
@@ -525,11 +525,10 @@ msgstr "_Czekaj"
msgid "_Force Quit"
msgstr "_Zakończ"
#: ../src/core/display.c:562
#: ../src/core/display.c:563
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr ""
"Otwarcie połączenia z ekranem \"%s\" systemu X Window się nie powiodło\n"
msgstr "Otwarcie połączenia z ekranem „%s” systemu X Window się nie powiodło\n"
#: ../src/core/main.c:176
msgid "Disable connection to session manager"
@@ -573,7 +572,7 @@ msgid ""
"PARTICULAR PURPOSE.\n"
msgstr ""
"mutter %s\n"
"Copyright (C) 2001-%d Havoc Pennington, Red Hat, Inc., oraz inni\n"
"Copyright (C) 2001%d Havoc Pennington, Red Hat, Inc., oraz inni\n"
"Niniejszy program jest wolnym oprogramowaniem, aby poznać warunki, pod\n"
"jakimi dopuszczalne jest kopiowanie programu, zajrzyj do jego źródeł.\n"
"Na program nie udziela się ŻADNYCH GWARANCJI, nawet domyślnej gwarancji\n"
@@ -598,13 +597,13 @@ msgid ""
"Display \"%s\" already has a window manager; try using the --replace option "
"to replace the current window manager."
msgstr ""
"Na ekranie \"%s\" działa już menedżer okien. Aby zastąpić działającego "
"Na ekranie „%s” działa już menedżer okien. Aby zastąpić działającego "
"menedżera okien, proszę spróbować użyć opcji --replace."
#: ../src/core/screen.c:607
#, c-format
msgid "Screen %d on display '%s' is invalid\n"
msgstr "Podekran %d ekranu \"%s\" jest nieprawidłowy\n"
msgstr "Podekran %d ekranu „%s” jest nieprawidłowy\n"
#: ../src/core/util.c:118
msgid "Mutter was compiled without support for verbose mode\n"
@@ -616,7 +615,7 @@ msgid ""
"These windows do not support &quot;save current setup&quot; and will have to "
"be restarted manually next time you log in."
msgstr ""
"Te okna nie obsługują opcji zapisu obecnego stanu (\"save current setup\"), "
"Te okna nie obsługują opcji zapisu obecnego stanu (save current setup), "
"więc przy następnym zalogowaniu będą musiały zostać uruchomione ręcznie."
#: ../src/x11/window-props.c:549

3395
po/ro.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -10,7 +10,7 @@ msgstr ""
"Project-Id-Version: metacity 3.3.4\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
"product=mutter&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2015-02-20 23:22+0000\n"
"POT-Creation-Date: 2015-07-21 10:52+0000\n"
"PO-Revision-Date: 2015-02-21 16:33+0800\n"
"Last-Translator: Chao-Hsiung Liao <j_h_liau@yahoo.com.tw>\n"
"Language-Team: Chinese (Taiwan) <zh-l10n@lists.linux.org.tw>\n"
@@ -439,22 +439,22 @@ msgstr "切換至 VT 11"
msgid "Switch to VT 12"
msgstr "切換至 VT 12"
#: ../src/backends/meta-monitor-manager.c:364
#: ../src/backends/meta-monitor-manager.c:500
msgid "Built-in display"
msgstr "內建顯示"
#: ../src/backends/meta-monitor-manager.c:391
#: ../src/backends/meta-monitor-manager.c:526
msgid "Unknown"
msgstr "不明"
#: ../src/backends/meta-monitor-manager.c:393
#: ../src/backends/meta-monitor-manager.c:528
msgid "Unknown Display"
msgstr "不明的顯示器"
#. TRANSLATORS: this is a monitor vendor name, followed by a
#. * size in inches, like 'Dell 15"'
#.
#: ../src/backends/meta-monitor-manager.c:401
#: ../src/backends/meta-monitor-manager.c:536
#, c-format
msgid "%s %s"
msgstr "%s %s"
@@ -462,7 +462,7 @@ msgstr "%s %s"
# FIXME: I'm still unclear about the meaning of XGetSelectionOwner -- Abel
#. This probably means that a non-WM compositor like xcompmgr is running;
#. * we have no way to get it to exit
#: ../src/compositor/compositor.c:456
#: ../src/compositor/compositor.c:451
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display \"%s"
@@ -496,14 +496,14 @@ msgstr "等待(_W)"
msgid "_Force Quit"
msgstr "強制結束(_F)"
#: ../src/core/display.c:562
#: ../src/core/display.c:563
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "無法開啟 X Window 畫面‘%s\n"
#: ../src/core/main.c:176
msgid "Disable connection to session manager"
msgstr "停用到作業階段管理程式的連線"
msgstr "停用到作業階段管理的連線"
#: ../src/core/main.c:182
msgid "Replace the running window manager"
@@ -1053,9 +1053,9 @@ msgstr "%s在 %s"
#~ msgid ""
#~ "\"%s\" found in configuration database is not a valid value for mouse "
#~ "button modifier\n"
#~ msgstr "組態資料庫中的“%s”設定值不是有效的滑鼠按鈕修改功能鍵\n"
#~ msgstr "設定資料庫中的“%s”設定值不是有效的滑鼠按鈕修改功能鍵\n"
#~ msgid ""
#~ "\"%s\" found in configuration database is not a valid value for "
#~ "keybinding \"%s\"\n"
#~ msgstr "組態資料庫中的“%s”不是按鍵組合“%s”的有效設定值\n"
#~ msgstr "設定資料庫中的“%s”不是按鍵組合“%s”的有效設定值\n"

View File

@@ -68,7 +68,6 @@ libmutter_la_SOURCES = \
backends/meta-barrier-private.h \
backends/meta-cursor.c \
backends/meta-cursor.h \
backends/meta-cursor-private.h \
backends/meta-cursor-tracker.c \
backends/meta-cursor-tracker-private.h \
backends/meta-cursor-renderer.c \
@@ -97,6 +96,8 @@ libmutter_la_SOURCES = \
backends/x11/meta-barrier-x11.h \
backends/x11/meta-cursor-renderer-x11.c \
backends/x11/meta-cursor-renderer-x11.h \
backends/x11/nested/meta-cursor-renderer-x11-nested.c \
backends/x11/nested/meta-cursor-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 \

View File

@@ -24,6 +24,8 @@
#include "config.h"
#include <stdlib.h>
#include <meta/meta-backend.h>
#include "meta-backend-private.h"
#include "meta-input-settings-private.h"
@@ -626,7 +628,10 @@ meta_clutter_init (void)
meta_create_backend ();
if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
g_error ("Unable to initialize Clutter.\n");
{
g_warning ("Unable to initialize Clutter.\n");
exit (1);
}
/*
* XXX: We cannot handle high dpi scaling yet, so fix the scale to 1

View File

@@ -1,66 +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/>.
*
* Author: Giovanni Campagna <gcampagn@redhat.com>
*/
#ifndef META_CURSOR_PRIVATE_H
#define META_CURSOR_PRIVATE_H
#include "meta-cursor.h"
#include <X11/Xcursor/Xcursor.h>
#include <cogl/cogl.h>
#ifdef HAVE_NATIVE_BACKEND
#include <gbm.h>
#endif
typedef struct {
CoglTexture2D *texture;
int hot_x, hot_y;
#ifdef HAVE_NATIVE_BACKEND
struct gbm_bo *bo;
#endif
} MetaCursorImage;
struct _MetaCursorReference {
int ref_count;
int current_frame;
XcursorImages *xcursor_images;
MetaCursor cursor;
MetaCursorImage image;
};
CoglTexture *meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor,
int *hot_x,
int *hot_y);
#ifdef HAVE_NATIVE_BACKEND
struct gbm_bo *meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
int *hot_x,
int *hot_y);
#endif
gboolean meta_cursor_reference_is_animated (MetaCursorReference *self);
void meta_cursor_reference_tick_frame (MetaCursorReference *self);
guint meta_cursor_reference_get_current_frame_time (MetaCursorReference *self);
#endif /* META_CURSOR_PRIVATE_H */

View File

@@ -25,7 +25,6 @@
#include "config.h"
#include "meta-cursor-renderer.h"
#include "meta-cursor-private.h"
#include <meta/meta-backend.h>
#include <meta/util.h>
@@ -38,9 +37,8 @@
struct _MetaCursorRendererPrivate
{
int current_x, current_y;
MetaRectangle current_rect;
MetaCursorReference *displayed_cursor;
MetaCursorSprite *displayed_cursor;
gboolean handled_by_backend;
};
typedef struct _MetaCursorRendererPrivate MetaCursorRendererPrivate;
@@ -48,27 +46,33 @@ typedef struct _MetaCursorRendererPrivate MetaCursorRendererPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRenderer, meta_cursor_renderer, G_TYPE_OBJECT);
static void
queue_redraw (MetaCursorRenderer *renderer)
queue_redraw (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite)
{
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
MetaBackend *backend = meta_get_backend ();
ClutterActor *stage = meta_backend_get_stage (backend);
CoglTexture *texture;
MetaRectangle rect = { 0 };
if (cursor_sprite)
rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite);
/* During early initialization, we can have no stage */
if (!stage)
return;
if (priv->displayed_cursor && !priv->handled_by_backend)
texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, NULL, NULL);
if (cursor_sprite && !priv->handled_by_backend)
texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
else
texture = NULL;
meta_stage_set_cursor (META_STAGE (stage), texture, &priv->current_rect);
meta_stage_set_cursor (META_STAGE (stage), texture, &rect);
}
static gboolean
meta_cursor_renderer_real_update_cursor (MetaCursorRenderer *renderer)
meta_cursor_renderer_real_update_cursor (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite)
{
return FALSE;
}
@@ -84,34 +88,50 @@ meta_cursor_renderer_init (MetaCursorRenderer *renderer)
{
}
MetaRectangle
meta_cursor_renderer_calculate_rect (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite)
{
MetaCursorRendererPrivate *priv =
meta_cursor_renderer_get_instance_private (renderer);
CoglTexture *texture;
int hot_x, hot_y;
int width, height;
float texture_scale;
texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
if (!texture)
return (MetaRectangle) { 0 };
meta_cursor_sprite_get_hotspot (cursor_sprite, &hot_x, &hot_y);
texture_scale = meta_cursor_sprite_get_texture_scale (cursor_sprite);
width = cogl_texture_get_width (texture);
height = cogl_texture_get_height (texture);
return (MetaRectangle) {
.x = (int)roundf (priv->current_x - (hot_x * texture_scale)),
.y = (int)roundf (priv->current_y - (hot_y * texture_scale)),
.width = (int)roundf (width * texture_scale),
.height = (int)roundf (height * texture_scale),
};
}
static void
update_cursor (MetaCursorRenderer *renderer)
update_cursor (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite)
{
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
gboolean handled_by_backend;
gboolean should_redraw = FALSE;
if (priv->displayed_cursor)
{
CoglTexture *texture;
int hot_x, hot_y;
if (cursor_sprite)
meta_cursor_sprite_prepare_at (cursor_sprite,
priv->current_x,
priv->current_y);
texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, &hot_x, &hot_y);
priv->current_rect.x = priv->current_x - hot_x;
priv->current_rect.y = priv->current_y - hot_y;
priv->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (texture));
priv->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (texture));
}
else
{
priv->current_rect.x = 0;
priv->current_rect.y = 0;
priv->current_rect.width = 0;
priv->current_rect.height = 0;
}
handled_by_backend = META_CURSOR_RENDERER_GET_CLASS (renderer)->update_cursor (renderer);
handled_by_backend =
META_CURSOR_RENDERER_GET_CLASS (renderer)->update_cursor (renderer,
cursor_sprite);
if (handled_by_backend != priv->handled_by_backend)
{
priv->handled_by_backend = handled_by_backend;
@@ -122,7 +142,7 @@ update_cursor (MetaCursorRenderer *renderer)
should_redraw = TRUE;
if (should_redraw)
queue_redraw (renderer);
queue_redraw (renderer, cursor_sprite);
}
MetaCursorRenderer *
@@ -132,23 +152,25 @@ meta_cursor_renderer_new (void)
}
void
meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer,
MetaCursorReference *cursor)
meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite)
{
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
if (priv->displayed_cursor == cursor)
if (priv->displayed_cursor == cursor_sprite)
return;
priv->displayed_cursor = cursor_sprite;
priv->displayed_cursor = cursor;
update_cursor (renderer);
update_cursor (renderer, cursor_sprite);
}
void
meta_cursor_renderer_force_update (MetaCursorRenderer *renderer)
{
update_cursor (renderer);
queue_redraw (renderer);
MetaCursorRendererPrivate *priv =
meta_cursor_renderer_get_instance_private (renderer);
update_cursor (renderer, priv->displayed_cursor);
}
void
@@ -162,10 +184,10 @@ meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
priv->current_x = x;
priv->current_y = y;
update_cursor (renderer);
update_cursor (renderer, priv->displayed_cursor);
}
MetaCursorReference *
MetaCursorSprite *
meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer)
{
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
@@ -173,10 +195,27 @@ meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer)
return priv->displayed_cursor;
}
const MetaRectangle *
meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer)
#ifdef HAVE_WAYLAND
void
meta_cursor_renderer_realize_cursor_from_wl_buffer (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite,
struct wl_resource *buffer)
{
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
return &priv->current_rect;
MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_GET_CLASS (renderer);
if (renderer_class->realize_cursor_from_wl_buffer)
renderer_class->realize_cursor_from_wl_buffer (renderer, cursor_sprite, buffer);
}
#endif
void
meta_cursor_renderer_realize_cursor_from_xcursor (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite,
XcursorImage *xc_image)
{
MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_GET_CLASS (renderer);
if (renderer_class->realize_cursor_from_xcursor)
renderer_class->realize_cursor_from_xcursor (renderer, cursor_sprite, xc_image);
}

View File

@@ -26,6 +26,10 @@
#define META_CURSOR_RENDERER_H
#include <glib-object.h>
#include <X11/Xcursor/Xcursor.h>
#ifdef HAVE_WAYLAND
#include <wayland-server.h>
#endif
#include <meta/screen.h>
#include "meta-cursor.h"
@@ -38,21 +42,40 @@ struct _MetaCursorRendererClass
{
GObjectClass parent_class;
gboolean (* update_cursor) (MetaCursorRenderer *renderer);
gboolean (* update_cursor) (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite);
#ifdef HAVE_WAYLAND
void (* realize_cursor_from_wl_buffer) (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite,
struct wl_resource *buffer);
#endif
void (* realize_cursor_from_xcursor) (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite,
XcursorImage *xc_image);
};
GType meta_cursor_renderer_get_type (void) G_GNUC_CONST;
MetaCursorRenderer * meta_cursor_renderer_new (void);
void meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer,
MetaCursorReference *cursor);
void meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite);
void meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
int x, int y);
void meta_cursor_renderer_force_update (MetaCursorRenderer *renderer);
MetaCursorReference * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer);
const MetaRectangle * meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer);
MetaCursorSprite * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer);
MetaRectangle meta_cursor_renderer_calculate_rect (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite);
#ifdef HAVE_WAYLAND
void meta_cursor_renderer_realize_cursor_from_wl_buffer (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite,
struct wl_resource *buffer);
#endif
void meta_cursor_renderer_realize_cursor_from_xcursor (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite,
XcursorImage *xc_image);
#endif /* META_CURSOR_RENDERER_H */

View File

@@ -34,7 +34,7 @@ struct _MetaCursorTracker {
gboolean is_showing;
MetaCursorReference *displayed_cursor;
MetaCursorSprite *displayed_cursor;
/* Wayland clients can set a NULL buffer as their cursor
* explicitly, which means that we shouldn't display anything.
@@ -42,12 +42,12 @@ struct _MetaCursorTracker {
* determine an unset window cursor; we need an extra boolean.
*/
gboolean has_window_cursor;
MetaCursorReference *window_cursor;
MetaCursorSprite *window_cursor;
MetaCursorReference *root_cursor;
MetaCursorSprite *root_cursor;
/* The cursor from the X11 server. */
MetaCursorReference *xfixes_cursor;
MetaCursorSprite *xfixes_cursor;
};
struct _MetaCursorTrackerClass {
@@ -57,16 +57,16 @@ struct _MetaCursorTrackerClass {
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
XEvent *xevent);
void meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor);
void meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker);
void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor);
void meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
MetaCursorSprite *cursor_sprite);
void meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker);
void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
MetaCursorSprite *cursor_sprite);
void meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
int new_x,
int new_y);
MetaCursorReference * meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker);
MetaCursorSprite * meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker);
#endif

View File

@@ -43,7 +43,6 @@
#include <X11/extensions/Xfixes.h>
#include "meta-backend-private.h"
#include "meta-cursor-private.h"
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
@@ -54,7 +53,7 @@ enum {
static guint signals[LAST_SIGNAL];
static MetaCursorReference *
static MetaCursorSprite *
get_displayed_cursor (MetaCursorTracker *tracker)
{
MetaDisplay *display = meta_get_display ();
@@ -80,14 +79,14 @@ update_displayed_cursor (MetaCursorTracker *tracker)
static void
sync_cursor (MetaCursorTracker *tracker)
{
MetaCursorReference *displayed_cursor = get_displayed_cursor (tracker);
MetaCursorSprite *displayed_cursor = get_displayed_cursor (tracker);
if (tracker->displayed_cursor == displayed_cursor)
return;
g_clear_pointer (&tracker->displayed_cursor, meta_cursor_reference_unref);
g_clear_object (&tracker->displayed_cursor);
if (displayed_cursor)
tracker->displayed_cursor = meta_cursor_reference_ref (displayed_cursor);
tracker->displayed_cursor = g_object_ref (displayed_cursor);
update_displayed_cursor (tracker);
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
@@ -108,9 +107,9 @@ meta_cursor_tracker_finalize (GObject *object)
MetaCursorTracker *self = META_CURSOR_TRACKER (object);
if (self->displayed_cursor)
meta_cursor_reference_unref (self->displayed_cursor);
g_object_unref (self->displayed_cursor);
if (self->root_cursor)
meta_cursor_reference_unref (self->root_cursor);
g_object_unref (self->root_cursor);
G_OBJECT_CLASS (meta_cursor_tracker_parent_class)->finalize (object);
}
@@ -156,13 +155,13 @@ meta_cursor_tracker_get_for_screen (MetaScreen *screen)
}
static void
set_window_cursor (MetaCursorTracker *tracker,
gboolean has_cursor,
MetaCursorReference *cursor)
set_window_cursor (MetaCursorTracker *tracker,
gboolean has_cursor,
MetaCursorSprite *cursor_sprite)
{
g_clear_pointer (&tracker->window_cursor, meta_cursor_reference_unref);
if (cursor)
tracker->window_cursor = meta_cursor_reference_ref (cursor);
g_clear_object (&tracker->window_cursor);
if (cursor_sprite)
tracker->window_cursor = g_object_ref (cursor_sprite);
tracker->has_window_cursor = has_cursor;
sync_cursor (tracker);
}
@@ -184,28 +183,12 @@ meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
if (notify_event->subtype != XFixesDisplayCursorNotify)
return FALSE;
g_clear_pointer (&tracker->xfixes_cursor, meta_cursor_reference_unref);
g_clear_object (&tracker->xfixes_cursor);
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
return TRUE;
}
static MetaCursorReference *
meta_cursor_reference_take_texture (CoglTexture2D *texture,
int hot_x,
int hot_y)
{
MetaCursorReference *self;
self = g_slice_new0 (MetaCursorReference);
self->ref_count = 1;
self->image.texture = texture;
self->image.hot_x = hot_x;
self->image.hot_y = hot_y;
return self;
}
static void
ensure_xfixes_cursor (MetaCursorTracker *tracker)
{
@@ -215,6 +198,7 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
guint8 *cursor_data;
gboolean free_cursor_data;
CoglContext *ctx;
CoglError *error = NULL;
if (tracker->xfixes_cursor)
return;
@@ -256,17 +240,26 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
CLUTTER_CAIRO_FORMAT_ARGB32,
cursor_image->width * 4, /* stride */
cursor_data,
NULL);
&error);
if (free_cursor_data)
g_free (cursor_data);
if (error != NULL)
{
meta_warning ("Failed to allocate cursor sprite texture: %s\n", error->message);
cogl_error_free (error);
}
if (sprite != NULL)
{
MetaCursorReference *cursor = meta_cursor_reference_take_texture (sprite,
cursor_image->xhot,
cursor_image->yhot);
tracker->xfixes_cursor = cursor;
MetaCursorSprite *cursor_sprite = meta_cursor_sprite_new ();
meta_cursor_sprite_set_texture (cursor_sprite,
sprite,
cursor_image->xhot,
cursor_image->yhot);
cogl_object_unref (sprite);
tracker->xfixes_cursor = cursor_sprite;
}
XFree (cursor_image);
}
@@ -279,22 +272,22 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
CoglTexture *
meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker)
{
MetaCursorReference *cursor;
MetaCursorSprite *cursor_sprite;
g_return_val_if_fail (META_IS_CURSOR_TRACKER (tracker), NULL);
if (meta_is_wayland_compositor ())
{
cursor = tracker->displayed_cursor;
cursor_sprite = tracker->displayed_cursor;
}
else
{
ensure_xfixes_cursor (tracker);
cursor = tracker->xfixes_cursor;
cursor_sprite = tracker->xfixes_cursor;
}
if (cursor)
return meta_cursor_reference_get_cogl_texture (cursor, NULL, NULL);
if (cursor_sprite)
return meta_cursor_sprite_get_cogl_texture (cursor_sprite);
else
return NULL;
}
@@ -311,22 +304,22 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
int *x,
int *y)
{
MetaCursorReference *cursor;
MetaCursorSprite *cursor_sprite;
g_return_if_fail (META_IS_CURSOR_TRACKER (tracker));
if (meta_is_wayland_compositor ())
{
cursor = tracker->displayed_cursor;
cursor_sprite = tracker->displayed_cursor;
}
else
{
ensure_xfixes_cursor (tracker);
cursor = tracker->xfixes_cursor;
cursor_sprite = tracker->xfixes_cursor;
}
if (cursor)
meta_cursor_reference_get_cogl_texture (cursor, x, y);
if (cursor_sprite)
meta_cursor_sprite_get_hotspot (cursor_sprite, x, y);
else
{
if (x)
@@ -337,10 +330,10 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
}
void
meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor)
meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
MetaCursorSprite *cursor_sprite)
{
set_window_cursor (tracker, TRUE, cursor);
set_window_cursor (tracker, TRUE, cursor_sprite);
}
void
@@ -350,12 +343,12 @@ meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker)
}
void
meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor)
meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
MetaCursorSprite *cursor_sprite)
{
g_clear_pointer (&tracker->root_cursor, meta_cursor_reference_unref);
if (cursor)
tracker->root_cursor = meta_cursor_reference_ref (cursor);
g_clear_object (&tracker->root_cursor);
if (cursor_sprite)
tracker->root_cursor = g_object_ref (cursor_sprite);
sync_cursor (tracker);
}
@@ -438,7 +431,7 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
sync_cursor (tracker);
}
MetaCursorReference *
MetaCursorSprite *
meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker)
{
return tracker->displayed_cursor;

View File

@@ -21,7 +21,7 @@
#include "config.h"
#include "meta-cursor-private.h"
#include "meta-cursor.h"
#include <meta/errors.h>
@@ -29,58 +29,38 @@
#include "screen-private.h"
#include "meta-backend-private.h"
#ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-cursor-renderer-native.h"
#endif
#include <string.h>
#include <X11/cursorfont.h>
#include <X11/extensions/Xfixes.h>
#include <X11/Xcursor/Xcursor.h>
#ifdef HAVE_WAYLAND
#include <cogl/cogl-wayland-server.h>
#endif
enum {
PREPARE_AT,
MetaCursorReference *
meta_cursor_reference_ref (MetaCursorReference *self)
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
struct _MetaCursorSprite
{
g_assert (self->ref_count > 0);
self->ref_count++;
GObject parent;
return self;
}
MetaCursor cursor;
static void
meta_cursor_image_free (MetaCursorImage *image)
{
if (image->texture)
cogl_object_unref (image->texture);
CoglTexture2D *texture;
float texture_scale;
int hot_x, hot_y;
#ifdef HAVE_NATIVE_BACKEND
if (image->bo)
gbm_bo_destroy (image->bo);
#endif
}
int current_frame;
XcursorImages *xcursor_images;
static void
meta_cursor_reference_free (MetaCursorReference *self)
{
if (self->xcursor_images)
XcursorImagesDestroy (self->xcursor_images);
meta_cursor_image_free (&self->image);
g_slice_free (MetaCursorReference, self);
}
int theme_scale;
gboolean theme_dirty;
};
void
meta_cursor_reference_unref (MetaCursorReference *self)
{
self->ref_count--;
if (self->ref_count == 0)
meta_cursor_reference_free (self);
}
G_DEFINE_TYPE (MetaCursorSprite, meta_cursor_sprite, G_TYPE_OBJECT)
static const char *
translate_meta_cursor (MetaCursor cursor)
@@ -138,92 +118,27 @@ meta_cursor_create_x_cursor (Display *xdisplay,
}
static XcursorImages *
load_cursor_on_client (MetaCursor cursor)
load_cursor_on_client (MetaCursor cursor, int scale)
{
return XcursorLibraryLoadImages (translate_meta_cursor (cursor),
meta_prefs_get_cursor_theme (),
meta_prefs_get_cursor_size ());
meta_prefs_get_cursor_size () * scale);
}
#ifdef HAVE_NATIVE_BACKEND
static void
get_hardware_cursor_size (uint64_t *cursor_width, uint64_t *cursor_height)
meta_cursor_sprite_load_from_xcursor_image (MetaCursorSprite *self,
XcursorImage *xc_image)
{
MetaBackend *meta_backend = meta_get_backend ();
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
{
meta_cursor_renderer_native_get_cursor_size (META_CURSOR_RENDERER_NATIVE (renderer), cursor_width, cursor_height);
return;
}
g_assert_not_reached ();
}
#endif
#ifdef HAVE_NATIVE_BACKEND
static void
meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
MetaCursorImage *image,
uint8_t *pixels,
uint width,
uint height,
int rowstride,
uint32_t gbm_format)
{
uint64_t cursor_width, cursor_height;
get_hardware_cursor_size (&cursor_width, &cursor_height);
if (width > cursor_width || height > cursor_height)
{
meta_warning ("Invalid theme cursor size (must be at most %ux%u)\n",
(unsigned int)cursor_width, (unsigned int)cursor_height);
return;
}
if (gbm_device_is_format_supported (gbm, gbm_format,
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE))
{
uint8_t buf[4 * cursor_width * cursor_height];
uint i;
image->bo = gbm_bo_create (gbm, cursor_width, cursor_height,
gbm_format, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
memset (buf, 0, sizeof(buf));
for (i = 0; i < height; i++)
memcpy (buf + i * 4 * cursor_width, pixels + i * rowstride, width * 4);
gbm_bo_write (image->bo, buf, cursor_width * cursor_height * 4);
}
else
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
}
#endif
#ifdef HAVE_NATIVE_BACKEND
static struct gbm_device *
get_gbm_device (void)
{
MetaBackend *meta_backend = meta_get_backend ();
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
return meta_cursor_renderer_native_get_gbm_device (META_CURSOR_RENDERER_NATIVE (renderer));
else
return NULL;
}
#endif
static void
meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
XcursorImage *xc_image)
{
uint width, height, rowstride;
CoglPixelFormat cogl_format;
ClutterBackend *clutter_backend;
CoglContext *cogl_context;
CoglTexture *texture;
CoglError *error = NULL;
g_assert (self->texture == NULL);
width = xc_image->width;
height = xc_image->height;
@@ -235,41 +150,42 @@ meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
#endif
image->hot_x = xc_image->xhot;
image->hot_y = xc_image->yhot;
clutter_backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (clutter_backend);
image->texture = cogl_texture_2d_new_from_data (cogl_context,
width, height,
cogl_format,
rowstride,
(uint8_t *) xc_image->pixels,
NULL);
texture = cogl_texture_2d_new_from_data (cogl_context,
width, height,
cogl_format,
rowstride,
(uint8_t *) xc_image->pixels,
&error);
#ifdef HAVE_NATIVE_BACKEND
struct gbm_device *gbm = get_gbm_device ();
if (gbm)
meta_cursor_image_load_gbm_buffer (gbm,
image,
(uint8_t *) xc_image->pixels,
width, height, rowstride,
GBM_FORMAT_ARGB8888);
#endif
if (error)
{
meta_warning ("Failed to allocate cursor texture: %s\n", error->message);
cogl_error_free (error);
}
meta_cursor_sprite_set_texture (self, texture,
xc_image->xhot, xc_image->yhot);
if (texture)
cogl_object_unref (texture);
meta_cursor_renderer_realize_cursor_from_xcursor (renderer, self, xc_image);
}
static XcursorImage *
meta_cursor_reference_get_current_frame_image (MetaCursorReference *self)
meta_cursor_sprite_get_current_frame_image (MetaCursorSprite *self)
{
return self->xcursor_images->images[self->current_frame];
}
void
meta_cursor_reference_tick_frame (MetaCursorReference *self)
meta_cursor_sprite_tick_frame (MetaCursorSprite *self)
{
XcursorImage *image;
if (!meta_cursor_reference_is_animated (self))
if (!meta_cursor_sprite_is_animated (self))
return;
self->current_frame++;
@@ -277,198 +193,176 @@ meta_cursor_reference_tick_frame (MetaCursorReference *self)
if (self->current_frame >= self->xcursor_images->nimage)
self->current_frame = 0;
meta_cursor_image_free (&self->image);
image = meta_cursor_reference_get_current_frame_image (self);
meta_cursor_image_load_from_xcursor_image (&self->image, image);
image = meta_cursor_sprite_get_current_frame_image (self);
g_clear_pointer (&self->texture, cogl_object_unref);
meta_cursor_sprite_load_from_xcursor_image (self, image);
}
guint
meta_cursor_reference_get_current_frame_time (MetaCursorReference *self)
meta_cursor_sprite_get_current_frame_time (MetaCursorSprite *self)
{
if (!meta_cursor_reference_is_animated (self))
if (!meta_cursor_sprite_is_animated (self))
return 0;
return self->xcursor_images->images[self->current_frame]->delay;
}
gboolean
meta_cursor_reference_is_animated (MetaCursorReference *self)
meta_cursor_sprite_is_animated (MetaCursorSprite *self)
{
return (self->xcursor_images &&
self->xcursor_images->nimage > 1);
}
MetaCursorSprite *
meta_cursor_sprite_new (void)
{
return g_object_new (META_TYPE_CURSOR_SPRITE, NULL);
}
static void
load_cursor_image (MetaCursorReference *cursor)
meta_cursor_sprite_load_from_theme (MetaCursorSprite *self)
{
XcursorImage *image;
/* Either cursors are loaded from X cursors or buffers. Since
* buffers are converted over immediately, we can make sure to
* load this directly. */
g_assert (cursor->cursor != META_CURSOR_NONE);
g_assert (self->cursor != META_CURSOR_NONE);
if (!cursor->xcursor_images)
/* We might be reloading with a different scale. If so clear the old data. */
if (self->xcursor_images)
{
cursor->current_frame = 0;
cursor->xcursor_images = load_cursor_on_client (cursor->cursor);
if (!cursor->xcursor_images)
meta_fatal ("Could not find cursor. Perhaps set XCURSOR_PATH?");
g_clear_pointer (&self->texture, cogl_object_unref);
XcursorImagesDestroy (self->xcursor_images);
}
image = meta_cursor_reference_get_current_frame_image (cursor);
meta_cursor_image_load_from_xcursor_image (&cursor->image, image);
self->current_frame = 0;
self->xcursor_images = load_cursor_on_client (self->cursor,
self->theme_scale);
if (!self->xcursor_images)
meta_fatal ("Could not find cursor. Perhaps set XCURSOR_PATH?");
image = meta_cursor_sprite_get_current_frame_image (self);
meta_cursor_sprite_load_from_xcursor_image (self, image);
self->theme_dirty = FALSE;
}
MetaCursorReference *
meta_cursor_reference_from_theme (MetaCursor cursor)
MetaCursorSprite *
meta_cursor_sprite_from_theme (MetaCursor cursor)
{
MetaCursorReference *self = g_slice_new0 (MetaCursorReference);
self->ref_count = 1;
MetaCursorSprite *self;
self = meta_cursor_sprite_new ();
self->cursor = cursor;
return self;
}
#ifdef HAVE_WAYLAND
static void
meta_cursor_image_load_from_buffer (MetaCursorImage *image,
struct wl_resource *buffer,
int hot_x,
int hot_y)
{
ClutterBackend *backend;
CoglContext *cogl_context;
image->hot_x = hot_x;
image->hot_y = hot_y;
backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (backend);
image->texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL);
#ifdef HAVE_NATIVE_BACKEND
struct gbm_device *gbm = get_gbm_device ();
if (gbm)
{
uint32_t gbm_format;
uint64_t cursor_width, cursor_height;
uint width, height;
width = cogl_texture_get_width (COGL_TEXTURE (image->texture));
height = cogl_texture_get_height (COGL_TEXTURE (image->texture));
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (buffer);
if (shm_buffer)
{
int rowstride = wl_shm_buffer_get_stride (shm_buffer);
wl_shm_buffer_begin_access (shm_buffer);
switch (wl_shm_buffer_get_format (shm_buffer))
{
#if G_BYTE_ORDER == G_BIG_ENDIAN
case WL_SHM_FORMAT_ARGB8888:
gbm_format = GBM_FORMAT_ARGB8888;
break;
case WL_SHM_FORMAT_XRGB8888:
gbm_format = GBM_FORMAT_XRGB8888;
break;
#else
case WL_SHM_FORMAT_ARGB8888:
gbm_format = GBM_FORMAT_ARGB8888;
break;
case WL_SHM_FORMAT_XRGB8888:
gbm_format = GBM_FORMAT_XRGB8888;
break;
#endif
default:
g_warn_if_reached ();
gbm_format = GBM_FORMAT_ARGB8888;
}
meta_cursor_image_load_gbm_buffer (gbm,
image,
(uint8_t *) wl_shm_buffer_get_data (shm_buffer),
width, height, rowstride,
gbm_format);
wl_shm_buffer_end_access (shm_buffer);
}
else
{
/* HW cursors have a predefined size (at least 64x64), which usually is bigger than cursor theme
size, so themed cursors must be padded with transparent pixels to fill the
overlay. This is trivial if we have CPU access to the data, but it's not
possible if the buffer is in GPU memory (and possibly tiled too), so if we
don't get the right size, we fallback to GL.
*/
get_hardware_cursor_size (&cursor_width, &cursor_height);
if (width != cursor_width || height != cursor_height)
{
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
return;
}
image->bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER, buffer, GBM_BO_USE_CURSOR);
if (!image->bo)
meta_warning ("Importing HW cursor from wl_buffer failed\n");
}
}
#endif
}
MetaCursorReference *
meta_cursor_reference_from_buffer (struct wl_resource *buffer,
int hot_x,
int hot_y)
{
MetaCursorReference *self;
self = g_slice_new0 (MetaCursorReference);
self->ref_count = 1;
meta_cursor_image_load_from_buffer (&self->image, buffer, hot_x, hot_y);
self->theme_dirty = TRUE;
return self;
}
#endif
void
meta_cursor_sprite_set_texture (MetaCursorSprite *self,
CoglTexture *texture,
int hot_x,
int hot_y)
{
g_clear_pointer (&self->texture, cogl_object_unref);
if (texture)
self->texture = cogl_object_ref (texture);
self->hot_x = hot_x;
self->hot_y = hot_y;
}
void
meta_cursor_sprite_set_texture_scale (MetaCursorSprite *self,
float scale)
{
self->texture_scale = scale;
}
void
meta_cursor_sprite_set_theme_scale (MetaCursorSprite *self,
int theme_scale)
{
if (self->theme_scale != theme_scale)
self->theme_dirty = TRUE;
self->theme_scale = theme_scale;
}
CoglTexture *
meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor,
int *hot_x,
int *hot_y)
meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *self)
{
if (!cursor->image.texture)
load_cursor_image (cursor);
if (hot_x)
*hot_x = cursor->image.hot_x;
if (hot_y)
*hot_y = cursor->image.hot_y;
return COGL_TEXTURE (cursor->image.texture);
return COGL_TEXTURE (self->texture);
}
#ifdef HAVE_NATIVE_BACKEND
struct gbm_bo *
meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
int *hot_x,
int *hot_y)
{
if (!cursor->image.bo)
load_cursor_image (cursor);
if (hot_x)
*hot_x = cursor->image.hot_x;
if (hot_y)
*hot_y = cursor->image.hot_y;
return cursor->image.bo;
}
#endif
MetaCursor
meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor)
meta_cursor_sprite_get_meta_cursor (MetaCursorSprite *self)
{
return cursor->cursor;
return self->cursor;
}
void
meta_cursor_sprite_get_hotspot (MetaCursorSprite *self,
int *hot_x,
int *hot_y)
{
*hot_x = self->hot_x;
*hot_y = self->hot_y;
}
float
meta_cursor_sprite_get_texture_scale (MetaCursorSprite *self)
{
return self->texture_scale;
}
void
meta_cursor_sprite_prepare_at (MetaCursorSprite *self,
int x,
int y)
{
g_signal_emit (self, signals[PREPARE_AT], 0, x, y);
}
void
meta_cursor_sprite_realize_texture (MetaCursorSprite *self)
{
if (self->theme_dirty)
meta_cursor_sprite_load_from_theme (self);
}
static void
meta_cursor_sprite_init (MetaCursorSprite *self)
{
self->texture_scale = 1.0f;
}
static void
meta_cursor_sprite_finalize (GObject *object)
{
MetaCursorSprite *self = META_CURSOR_SPRITE (object);
if (self->xcursor_images)
XcursorImagesDestroy (self->xcursor_images);
g_clear_pointer (&self->texture, cogl_object_unref);
G_OBJECT_CLASS (meta_cursor_sprite_parent_class)->finalize (object);
}
static void
meta_cursor_sprite_class_init (MetaCursorSpriteClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_cursor_sprite_finalize;
signals[PREPARE_AT] = g_signal_new ("prepare-at",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 2,
G_TYPE_INT,
G_TYPE_INT);
}

View File

@@ -22,25 +22,54 @@
#ifndef META_CURSOR_H
#define META_CURSOR_H
typedef struct _MetaCursorReference MetaCursorReference;
MetaCursorReference * meta_cursor_reference_ref (MetaCursorReference *cursor);
void meta_cursor_reference_unref (MetaCursorReference *cursor);
#include <meta/common.h>
#include <meta/boxes.h>
MetaCursorReference * meta_cursor_reference_from_theme (MetaCursor cursor);
typedef struct _MetaCursorSprite MetaCursorSprite;
#ifdef HAVE_WAYLAND
#include <wayland-server.h>
MetaCursorReference * meta_cursor_reference_from_buffer (struct wl_resource *buffer,
int hot_x,
int hot_y);
#endif
#define META_TYPE_CURSOR_SPRITE (meta_cursor_sprite_get_type ())
G_DECLARE_FINAL_TYPE (MetaCursorSprite,
meta_cursor_sprite,
META, CURSOR_SPRITE,
GObject);
MetaCursor meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor);
MetaCursorSprite * meta_cursor_sprite_new (void);
MetaCursorSprite * meta_cursor_sprite_from_theme (MetaCursor cursor);
void meta_cursor_sprite_set_theme_scale (MetaCursorSprite *self,
int scale);
MetaCursor meta_cursor_sprite_get_meta_cursor (MetaCursorSprite *self);
Cursor meta_cursor_create_x_cursor (Display *xdisplay,
MetaCursor cursor);
void meta_cursor_sprite_prepare_at (MetaCursorSprite *self,
int x,
int y);
void meta_cursor_sprite_realize_texture (MetaCursorSprite *self);
void meta_cursor_sprite_set_texture (MetaCursorSprite *self,
CoglTexture *texture,
int hot_x,
int hot_y);
void meta_cursor_sprite_set_texture_scale (MetaCursorSprite *self,
float scale);
CoglTexture *meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *self);
void meta_cursor_sprite_get_hotspot (MetaCursorSprite *self,
int *hot_x,
int *hot_y);
float meta_cursor_sprite_get_texture_scale (MetaCursorSprite *self);
gboolean meta_cursor_sprite_is_animated (MetaCursorSprite *self);
void meta_cursor_sprite_tick_frame (MetaCursorSprite *self);
guint meta_cursor_sprite_get_current_frame_time (MetaCursorSprite *self);
#endif /* META_CURSOR_H */

View File

@@ -523,15 +523,13 @@ update_trackball_scroll_button (MetaInputSettings *input_settings,
}
else if (!device)
{
MetaInputSettingsPrivate *priv;
const GSList *devices;
priv = meta_input_settings_get_instance_private (input_settings);
devices = clutter_device_manager_peek_devices (priv->device_manager);
while (devices)
{
ClutterInputDevice *device = devices->data;
device = devices->data;
if (device_is_trackball (device))
input_settings_class->set_scroll_button (input_settings, device, button);

View File

@@ -1846,7 +1846,7 @@ crtc_assignment_assign (CrtcAssignment *assign,
}
else
{
MetaCRTCInfo *info = g_slice_new0 (MetaCRTCInfo);
info = g_slice_new0 (MetaCRTCInfo);
info->crtc = crtc;
info->mode = mode;

View File

@@ -197,7 +197,7 @@ meta_monitor_manager_dummy_apply_config (MetaMonitorManager *manager,
{
MetaMonitorMode *mode;
MetaOutput *output;
int i, n_outputs;
unsigned int j;
int width, height;
mode = crtc_info->mode;
@@ -223,10 +223,9 @@ meta_monitor_manager_dummy_apply_config (MetaMonitorManager *manager,
screen_width = MAX (screen_width, crtc_info->x + width);
screen_height = MAX (screen_height, crtc_info->y + height);
n_outputs = crtc_info->outputs->len;
for (i = 0; i < n_outputs; i++)
for (j = 0; j < crtc_info->outputs->len; j++)
{
output = ((MetaOutput**)crtc_info->outputs->pdata)[i];
output = ((MetaOutput**)crtc_info->outputs->pdata)[j];
output->is_dirty = TRUE;
output->crtc = crtc;

View File

@@ -174,7 +174,8 @@ struct _MetaCRTC
/* Used when changing configuration */
gboolean is_dirty;
MetaCursorReference *cursor;
/* Used by cursor renderer backend */
void *cursor_renderer_private;
gpointer driver_private;
GDestroyNotify driver_notify;
@@ -413,6 +414,10 @@ gint meta_monitor_manager_get_monitor_at_point (MetaMonitorManager
gfloat x,
gfloat y);
void meta_monitor_manager_clear_output (MetaOutput *output);
void meta_monitor_manager_clear_mode (MetaMonitorMode *mode);
void meta_monitor_manager_clear_crtc (MetaCRTC *crtc);
/* Returns true if transform causes width and height to be inverted
This is true for the odd transforms in the enum */
static inline gboolean

View File

@@ -178,7 +178,7 @@ make_logical_config (MetaMonitorManager *manager)
unsigned int i, j;
monitor_infos = g_array_sized_new (FALSE, TRUE, sizeof (MetaMonitorInfo),
manager->n_outputs);
manager->n_crtcs);
/* Walk the list of MetaCRTCs, and build a MetaMonitorInfo
for each of them, unless they reference a rectangle that
@@ -346,6 +346,23 @@ meta_monitor_manager_constructed (GObject *object)
manager->in_init = FALSE;
}
void
meta_monitor_manager_clear_output (MetaOutput *output)
{
g_free (output->name);
g_free (output->vendor);
g_free (output->product);
g_free (output->serial);
g_free (output->modes);
g_free (output->possible_crtcs);
g_free (output->possible_clones);
if (output->driver_notify)
output->driver_notify (output);
memset (output, 0, sizeof (*output));
}
static void
meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
int n_old_outputs)
@@ -353,22 +370,22 @@ meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
int i;
for (i = 0; i < n_old_outputs; i++)
{
g_free (old_outputs[i].name);
g_free (old_outputs[i].vendor);
g_free (old_outputs[i].product);
g_free (old_outputs[i].serial);
g_free (old_outputs[i].modes);
g_free (old_outputs[i].possible_crtcs);
g_free (old_outputs[i].possible_clones);
if (old_outputs[i].driver_notify)
old_outputs[i].driver_notify (&old_outputs[i]);
}
meta_monitor_manager_clear_output (&old_outputs[i]);
g_free (old_outputs);
}
void
meta_monitor_manager_clear_mode (MetaMonitorMode *mode)
{
g_free (mode->name);
if (mode->driver_notify)
mode->driver_notify (mode);
memset (mode, 0, sizeof (*mode));
}
static void
meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
int n_old_modes)
@@ -376,16 +393,20 @@ meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
int i;
for (i = 0; i < n_old_modes; i++)
{
g_free (old_modes[i].name);
if (old_modes[i].driver_notify)
old_modes[i].driver_notify (&old_modes[i]);
}
meta_monitor_manager_clear_mode (&old_modes[i]);
g_free (old_modes);
}
void
meta_monitor_manager_clear_crtc (MetaCRTC *crtc)
{
if (crtc->driver_notify)
crtc->driver_notify (crtc);
memset (crtc, 0, sizeof (*crtc));
}
static void
meta_monitor_manager_free_crtc_array (MetaCRTC *old_crtcs,
int n_old_crtcs)
@@ -393,10 +414,7 @@ meta_monitor_manager_free_crtc_array (MetaCRTC *old_crtcs,
int i;
for (i = 0; i < n_old_crtcs; i++)
{
if (old_crtcs[i].driver_notify)
old_crtcs[i].driver_notify (&old_crtcs[i]);
}
meta_monitor_manager_clear_crtc (&old_crtcs[i]);
g_free (old_crtcs);
}
@@ -884,8 +902,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
crtc_info->y = 0;
}
if (transform < META_MONITOR_TRANSFORM_NORMAL ||
transform > META_MONITOR_TRANSFORM_FLIPPED_270 ||
if (transform > META_MONITOR_TRANSFORM_FLIPPED_270 ||
((crtc->all_transforms & (1 << transform)) == 0))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,

View File

@@ -24,7 +24,6 @@
#include "meta-stage.h"
#include "meta-cursor-private.h"
#include <meta/meta-backend.h>
#include <meta/util.h>

View File

@@ -37,6 +37,8 @@
#include "meta-cursor-renderer-native.h"
#include "meta-launcher.h"
#include <stdlib.h>
struct _MetaBackendNativePrivate
{
MetaLauncher *launcher;
@@ -327,9 +329,14 @@ static void
meta_backend_native_init (MetaBackendNative *native)
{
MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native);
GError *error = NULL;
/* We're a display server, so start talking to weston-launch. */
priv->launcher = meta_launcher_new ();
priv->launcher = meta_launcher_new (&error);
if (priv->launcher == NULL)
{
g_warning ("Can't initialize KMS backend: %s\n", error->message);
exit (1);
}
priv->barrier_manager = meta_barrier_manager_native_new ();

View File

@@ -26,11 +26,16 @@
#include "meta-cursor-renderer-native.h"
#include <string.h>
#include <gbm.h>
#include <xf86drm.h>
#include <errno.h>
#include <meta/util.h>
#include <meta/meta-backend.h>
#include "meta-cursor-private.h"
#include "meta-monitor-manager-private.h"
#include "meta/boxes.h"
#ifndef DRM_CAP_CURSOR_WIDTH
#define DRM_CAP_CURSOR_WIDTH 0x8
@@ -39,11 +44,26 @@
#define DRM_CAP_CURSOR_HEIGHT 0x9
#endif
/* When animating a cursor, we usually call drmModeSetCursor2 once per frame.
* Though, testing shows that we need to triple buffer the cursor buffer in
* order to avoid glitches when animating the cursor, at least when running on
* Intel. The reason for this might be (but is not confirmed to be) due to
* the user space gbm_bo cache, making us reuse and overwrite the kernel side
* buffer content before it was scanned out. To avoid this, we keep a user space
* reference to each buffer we set until at least one frame after it was drawn.
* In effect, this means we three active cursor gbm_bo's: one that that just has
* been set, one that was previously set and may or may not have been scanned
* out, and one pending that will be replaced if the cursor sprite changes.
*/
#define HW_CURSOR_BUFFER_COUNT 3
static GQuark quark_cursor_sprite = 0;
struct _MetaCursorRendererNativePrivate
{
gboolean has_hw_cursor;
MetaCursorReference *last_cursor;
MetaCursorSprite *last_cursor;
guint animation_timeout_id;
int drm_fd;
@@ -54,8 +74,25 @@ struct _MetaCursorRendererNativePrivate
};
typedef struct _MetaCursorRendererNativePrivate MetaCursorRendererNativePrivate;
typedef enum _MetaCursorGbmBoState
{
META_CURSOR_GBM_BO_STATE_NONE,
META_CURSOR_GBM_BO_STATE_SET,
META_CURSOR_GBM_BO_STATE_INVALIDATED,
} MetaCursorGbmBoState;
typedef struct _MetaCursorNativePrivate
{
guint active_bo;
MetaCursorGbmBoState pending_bo_state;
struct gbm_bo *bos[HW_CURSOR_BUFFER_COUNT];
} MetaCursorNativePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererNative, meta_cursor_renderer_native, META_TYPE_CURSOR_RENDERER);
static MetaCursorNativePrivate *
ensure_cursor_priv (MetaCursorSprite *cursor_sprite);
static void
meta_cursor_renderer_native_finalize (GObject *object)
{
@@ -71,63 +108,136 @@ meta_cursor_renderer_native_finalize (GObject *object)
G_OBJECT_CLASS (meta_cursor_renderer_native_parent_class)->finalize (object);
}
static guint
get_pending_cursor_sprite_gbm_bo_index (MetaCursorSprite *cursor_sprite)
{
MetaCursorNativePrivate *cursor_priv =
g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite);
return (cursor_priv->active_bo + 1) % HW_CURSOR_BUFFER_COUNT;
}
static struct gbm_bo *
get_pending_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite)
{
MetaCursorNativePrivate *cursor_priv =
g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite);
guint pending_bo;
if (!cursor_priv)
return NULL;
pending_bo = get_pending_cursor_sprite_gbm_bo_index (cursor_sprite);
return cursor_priv->bos[pending_bo];
}
static struct gbm_bo *
get_active_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite)
{
MetaCursorNativePrivate *cursor_priv =
g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite);
if (!cursor_priv)
return NULL;
return cursor_priv->bos[cursor_priv->active_bo];
}
static void
set_pending_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite,
struct gbm_bo *bo)
{
MetaCursorNativePrivate *cursor_priv;
guint pending_bo;
cursor_priv = ensure_cursor_priv (cursor_sprite);
pending_bo = get_pending_cursor_sprite_gbm_bo_index (cursor_sprite);
cursor_priv->bos[pending_bo] = bo;
cursor_priv->pending_bo_state = META_CURSOR_GBM_BO_STATE_SET;
}
static void
set_crtc_cursor (MetaCursorRendererNative *native,
MetaCRTC *crtc,
MetaCursorReference *cursor,
MetaCursorSprite *cursor_sprite,
gboolean force)
{
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
if (crtc->cursor == cursor && !force)
return;
crtc->cursor = cursor;
if (cursor)
if (cursor_sprite)
{
MetaCursorNativePrivate *cursor_priv =
g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite);
struct gbm_bo *bo;
union gbm_bo_handle handle;
int hot_x, hot_y;
bo = meta_cursor_reference_get_gbm_bo (cursor, &hot_x, &hot_y);
if (cursor_priv->pending_bo_state == META_CURSOR_GBM_BO_STATE_SET)
bo = get_pending_cursor_sprite_gbm_bo (cursor_sprite);
else
bo = get_active_cursor_sprite_gbm_bo (cursor_sprite);
if (!force && bo == crtc->cursor_renderer_private)
return;
crtc->cursor_renderer_private = bo;
handle = gbm_bo_get_handle (bo);
meta_cursor_sprite_get_hotspot (cursor_sprite, &hot_x, &hot_y);
drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, handle.u32,
priv->cursor_width, priv->cursor_height, hot_x, hot_y);
if (cursor_priv->pending_bo_state == META_CURSOR_GBM_BO_STATE_SET)
{
cursor_priv->active_bo =
(cursor_priv->active_bo + 1) % HW_CURSOR_BUFFER_COUNT;
cursor_priv->pending_bo_state = META_CURSOR_GBM_BO_STATE_NONE;
}
}
else
{
drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, 0, 0, 0, 0, 0);
if (force || crtc->cursor_renderer_private != NULL)
{
drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, 0, 0, 0, 0, 0);
crtc->cursor_renderer_private = NULL;
}
}
}
static void
update_hw_cursor (MetaCursorRendererNative *native,
MetaCursorSprite *cursor_sprite,
gboolean force)
{
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native);
const MetaRectangle *cursor_rect = meta_cursor_renderer_get_rect (renderer);
MetaCursorReference *cursor = meta_cursor_renderer_get_cursor (renderer);
MetaMonitorManager *monitors;
MetaCRTC *crtcs;
unsigned int i, n_crtcs;
MetaRectangle rect;
monitors = meta_monitor_manager_get ();
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
if (cursor_sprite)
rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite);
else
rect = (MetaRectangle) { 0 };
for (i = 0; i < n_crtcs; i++)
{
gboolean crtc_should_have_cursor;
MetaCursorReference *crtc_cursor;
gboolean crtc_should_use_cursor;
MetaCursorSprite *crtc_cursor;
MetaRectangle *crtc_rect;
crtc_rect = &crtcs[i].rect;
crtc_should_have_cursor = (priv->has_hw_cursor && meta_rectangle_overlap (cursor_rect, crtc_rect));
if (crtc_should_have_cursor)
crtc_cursor = cursor;
crtc_should_use_cursor = (priv->has_hw_cursor &&
meta_rectangle_overlap (&rect, crtc_rect));
if (crtc_should_use_cursor)
crtc_cursor = cursor_sprite;
else
crtc_cursor = NULL;
@@ -136,49 +246,79 @@ update_hw_cursor (MetaCursorRendererNative *native,
if (crtc_cursor)
{
drmModeMoveCursor (priv->drm_fd, crtcs[i].crtc_id,
cursor_rect->x - crtc_rect->x,
cursor_rect->y - crtc_rect->y);
rect.x - crtc_rect->x,
rect.y - crtc_rect->y);
}
}
}
static gboolean
should_have_hw_cursor (MetaCursorRenderer *renderer)
has_valid_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite)
{
MetaCursorReference *cursor = meta_cursor_renderer_get_cursor (renderer);
MetaCursorNativePrivate *cursor_priv =
g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite);
if (cursor)
return (meta_cursor_reference_get_gbm_bo (cursor, NULL, NULL) != NULL);
else
switch (cursor_priv->pending_bo_state)
{
case META_CURSOR_GBM_BO_STATE_NONE:
return get_active_cursor_sprite_gbm_bo (cursor_sprite) != NULL;
case META_CURSOR_GBM_BO_STATE_SET:
return TRUE;
case META_CURSOR_GBM_BO_STATE_INVALIDATED:
return FALSE;
}
g_assert_not_reached ();
return FALSE;
}
static gboolean
should_have_hw_cursor (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite)
{
CoglTexture *texture;
if (!cursor_sprite)
return FALSE;
texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
if (!texture)
return FALSE;
if (meta_cursor_sprite_get_texture_scale (cursor_sprite) != 1)
return FALSE;
if (!has_valid_cursor_sprite_gbm_bo (cursor_sprite))
return FALSE;
return TRUE;
}
static gboolean
meta_cursor_renderer_native_update_animation (MetaCursorRendererNative *native)
{
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
MetaCursorReference *cursor;
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native);
MetaCursorSprite *cursor_sprite = meta_cursor_renderer_get_cursor (renderer);
priv->animation_timeout_id = 0;
cursor = meta_cursor_renderer_get_cursor (META_CURSOR_RENDERER (native));
meta_cursor_reference_tick_frame (cursor);
meta_cursor_renderer_force_update (META_CURSOR_RENDERER (native));
meta_cursor_renderer_native_force_update (native);
meta_cursor_sprite_tick_frame (cursor_sprite);
meta_cursor_renderer_force_update (renderer);
return G_SOURCE_REMOVE;
}
static void
meta_cursor_renderer_native_trigger_frame (MetaCursorRendererNative *native)
meta_cursor_renderer_native_trigger_frame (MetaCursorRendererNative *native,
MetaCursorSprite *cursor_sprite)
{
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
MetaCursorReference *cursor;
gboolean cursor_change;
guint delay;
cursor = meta_cursor_renderer_get_cursor (META_CURSOR_RENDERER (native));
cursor_change = cursor != priv->last_cursor;
priv->last_cursor = cursor;
cursor_change = cursor_sprite != priv->last_cursor;
priv->last_cursor = cursor_sprite;
if (!cursor_change && priv->animation_timeout_id)
return;
@@ -189,9 +329,9 @@ meta_cursor_renderer_native_trigger_frame (MetaCursorRendererNative *native)
priv->animation_timeout_id = 0;
}
if (cursor && meta_cursor_reference_is_animated (cursor))
if (cursor_sprite && meta_cursor_sprite_is_animated (cursor_sprite))
{
delay = meta_cursor_reference_get_current_frame_time (cursor);
delay = meta_cursor_sprite_get_current_frame_time (cursor_sprite);
if (delay == 0)
return;
@@ -206,18 +346,250 @@ meta_cursor_renderer_native_trigger_frame (MetaCursorRendererNative *native)
}
static gboolean
meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer)
meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite)
{
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
meta_cursor_renderer_native_trigger_frame (native);
if (cursor_sprite)
meta_cursor_sprite_realize_texture (cursor_sprite);
priv->has_hw_cursor = should_have_hw_cursor (renderer);
update_hw_cursor (native, FALSE);
meta_cursor_renderer_native_trigger_frame (native, cursor_sprite);
priv->has_hw_cursor = should_have_hw_cursor (renderer, cursor_sprite);
update_hw_cursor (native, cursor_sprite, FALSE);
return priv->has_hw_cursor;
}
static void
get_hardware_cursor_size (MetaCursorRendererNative *native,
uint64_t *width, uint64_t *height)
{
MetaCursorRendererNativePrivate *priv =
meta_cursor_renderer_native_get_instance_private (native);
*width = priv->cursor_width;
*height = priv->cursor_height;
}
static void
cursor_priv_free (gpointer data)
{
MetaCursorNativePrivate *cursor_priv = data;
guint i;
if (!data)
return;
for (i = 0; i < HW_CURSOR_BUFFER_COUNT; i++)
g_clear_pointer (&cursor_priv->bos[0], (GDestroyNotify) gbm_bo_destroy);
g_slice_free (MetaCursorNativePrivate, cursor_priv);
}
static MetaCursorNativePrivate *
ensure_cursor_priv (MetaCursorSprite *cursor_sprite)
{
MetaCursorNativePrivate *cursor_priv =
g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite);
if (!cursor_priv)
{
cursor_priv = g_slice_new0 (MetaCursorNativePrivate);
g_object_set_qdata_full (G_OBJECT (cursor_sprite),
quark_cursor_sprite,
cursor_priv,
cursor_priv_free);
}
return cursor_priv;
}
static void
load_cursor_sprite_gbm_buffer (MetaCursorRendererNative *native,
MetaCursorSprite *cursor_sprite,
uint8_t *pixels,
uint width,
uint height,
int rowstride,
uint32_t gbm_format)
{
MetaCursorRendererNativePrivate *priv =
meta_cursor_renderer_native_get_instance_private (native);
uint64_t cursor_width, cursor_height;
get_hardware_cursor_size (native, &cursor_width, &cursor_height);
if (width > cursor_width || height > cursor_height)
{
meta_warning ("Invalid theme cursor size (must be at most %ux%u)\n",
(unsigned int)cursor_width, (unsigned int)cursor_height);
return;
}
if (gbm_device_is_format_supported (priv->gbm, gbm_format,
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE))
{
struct gbm_bo *bo;
uint8_t buf[4 * cursor_width * cursor_height];
uint i;
bo = gbm_bo_create (priv->gbm, cursor_width, cursor_height,
gbm_format, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
if (!bo)
{
meta_warning ("Failed to allocate HW cursor buffer\n");
return;
}
memset (buf, 0, sizeof(buf));
for (i = 0; i < height; i++)
memcpy (buf + i * 4 * cursor_width, pixels + i * rowstride, width * 4);
if (gbm_bo_write (bo, buf, cursor_width * cursor_height * 4) != 0)
{
meta_warning ("Failed to write cursors buffer data: %s",
g_strerror (errno));
gbm_bo_destroy (bo);
return;
}
set_pending_cursor_sprite_gbm_bo (cursor_sprite, bo);
}
else
{
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
}
}
static void
invalidate_pending_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite)
{
MetaCursorNativePrivate *cursor_priv =
g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite);
guint pending_bo;
if (!cursor_priv)
return;
pending_bo = get_pending_cursor_sprite_gbm_bo_index (cursor_sprite);
g_clear_pointer (&cursor_priv->bos[pending_bo],
(GDestroyNotify) gbm_bo_destroy);
cursor_priv->pending_bo_state = META_CURSOR_GBM_BO_STATE_INVALIDATED;
}
#ifdef HAVE_WAYLAND
static void
meta_cursor_renderer_native_realize_cursor_from_wl_buffer (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite,
struct wl_resource *buffer)
{
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
MetaCursorRendererNativePrivate *priv =
meta_cursor_renderer_native_get_instance_private (native);
uint32_t gbm_format;
uint64_t cursor_width, cursor_height;
CoglTexture *texture;
uint width, height;
/* Destroy any previous pending cursor buffer; we'll always either fail (which
* should unset, or succeed, which will set new buffer.
*/
invalidate_pending_cursor_sprite_gbm_bo (cursor_sprite);
texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
width = cogl_texture_get_width (texture);
height = cogl_texture_get_height (texture);
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (buffer);
if (shm_buffer)
{
int rowstride = wl_shm_buffer_get_stride (shm_buffer);
uint8_t *buffer_data;
wl_shm_buffer_begin_access (shm_buffer);
switch (wl_shm_buffer_get_format (shm_buffer))
{
#if G_BYTE_ORDER == G_BIG_ENDIAN
case WL_SHM_FORMAT_ARGB8888:
gbm_format = GBM_FORMAT_ARGB8888;
break;
case WL_SHM_FORMAT_XRGB8888:
gbm_format = GBM_FORMAT_XRGB8888;
break;
#else
case WL_SHM_FORMAT_ARGB8888:
gbm_format = GBM_FORMAT_ARGB8888;
break;
case WL_SHM_FORMAT_XRGB8888:
gbm_format = GBM_FORMAT_XRGB8888;
break;
#endif
default:
g_warn_if_reached ();
gbm_format = GBM_FORMAT_ARGB8888;
}
buffer_data = wl_shm_buffer_get_data (shm_buffer);
load_cursor_sprite_gbm_buffer (native,
cursor_sprite,
buffer_data,
width, height, rowstride,
gbm_format);
wl_shm_buffer_end_access (shm_buffer);
}
else
{
struct gbm_bo *bo;
/* HW cursors have a predefined size (at least 64x64), which usually is
* bigger than cursor theme size, so themed cursors must be padded with
* transparent pixels to fill the overlay. This is trivial if we have CPU
* access to the data, but it's not possible if the buffer is in GPU
* memory (and possibly tiled too), so if we don't get the right size, we
* fallback to GL. */
get_hardware_cursor_size (native, &cursor_width, &cursor_height);
if (width != cursor_width || height != cursor_height)
{
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
return;
}
bo = gbm_bo_import (priv->gbm,
GBM_BO_IMPORT_WL_BUFFER,
buffer,
GBM_BO_USE_CURSOR);
if (!bo)
{
meta_warning ("Importing HW cursor from wl_buffer failed\n");
return;
}
set_pending_cursor_sprite_gbm_bo (cursor_sprite, bo);
}
}
#endif
static void
meta_cursor_renderer_native_realize_cursor_from_xcursor (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite,
XcursorImage *xc_image)
{
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
invalidate_pending_cursor_sprite_gbm_bo (cursor_sprite);
load_cursor_sprite_gbm_buffer (native,
cursor_sprite,
(uint8_t *) xc_image->pixels,
xc_image->width,
xc_image->height,
xc_image->width * 4,
GBM_FORMAT_ARGB8888);
}
static void
meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass)
{
@@ -226,6 +598,22 @@ meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass)
object_class->finalize = meta_cursor_renderer_native_finalize;
renderer_class->update_cursor = meta_cursor_renderer_native_update_cursor;
#ifdef HAVE_WAYLAND
renderer_class->realize_cursor_from_wl_buffer =
meta_cursor_renderer_native_realize_cursor_from_wl_buffer;
#endif
renderer_class->realize_cursor_from_xcursor =
meta_cursor_renderer_native_realize_cursor_from_xcursor;
quark_cursor_sprite = g_quark_from_static_string ("-meta-cursor-native");
}
static void
force_update_hw_cursor (MetaCursorRendererNative *native)
{
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native);
update_hw_cursor (native, meta_cursor_renderer_get_cursor (renderer), TRUE);
}
static void
@@ -233,7 +621,7 @@ on_monitors_changed (MetaMonitorManager *monitors,
MetaCursorRendererNative *native)
{
/* Our tracking is all messed up, so force an update. */
update_hw_cursor (native, TRUE);
force_update_hw_cursor (native);
}
static void
@@ -278,18 +666,8 @@ meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *native)
return priv->gbm;
}
void
meta_cursor_renderer_native_get_cursor_size (MetaCursorRendererNative *native,
uint64_t *width, uint64_t *height)
{
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
*width = priv->cursor_width;
*height = priv->cursor_height;
}
void
meta_cursor_renderer_native_force_update (MetaCursorRendererNative *native)
{
update_hw_cursor (native, TRUE);
force_update_hw_cursor (native);
}

View File

@@ -37,6 +37,7 @@
#include <unistd.h>
#include <systemd/sd-login.h>
#include <gudev/gudev.h>
#include "dbus-utils.h"
#include "meta-dbus-login1.h"
@@ -54,14 +55,21 @@ struct _MetaLauncher
};
static Login1Session *
get_session_proxy (GCancellable *cancellable)
get_session_proxy (GCancellable *cancellable,
GError **error)
{
char *proxy_path;
char *session_id;
Login1Session *session_proxy;
if (sd_pid_get_session (getpid (), &session_id) < 0)
return NULL;
{
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_NOT_FOUND,
"Could not get session ID: %m");
return NULL;
}
proxy_path = get_escaped_dbus_path ("/org/freedesktop/login1/session", session_id);
@@ -69,31 +77,39 @@ get_session_proxy (GCancellable *cancellable)
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
"org.freedesktop.login1",
proxy_path,
cancellable, NULL);
cancellable, error);
if (!session_proxy)
g_prefix_error(error, "Could not get session proxy: ");
free (proxy_path);
return session_proxy;
}
static Login1Seat *
get_seat_proxy (GCancellable *cancellable)
get_seat_proxy (GCancellable *cancellable,
GError **error)
{
return login1_seat_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
"org.freedesktop.login1",
"/org/freedesktop/login1/seat/self",
cancellable, NULL);
Login1Seat *seat = login1_seat_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
"org.freedesktop.login1",
"/org/freedesktop/login1/seat/self",
cancellable, error);
if (!seat)
g_prefix_error(error, "Could not get seat proxy: ");
return seat;
}
static void
session_unpause (void)
{
ClutterBackend *backend;
ClutterBackend *clutter_backend;
CoglContext *cogl_context;
CoglDisplay *cogl_display;
backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (backend);
clutter_backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (clutter_backend);
cogl_display = cogl_context_get_display (cogl_context);
cogl_kms_display_queue_modes_reset (cogl_display);
@@ -262,25 +278,108 @@ on_active_changed (Login1Session *session,
sync_active (self);
}
static gchar *
get_primary_gpu_path (const gchar *seat_name)
{
const gchar *subsystems[] = {"drm", NULL};
gchar *path = NULL;
GList *devices, *tmp;
GUdevClient *gudev_client = g_udev_client_new (subsystems);
GUdevEnumerator *enumerator = g_udev_enumerator_new (gudev_client);
g_udev_enumerator_add_match_name (enumerator, "card*");
g_udev_enumerator_add_match_tag (enumerator, "seat");
devices = g_udev_enumerator_execute (enumerator);
if (!devices)
goto out;
for (tmp = devices; tmp != NULL; tmp = tmp->next)
{
GUdevDevice *pci_device;
GUdevDevice *dev = tmp->data;
gint boot_vga;
const gchar *device_seat;
/* filter out devices that are not character device, like card0-VGA-1 */
if (g_udev_device_get_device_type (dev) != G_UDEV_DEVICE_TYPE_CHAR)
continue;
device_seat = g_udev_device_get_property (dev, "ID_SEAT");
if (!device_seat)
{
/* when ID_SEAT is not set, it means seat0 */
device_seat = "seat0";
}
else if (g_strcmp0 (device_seat, "seat0") != 0)
{
/* if the device has been explicitly assigned other seat
* than seat0, it is probably the right device to use */
path = g_strdup (g_udev_device_get_device_file (dev));
break;
}
/* skip devices that do not belong to our seat */
if (g_strcmp0 (seat_name, device_seat))
continue;
pci_device = g_udev_device_get_parent_with_subsystem (dev, "pci", NULL);
if (!pci_device)
continue;
/* get value of boot_vga attribute or 0 if the device has no boot_vga */
boot_vga = g_udev_device_get_sysfs_attr_as_int (pci_device, "boot_vga");
g_object_unref (pci_device);
if (boot_vga == 1)
{
/* found the boot_vga device */
path = g_strdup (g_udev_device_get_device_file (dev));
break;
}
}
g_list_free_full (devices, g_object_unref);
out:
g_object_unref (enumerator);
g_object_unref (gudev_client);
return path;
}
static gboolean
get_kms_fd (Login1Session *session_proxy,
int *fd_out)
const gchar *seat_id,
int *fd_out,
GError **error)
{
int major, minor;
int fd;
GError *error = NULL;
/* XXX -- use udev to find the DRM master device */
if (!get_device_info_from_path ("/dev/dri/card0", &major, &minor))
g_autofree gchar *path = get_primary_gpu_path (seat_id);
if (!path)
{
g_warning ("Could not stat /dev/dri/card0: %m");
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_NOT_FOUND,
"could not find drm kms device");
return FALSE;
}
if (!take_device (session_proxy, major, minor, &fd, NULL, &error))
if (!get_device_info_from_path (path, &major, &minor))
{
g_warning ("Could not open DRM device: %s\n", error->message);
g_error_free (error);
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_NOT_FOUND,
"Could not get device info for path %s: %m", path);
return FALSE;
}
if (!take_device (session_proxy, major, minor, &fd, NULL, error))
{
g_prefix_error (error, "Could not open DRM device: ");
return FALSE;
}
@@ -289,28 +388,75 @@ get_kms_fd (Login1Session *session_proxy,
return TRUE;
}
MetaLauncher *
meta_launcher_new (void)
static gchar *
get_seat_id (GError **error)
{
MetaLauncher *self = NULL;
Login1Session *session_proxy;
GError *error = NULL;
int kms_fd;
char *session_id, *seat_id;
int r;
session_proxy = get_session_proxy (NULL);
if (!login1_session_call_take_control_sync (session_proxy, FALSE, NULL, &error))
r = sd_pid_get_session (0, &session_id);
if (r < 0)
{
g_warning ("Could not take control: %s", error->message);
g_error_free (error);
goto out;
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_NOT_FOUND,
"Could not get session for PID: %s", g_strerror (-r));
return NULL;
}
if (!get_kms_fd (session_proxy, &kms_fd))
goto out;
r = sd_session_get_seat (session_id, &seat_id);
free (session_id);
if (r < 0)
{
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_NOT_FOUND,
"Could not get seat for session: %s", g_strerror (-r));
return NULL;
}
return seat_id;
}
MetaLauncher *
meta_launcher_new (GError **error)
{
MetaLauncher *self = NULL;
Login1Session *session_proxy = NULL;
Login1Seat *seat_proxy = NULL;
char *seat_id = NULL;
gboolean have_control = FALSE;
int kms_fd;
session_proxy = get_session_proxy (NULL, error);
if (!session_proxy)
goto fail;
if (!login1_session_call_take_control_sync (session_proxy, FALSE, NULL, error))
{
g_prefix_error (error, "Could not take control: ");
goto fail;
}
have_control = TRUE;
seat_id = get_seat_id (error);
if (!seat_id)
goto fail;
seat_proxy = get_seat_proxy (NULL, error);
if (!seat_proxy)
goto fail;
if (!get_kms_fd (session_proxy, seat_id, &kms_fd, error))
goto fail;
free (seat_id);
self = g_slice_new0 (MetaLauncher);
self->session_proxy = g_object_ref (session_proxy);
self->seat_proxy = get_seat_proxy (NULL);
self->session_proxy = session_proxy;
self->seat_proxy = seat_proxy;
self->session_active = TRUE;
@@ -320,11 +466,16 @@ meta_launcher_new (void)
self);
g_signal_connect (self->session_proxy, "notify::active", G_CALLBACK (on_active_changed), self);
out:
g_object_unref (session_proxy);
return self;
fail:
if (have_control)
login1_session_call_release_control_sync (session_proxy, NULL, NULL);
g_clear_object (&session_proxy);
g_clear_object (&seat_proxy);
free (seat_id);
return NULL;
}
void

View File

@@ -24,7 +24,7 @@
typedef struct _MetaLauncher MetaLauncher;
MetaLauncher *meta_launcher_new (void);
MetaLauncher *meta_launcher_new (GError **error);
void meta_launcher_free (MetaLauncher *self);
gboolean meta_launcher_activate_session (MetaLauncher *self,

View File

@@ -40,7 +40,11 @@
#include "meta-idle-monitor-xsync.h"
#include "meta-monitor-manager-xrandr.h"
#include "backends/meta-monitor-manager-dummy.h"
#include "backends/x11/nested/meta-cursor-renderer-x11-nested.h"
#include "meta-cursor-renderer-x11.h"
#ifdef HAVE_WAYLAND
#include "wayland/meta-wayland.h"
#endif
#include <meta/util.h>
#include "display-private.h"
@@ -78,6 +82,7 @@ struct _MetaBackendX11Private
gchar *keymap_layouts;
gchar *keymap_variants;
gchar *keymap_options;
int locked_group;
};
typedef struct _MetaBackendX11Private MetaBackendX11Private;
@@ -269,20 +274,47 @@ handle_host_xevent (MetaBackend *backend,
}
}
if (priv->mode == META_BACKEND_X11_MODE_NESTED && event->type == FocusIn)
{
#ifdef HAVE_WAYLAND
Window xwin = meta_backend_x11_get_xwindow(x11);
XEvent xev;
if (event->xfocus.window == xwin)
{
/* Since we've selected for KeymapStateMask, every FocusIn is followed immediately
* by a KeymapNotify event */
XMaskEvent(priv->xdisplay, KeymapStateMask, &xev);
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
meta_wayland_compositor_update_key_state (compositor, xev.xkeymap.key_vector, 32, 8);
}
#else
g_assert_not_reached ();
#endif
}
if (event->type == (priv->xsync_event_base + XSyncAlarmNotify))
handle_alarm_notify (backend, event);
if (event->type == priv->xkb_event_base)
{
XkbAnyEvent *xkb_ev = (XkbAnyEvent *) event;
XkbEvent *xkb_ev = (XkbEvent *) event;
if (xkb_ev->device == META_VIRTUAL_CORE_KEYBOARD_ID)
if (xkb_ev->any.device == META_VIRTUAL_CORE_KEYBOARD_ID)
{
switch (xkb_ev->xkb_type)
switch (xkb_ev->any.xkb_type)
{
case XkbNewKeyboardNotify:
case XkbMapNotify:
keymap_changed (backend);
break;
case XkbStateNotify:
if (xkb_ev->state.changed & XkbGroupLockMask)
{
if (priv->locked_group != xkb_ev->state.locked_group)
XkbLockGroup (priv->xdisplay, XkbUseCoreKbd, priv->locked_group);
}
break;
default:
break;
}
@@ -418,6 +450,7 @@ meta_backend_x11_post_init (MetaBackend *backend)
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
int major, minor;
gboolean has_xi = FALSE;
priv->xdisplay = clutter_x11_get_default_display ();
@@ -427,27 +460,23 @@ meta_backend_x11_post_init (MetaBackend *backend)
!XSyncInitialize (priv->xdisplay, &major, &minor))
meta_fatal ("Could not initialize XSync");
{
int major = 2, minor = 3;
gboolean has_xi = FALSE;
if (XQueryExtension (priv->xdisplay,
"XInputExtension",
&priv->xinput_opcode,
&priv->xinput_error_base,
&priv->xinput_event_base))
{
major = 2; minor = 3;
if (XIQueryVersion (priv->xdisplay, &major, &minor) == Success)
{
int version = (major * 10) + minor;
if (version >= 22)
has_xi = TRUE;
}
}
if (XQueryExtension (priv->xdisplay,
"XInputExtension",
&priv->xinput_opcode,
&priv->xinput_error_base,
&priv->xinput_event_base))
{
if (XIQueryVersion (priv->xdisplay, &major, &minor) == Success)
{
int version = (major * 10) + minor;
if (version >= 22)
has_xi = TRUE;
}
}
if (!has_xi)
meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
}
if (!has_xi)
meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
/* We only take the passive touch grab if we are a X11 compositor */
if (priv->mode == META_BACKEND_X11_MODE_COMPOSITOR)
@@ -499,7 +528,20 @@ meta_backend_x11_create_monitor_manager (MetaBackend *backend)
static MetaCursorRenderer *
meta_backend_x11_create_cursor_renderer (MetaBackend *backend)
{
return g_object_new (META_TYPE_CURSOR_RENDERER_X11, NULL);
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
switch (priv->mode)
{
case META_BACKEND_X11_MODE_COMPOSITOR:
return g_object_new (META_TYPE_CURSOR_RENDERER_X11, NULL);
break;
case META_BACKEND_X11_MODE_NESTED:
return g_object_new (META_TYPE_CURSOR_RENDERER_X11_NESTED, NULL);
break;
default:
g_assert_not_reached ();
}
}
static gboolean
@@ -727,6 +769,9 @@ meta_backend_x11_get_keymap (MetaBackend *backend)
priv->xcb,
xkb_x11_get_core_keyboard_device_id (priv->xcb),
XKB_KEYMAP_COMPILE_NO_FLAGS);
if (priv->keymap == NULL)
priv->keymap = xkb_keymap_new_from_names (context, NULL, XKB_KEYMAP_COMPILE_NO_FLAGS);
xkb_context_unref (context);
}
@@ -740,6 +785,7 @@ meta_backend_x11_lock_layout_group (MetaBackend *backend,
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
priv->locked_group = idx;
XkbLockGroup (priv->xdisplay, XkbUseCoreKbd, idx);
}
@@ -759,8 +805,6 @@ meta_backend_x11_update_screen_size (MetaBackend *backend,
}
else
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
Window xwin = meta_backend_x11_get_xwindow (x11);
XResizeWindow (priv->xdisplay, xwin, width, height);
}
@@ -800,6 +844,20 @@ meta_backend_x11_select_stage_events (MetaBackend *backend)
}
XISelectEvents (priv->xdisplay, xwin, &mask, 1);
if (priv->mode == META_BACKEND_X11_MODE_NESTED)
{
/* We have no way of tracking key changes when the stage doesn't have
* focus, so we select for KeymapStateMask so that we get a complete
* dump of the keyboard state in a KeymapNotify event that immediately
* follows each FocusIn (and EnterNotify, but we ignore that.)
*/
XWindowAttributes xwa;
XGetWindowAttributes(priv->xdisplay, xwin, &xwa);
XSelectInput(priv->xdisplay, xwin,
xwa.your_event_mask | FocusChangeMask | KeymapStateMask);
}
}
static void

View File

@@ -40,25 +40,29 @@ typedef struct _MetaCursorRendererX11Private MetaCursorRendererX11Private;
G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererX11, meta_cursor_renderer_x11, META_TYPE_CURSOR_RENDERER);
static gboolean
meta_cursor_renderer_x11_update_cursor (MetaCursorRenderer *renderer)
meta_cursor_renderer_x11_update_cursor (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite)
{
MetaCursorRendererX11 *x11 = META_CURSOR_RENDERER_X11 (renderer);
MetaCursorRendererX11Private *priv = meta_cursor_renderer_x11_get_instance_private (x11);
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
Window xwindow = meta_backend_x11_get_xwindow (backend);
if (xwindow == None)
return FALSE;
Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
MetaCursorReference *cursor_ref = meta_cursor_renderer_get_cursor (renderer);
if (xwindow == None)
{
if (cursor_sprite)
meta_cursor_sprite_realize_texture (cursor_sprite);
return FALSE;
}
gboolean has_server_cursor = FALSE;
if (cursor_ref)
if (cursor_sprite)
{
MetaCursor cursor = meta_cursor_reference_get_meta_cursor (cursor_ref);
MetaCursor cursor = meta_cursor_sprite_get_meta_cursor (cursor_sprite);
if (cursor != META_CURSOR_NONE)
{
Cursor xcursor = meta_cursor_create_x_cursor (xdisplay, cursor);
@@ -80,6 +84,9 @@ meta_cursor_renderer_x11_update_cursor (MetaCursorRenderer *renderer)
priv->server_cursor_visible = has_server_cursor;
}
if (!priv->server_cursor_visible && cursor_sprite)
meta_cursor_sprite_realize_texture (cursor_sprite);
return priv->server_cursor_visible;
}

View File

@@ -637,6 +637,70 @@ output_get_connector_type (MetaMonitorManagerXrandr *manager_xrandr,
return META_CONNECTOR_TYPE_Unknown;
}
static void
output_get_modes (MetaMonitorManager *manager,
MetaOutput *meta_output,
XRROutputInfo *output)
{
guint j, k;
guint n_actual_modes;
meta_output->modes = g_new0 (MetaMonitorMode *, output->nmode);
n_actual_modes = 0;
for (j = 0; j < (guint)output->nmode; j++)
{
for (k = 0; k < manager->n_modes; k++)
{
if (output->modes[j] == (XID)manager->modes[k].mode_id)
{
meta_output->modes[n_actual_modes] = &manager->modes[k];
n_actual_modes += 1;
break;
}
}
}
meta_output->n_modes = n_actual_modes;
if (n_actual_modes > 0)
meta_output->preferred_mode = meta_output->modes[0];
}
static void
output_get_crtcs (MetaMonitorManager *manager,
MetaOutput *meta_output,
XRROutputInfo *output)
{
guint j, k;
guint n_actual_crtcs;
meta_output->possible_crtcs = g_new0 (MetaCRTC *, output->ncrtc);
n_actual_crtcs = 0;
for (j = 0; j < (unsigned)output->ncrtc; j++)
{
for (k = 0; k < manager->n_crtcs; k++)
{
if ((XID)manager->crtcs[k].crtc_id == output->crtcs[j])
{
meta_output->possible_crtcs[n_actual_crtcs] = &manager->crtcs[k];
n_actual_crtcs += 1;
break;
}
}
}
meta_output->n_possible_crtcs = n_actual_crtcs;
meta_output->crtc = NULL;
for (j = 0; j < manager->n_crtcs; j++)
{
if ((XID)manager->crtcs[j].crtc_id == output->crtc)
{
meta_output->crtc = &manager->crtcs[j];
break;
}
}
}
static char *
get_xmode_name (XRRModeInfo *xmode)
{
@@ -773,6 +837,8 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
MetaOutput *meta_output;
output = XRRGetOutputInfo (manager_xrandr->xdisplay, resources, resources->outputs[i]);
if (!output)
continue;
meta_output = &manager->outputs[n_actual_outputs];
@@ -796,44 +862,8 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
meta_output->connector_type = output_get_connector_type (manager_xrandr, meta_output);
output_get_tile_info (manager_xrandr, meta_output);
meta_output->n_modes = output->nmode;
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
for (j = 0; j < meta_output->n_modes; j++)
{
for (k = 0; k < manager->n_modes; k++)
{
if (output->modes[j] == (XID)manager->modes[k].mode_id)
{
meta_output->modes[j] = &manager->modes[k];
break;
}
}
}
meta_output->preferred_mode = meta_output->modes[0];
meta_output->n_possible_crtcs = output->ncrtc;
meta_output->possible_crtcs = g_new0 (MetaCRTC *, meta_output->n_possible_crtcs);
for (j = 0; j < (unsigned)output->ncrtc; j++)
{
for (k = 0; k < manager->n_crtcs; k++)
{
if ((XID)manager->crtcs[k].crtc_id == output->crtcs[j])
{
meta_output->possible_crtcs[j] = &manager->crtcs[k];
break;
}
}
}
meta_output->crtc = NULL;
for (j = 0; j < manager->n_crtcs; j++)
{
if ((XID)manager->crtcs[j].crtc_id == output->crtc)
{
meta_output->crtc = &manager->crtcs[j];
break;
}
}
output_get_modes (manager, meta_output, output);
output_get_crtcs (manager, meta_output, output);
meta_output->n_possible_clones = output->nclone;
meta_output->possible_clones = g_new0 (MetaOutput *, meta_output->n_possible_clones);
@@ -857,7 +887,10 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
else
meta_output->backlight = -1;
n_actual_outputs++;
if (meta_output->n_modes == 0 || meta_output->n_possible_crtcs == 0)
meta_monitor_manager_clear_output (meta_output);
else
n_actual_outputs++;
}
XRRFreeOutputInfo (output);
@@ -1133,17 +1166,16 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
if (crtc_info->mode != NULL)
{
MetaMonitorMode *mode;
g_autofree XID *outputs = NULL;
unsigned int j, n_outputs;
int width, height;
g_autofree XID *output_ids = NULL;
unsigned int j, n_output_ids;
Status ok;
mode = crtc_info->mode;
n_outputs = crtc_info->outputs->len;
outputs = g_new (XID, n_outputs);
n_output_ids = crtc_info->outputs->len;
output_ids = g_new (XID, n_output_ids);
for (j = 0; j < n_outputs; j++)
for (j = 0; j < n_output_ids; j++)
{
MetaOutput *output;
@@ -1152,7 +1184,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
output->is_dirty = TRUE;
output->crtc = crtc;
outputs[j] = output->winsys_id;
output_ids[j] = output->winsys_id;
}
ok = XRRSetCrtcConfig (manager_xrandr->xdisplay,
@@ -1162,7 +1194,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
crtc_info->x, crtc_info->y,
(XID)mode->mode_id,
meta_monitor_transform_to_xrandr (crtc_info->transform),
outputs, n_outputs);
output_ids, n_output_ids);
if (ok != Success)
{

View File

@@ -0,0 +1,89 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2015 Red Hat
*
* 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.
*
* Written by:
* Jonas Ådahl <jadahl@gmail.com>
*/
#include "config.h"
#include "backends/x11/nested/meta-cursor-renderer-x11-nested.h"
#include "backends/x11/meta-backend-x11.h"
struct _MetaCursorRendererX11Nested
{
MetaCursorRenderer parent;
};
G_DEFINE_TYPE (MetaCursorRendererX11Nested, meta_cursor_renderer_x11_nested,
META_TYPE_CURSOR_RENDERER);
static gboolean
meta_cursor_renderer_x11_nested_update_cursor (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite)
{
if (cursor_sprite)
meta_cursor_sprite_realize_texture (cursor_sprite);
return FALSE;
}
static Cursor
create_empty_cursor (Display *xdisplay)
{
XcursorImage *image;
XcursorPixel *pixels;
Cursor xcursor;
image = XcursorImageCreate (1, 1);
if (image == NULL)
return None;
image->xhot = 0;
image->yhot = 0;
pixels = image->pixels;
pixels[0] = 0;
xcursor = XcursorImageLoadCursor (xdisplay, image);
XcursorImageDestroy (image);
return xcursor;
}
static void
meta_cursor_renderer_x11_nested_init (MetaCursorRendererX11Nested *x11_nested)
{
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
Window xwindow = meta_backend_x11_get_xwindow (backend);
Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
Cursor empty_xcursor = create_empty_cursor (xdisplay);
XDefineCursor (xdisplay, xwindow, empty_xcursor);
XFreeCursor (xdisplay, empty_xcursor);
}
static void
meta_cursor_renderer_x11_nested_class_init (MetaCursorRendererX11NestedClass *klass)
{
MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_CLASS (klass);
renderer_class->update_cursor = meta_cursor_renderer_x11_nested_update_cursor;
}

View File

@@ -0,0 +1,38 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2015 Red Hat
*
* 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.
*
* Written by:
* Jonas Ådahl <jadahl@gmail.com>
*/
#ifndef META_CURSOR_RENDERER_X11_NESTED_NESTED_H
#define META_CURSOR_RENDERER_X11_NESTED_NESTED_H
#include <glib-object.h>
#include "backends/meta-cursor-renderer.h"
#define META_TYPE_CURSOR_RENDERER_X11_NESTED (meta_cursor_renderer_x11_nested_get_type ())
G_DECLARE_FINAL_TYPE (MetaCursorRendererX11Nested,
meta_cursor_renderer_x11_nested,
META, CURSOR_RENDERER_X11_NESTED,
MetaCursorRenderer);
#endif /* META_CURSOR_RENDERER_X11_NESTED_NESTED_H */

View File

@@ -779,7 +779,7 @@ meta_compositor_size_change_window (MetaCompositor *compositor,
MetaRectangle *old_buffer_rect)
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
meta_window_actor_size_change (window_actor, META_SIZE_CHANGE_MAXIMIZE, old_frame_rect, old_buffer_rect);
meta_window_actor_size_change (window_actor, which_change, old_frame_rect, old_buffer_rect);
}
void

View File

@@ -152,6 +152,7 @@ file_loaded (GObject *source_object,
{
MetaBackgroundImage *image = META_BACKGROUND_IMAGE (source_object);
GError *error = NULL;
CoglError *catch_error = NULL;
GTask *task;
CoglTexture *texture;
GdkPixbuf *pixbuf;
@@ -186,9 +187,10 @@ file_loaded (GObject *source_object,
has_alpha ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888,
row_stride,
pixels, 0,
NULL))
&catch_error))
{
g_warning ("Failed to create texture for background");
cogl_error_free (catch_error);
cogl_object_unref (texture);
}

View File

@@ -17,11 +17,14 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <meta/util.h>
#include <meta/meta-background.h>
#include <meta/meta-background-image.h>
#include "meta-background-private.h"
#include "cogl-utils.h"
#include <string.h>
enum
{
CHANGED,
@@ -71,6 +74,8 @@ enum
G_DEFINE_TYPE (MetaBackground, meta_background, G_TYPE_OBJECT)
static gboolean texture_has_alpha (CoglTexture *texture);
static GSList *all_backgrounds = NULL;
static void
@@ -474,7 +479,7 @@ get_texture_area (MetaBackground *self,
}
}
static void
static gboolean
draw_texture (MetaBackground *self,
CoglFramebuffer *framebuffer,
CoglPipeline *pipeline,
@@ -483,6 +488,7 @@ draw_texture (MetaBackground *self,
{
MetaBackgroundPrivate *priv = self->priv;
cairo_rectangle_int_t texture_area;
gboolean bare_region_visible;
get_texture_area (self, monitor_area, texture, &texture_area);
@@ -503,6 +509,9 @@ draw_texture (MetaBackground *self,
- texture_area.y / (float)texture_area.height,
(monitor_area->width - texture_area.x) / (float)texture_area.width,
(monitor_area->height - texture_area.y) / (float)texture_area.height);
bare_region_visible = texture_has_alpha (texture);
/* Draw just the texture */
break;
case G_DESKTOP_BACKGROUND_STYLE_CENTERED:
@@ -513,11 +522,16 @@ draw_texture (MetaBackground *self,
texture_area.x + texture_area.width,
texture_area.y + texture_area.height,
0, 0, 1.0, 1.0);
bare_region_visible = texture_has_alpha (texture) || memcmp (&texture_area, monitor_area, sizeof (cairo_rectangle_int_t)) != 0;
break;
case G_DESKTOP_BACKGROUND_STYLE_NONE:
bare_region_visible = TRUE;
break;
default:
g_return_if_reached();
g_return_val_if_reached(FALSE);
}
return bare_region_visible;
}
static void
@@ -529,6 +543,7 @@ ensure_color_texture (MetaBackground *self)
{
ClutterBackend *backend = clutter_get_default_backend ();
CoglContext *ctx = clutter_backend_get_cogl_context (backend);
CoglError *error = NULL;
uint8_t pixels[6];
int width, height;
@@ -569,7 +584,13 @@ ensure_color_texture (MetaBackground *self)
COGL_PIXEL_FORMAT_RGB_888,
width * 3,
pixels,
NULL));
&error));
if (error != NULL)
{
meta_warning ("Failed to allocate color texture: %s\n", error->message);
cogl_error_free (error);
}
}
}
@@ -748,6 +769,7 @@ meta_background_get_texture (MetaBackground *self,
if (monitor->dirty)
{
CoglError *catch_error = NULL;
gboolean bare_region_visible = FALSE;
if (monitor->texture == NULL)
{
@@ -783,9 +805,9 @@ meta_background_get_texture (MetaBackground *self,
cogl_pipeline_set_layer_texture (pipeline, 0, texture2);
cogl_pipeline_set_layer_wrap_mode (pipeline, 0, get_wrap_mode (priv->style));
draw_texture (self,
monitor->fbo, pipeline,
texture2, &monitor_area);
bare_region_visible = draw_texture (self,
monitor->fbo, pipeline,
texture2, &monitor_area);
cogl_object_unref (pipeline);
}
@@ -796,8 +818,7 @@ meta_background_get_texture (MetaBackground *self,
0.0, 0.0, 0.0, 0.0);
}
if (texture1 != NULL &&
!(texture2 != NULL && priv->blend_factor == 1.0 && !texture_has_alpha (texture2)))
if (texture1 != NULL && priv->blend_factor != 1.0)
{
CoglPipeline *pipeline = create_pipeline (PIPELINE_ADD);
cogl_pipeline_set_color4f (pipeline,
@@ -808,15 +829,14 @@ meta_background_get_texture (MetaBackground *self,
cogl_pipeline_set_layer_texture (pipeline, 0, texture1);
cogl_pipeline_set_layer_wrap_mode (pipeline, 0, get_wrap_mode (priv->style));
draw_texture (self,
monitor->fbo, pipeline,
texture1, &monitor_area);
bare_region_visible = bare_region_visible || draw_texture (self,
monitor->fbo, pipeline,
texture1, &monitor_area);
cogl_object_unref (pipeline);
}
if (!((texture2 != NULL && priv->blend_factor == 1.0 && !texture_has_alpha (texture2)) ||
(texture1 != NULL && !texture_has_alpha (texture1))))
if (bare_region_visible)
{
CoglPipeline *pipeline = create_pipeline (PIPELINE_OVER_REVERSE);

View File

@@ -27,6 +27,7 @@
#include <string.h>
#include <meta/meta-shadow-factory.h>
#include <meta/util.h>
#include "cogl-utils.h"
#include "region-utils.h"
@@ -707,6 +708,7 @@ make_shadow (MetaShadow *shadow,
{
ClutterBackend *backend = clutter_get_default_backend ();
CoglContext *ctx = clutter_backend_get_cogl_context (backend);
CoglError *error = NULL;
int d = get_box_filter_size (shadow->key.radius);
int spread = get_shadow_spread (shadow->key.radius);
cairo_rectangle_int_t extents;
@@ -804,7 +806,13 @@ make_shadow (MetaShadow *shadow,
(buffer +
(y_offset - shadow->outer_border_top) * buffer_width +
(x_offset - shadow->outer_border_left)),
NULL));
&error));
if (error)
{
meta_warning ("Failed to allocate shadow texture: %s\n", error->message);
cogl_error_free (error);
}
cairo_region_destroy (row_convolve_region);
cairo_region_destroy (column_convolve_region);

View File

@@ -293,8 +293,12 @@ static MetaWindow *
meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor)
{
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (META_SURFACE_ACTOR_WAYLAND (actor));
MetaWaylandSurface *surface = priv->surface;
return priv->surface->window;
if (!surface)
return NULL;
return surface->window;
}
static void

View File

@@ -102,8 +102,7 @@ detach_pixmap (MetaSurfaceActorX11 *self)
priv->pixmap = None;
meta_error_trap_pop (display);
cogl_object_unref (priv->texture);
priv->texture = NULL;
g_clear_pointer (&priv->texture, cogl_object_unref);
}
static void
@@ -114,14 +113,20 @@ set_pixmap (MetaSurfaceActorX11 *self,
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
CoglError *error = NULL;
CoglTexture *texture;
g_assert (priv->pixmap == None);
priv->pixmap = pixmap;
texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, priv->pixmap, FALSE, NULL));
texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, priv->pixmap, FALSE, &error));
if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture))))
if (error != NULL)
{
g_warning ("Failed to allocate stex texture: %s", error->message);
cogl_error_free (error);
}
else if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture))))
g_warning ("NOTE: Not using GLX TFP!\n");
priv->texture = texture;

View File

@@ -832,21 +832,23 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
return TRUE;
/*
* Do not add shadows to non-opaque windows; eventually we should generate
* a shadow from the input shape for such windows.
* Do not add shadows to non-opaque (ARGB32) windows, as we can't easily
* generate shadows for them.
*/
if (is_non_opaque (self))
return FALSE;
/*
* Add shadows to override redirect windows on X11 unless the toolkit
* indicates that it is handling shadows itself (e.g., Gtk menus).
* If a window specifies that it has custom frame extents, that likely
* means that it is drawing a shadow itself. Don't draw our own.
*/
if (priv->window->override_redirect &&
!priv->window->has_custom_frame_extents)
return TRUE;
if (priv->window->has_custom_frame_extents)
return FALSE;
return FALSE;
/*
* Generate shadows for all other windows.
*/
return TRUE;
}
/**
@@ -1750,9 +1752,17 @@ build_and_scan_frame_mask (MetaWindowActor *self,
}
else
{
CoglError *error = NULL;
mask_texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx, tex_width, tex_height,
COGL_PIXEL_FORMAT_A_8,
stride, mask_data, NULL));
stride, mask_data, &error));
if (error)
{
g_warning ("Failed to allocate mask texture: %s", error->message);
cogl_error_free (error);
}
}
meta_shaped_texture_set_mask_texture (stex, mask_texture);

View File

@@ -547,7 +547,7 @@ meta_display_open (void)
guint32 timestamp;
/* A list of all atom names, so that we can intern them in one go. */
char *atom_names[] = {
const char *atom_names[] = {
#define item(x) #x,
#include <x11/atomnames.h>
#undef item
@@ -605,14 +605,13 @@ meta_display_open (void)
meta_prefs_add_listener (prefs_changed_callback, display);
meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names));
XInternAtoms (display->xdisplay, atom_names, G_N_ELEMENTS (atom_names),
XInternAtoms (display->xdisplay, (char **)atom_names, G_N_ELEMENTS (atom_names),
False, atoms);
{
int i = 0;
i = 0;
#define item(x) display->atom_##x = atoms[i++];
#include <x11/atomnames.h>
#undef item
}
display->prop_hooks = NULL;
meta_display_init_window_prop_hooks (display);
@@ -1964,9 +1963,12 @@ meta_display_end_grab_op (MetaDisplay *display,
meta_topic (META_DEBUG_WINDOW_OPS,
"Ending grab op %u at time %u\n", grab_op, timestamp);
if (display->event_route == META_EVENT_ROUTE_NORMAL)
if (display->event_route == META_EVENT_ROUTE_NORMAL ||
display->event_route == META_EVENT_ROUTE_COMPOSITOR_GRAB)
return;
g_assert (grab_window != NULL);
g_signal_emit (display, display_signals[GRAB_OP_END], 0,
display->screen, grab_window, grab_op);

View File

@@ -206,8 +206,8 @@ meta_display_handle_event (MetaDisplay *display,
if (meta_is_wayland_compositor () && event->type == CLUTTER_MOTION)
{
MetaCursorTracker *tracker = meta_cursor_tracker_get_for_screen (NULL);
meta_cursor_tracker_update_position (tracker, event->motion.x, event->motion.y);
meta_cursor_tracker_update_position (meta_cursor_tracker_get_for_screen (NULL),
event->motion.x, event->motion.y);
display->monitor_cache_invalidated = TRUE;
}

View File

@@ -188,7 +188,7 @@ reload_modmap (MetaKeyBindingManager *keys)
/* Modifiers to find. */
struct {
char *name;
const char *name;
xkb_mod_mask_t *mask_p;
} mods[] = {
{ "ScrollLock", &scroll_lock_mask },

View File

@@ -44,7 +44,7 @@ print_version (const gchar *option_name,
exit (0);
}
static gchar *plugin = "default";
static const char *plugin = "default";
GOptionEntry mutter_options[] = {
{

View File

@@ -96,6 +96,10 @@ static gboolean bell_is_audible = TRUE;
static gboolean gnome_accessibility = FALSE;
static gboolean gnome_animations = TRUE;
static char *cursor_theme = NULL;
/* cursor_size will, when running as an X11 compositing window manager, be the
* actual cursor size, multiplied with the global window scaling factor. On
* Wayland, it will be the actual cursor size retrieved from gsettings.
*/
static int cursor_size = 24;
static int draggable_border_width = 10;
static int drag_threshold;
@@ -123,6 +127,9 @@ static gboolean update_binding (MetaKeyPref *binding,
static gboolean update_key_binding (const char *key,
gchar **strokes);
static void wayland_settings_changed (GSettings *settings,
gchar *key,
gpointer data);
static void settings_changed (GSettings *settings,
gchar *key,
gpointer data);
@@ -134,9 +141,10 @@ static void shell_shows_app_menu_changed (GtkSettings *settings,
GParamSpec *pspec,
gpointer data);
static void update_cursor_size (GtkSettings *settings,
GParamSpec *pspec,
gpointer data);
static void update_cursor_size_from_gtk (GtkSettings *settings,
GParamSpec *pspec,
gpointer data);
static void update_cursor_size (void);
static void queue_changed (MetaPreference pref);
@@ -161,8 +169,8 @@ typedef struct
typedef struct
{
char *key;
char *schema;
const char *key;
const char *schema;
MetaPreference pref;
} MetaBasePreference;
@@ -963,14 +971,18 @@ meta_prefs_init (void)
G_CALLBACK (settings_changed), NULL);
g_signal_connect (settings, "changed::" KEY_GNOME_CURSOR_THEME,
G_CALLBACK (settings_changed), NULL);
if (meta_is_wayland_compositor ())
g_signal_connect (settings, "changed::cursor-size",
G_CALLBACK (wayland_settings_changed), NULL);
g_hash_table_insert (settings_schemas, g_strdup (SCHEMA_INTERFACE), settings);
g_signal_connect (gtk_settings_get_default (),
"notify::gtk-shell-shows-app-menu",
G_CALLBACK (shell_shows_app_menu_changed), NULL);
g_signal_connect (gtk_settings_get_default (), "notify::gtk-cursor-theme-size",
G_CALLBACK (update_cursor_size), NULL);
if (!meta_is_wayland_compositor ())
g_signal_connect (gtk_settings_get_default (), "notify::gtk-cursor-theme-size",
G_CALLBACK (update_cursor_size_from_gtk), NULL);
settings = g_settings_new (SCHEMA_INPUT_SOURCES);
g_signal_connect (settings, "changed::" KEY_XKB_OPTIONS,
@@ -992,7 +1004,7 @@ meta_prefs_init (void)
handle_preference_init_string_array ();
handle_preference_init_int ();
update_cursor_size (gtk_settings_get_default (), NULL, NULL);
update_cursor_size ();
shell_shows_app_menu_changed (gtk_settings_get_default (), NULL, NULL);
init_bindings ();
@@ -1133,6 +1145,20 @@ meta_prefs_override_preference_schema (const char *key, const char *schema)
/****************************************************************************/
static void
wayland_settings_changed (GSettings *settings,
gchar *key,
gpointer data)
{
GVariant *value = g_settings_get_value (settings, key);
const GVariantType *type = g_variant_get_type (value);
g_return_if_fail (g_variant_type_equal (type, G_VARIANT_TYPE_INT32));
g_return_if_fail (g_str_equal (key, "cursor-size"));
update_cursor_size ();
}
static void
settings_changed (GSettings *settings,
gchar *key,
@@ -1216,9 +1242,29 @@ shell_shows_app_menu_changed (GtkSettings *settings,
}
static void
update_cursor_size (GtkSettings *settings,
GParamSpec *pspec,
gpointer data)
update_cursor_size (void)
{
if (meta_is_wayland_compositor ())
{
/* When running as a Wayland compositor, since we size of the cursor
* depends on what output it is on, we cannot use the GTK+
* "gtk-cursor-theme-size" setting because it has already been multiplied
* by the primary monitor scale. So, instead get the non-premultiplied
* cursor size value directly from gsettings instead.
*/
cursor_size =
g_settings_get_int (SETTINGS (SCHEMA_INTERFACE), "cursor-size");
}
else
{
update_cursor_size_from_gtk (gtk_settings_get_default (), NULL, NULL);
}
}
static void
update_cursor_size_from_gtk (GtkSettings *settings,
GParamSpec *pspec,
gpointer data)
{
GdkScreen *screen = gdk_screen_get_default ();
GValue value = G_VALUE_INIT;

View File

@@ -152,6 +152,10 @@ const MetaMonitorInfo* meta_screen_get_monitor_for_rect (MetaScreen *screen
const MetaMonitorInfo* meta_screen_calculate_monitor_for_window (MetaScreen *screen,
MetaWindow *window);
const MetaMonitorInfo* meta_screen_get_monitor_for_point (MetaScreen *screen,
int x,
int y);
const MetaMonitorInfo* meta_screen_get_monitor_neighbor (MetaScreen *screen,
int which_monitor,

View File

@@ -43,6 +43,7 @@
#include <meta/meta-enum-types.h>
#include "core.h"
#include "meta-cursor-tracker-private.h"
#include "boxes-private.h"
#include <X11/extensions/Xinerama.h>
#include <X11/extensions/Xcomposite.h>
@@ -1255,18 +1256,48 @@ update_num_workspaces (MetaScreen *screen,
g_object_notify (G_OBJECT (screen), "n-workspaces");
}
static void
root_cursor_prepare_at (MetaCursorSprite *cursor_sprite,
int x,
int y,
MetaScreen *screen)
{
const MetaMonitorInfo *monitor;
monitor = meta_screen_get_monitor_for_point (screen, x, y);
/* Reload the cursor texture if the scale has changed. */
if (monitor)
meta_cursor_sprite_set_theme_scale (cursor_sprite, monitor->scale);
}
static void
manage_root_cursor_sprite_scale (MetaScreen *screen,
MetaCursorSprite *cursor_sprite)
{
g_signal_connect_object (cursor_sprite,
"prepare-at",
G_CALLBACK (root_cursor_prepare_at),
screen,
0);
}
void
meta_screen_update_cursor (MetaScreen *screen)
{
MetaDisplay *display = screen->display;
MetaCursor cursor = screen->current_cursor;
Cursor xcursor;
MetaCursorReference *cursor_ref;
MetaCursorSprite *cursor_sprite;
MetaCursorTracker *tracker = meta_cursor_tracker_get_for_screen (screen);
cursor_ref = meta_cursor_reference_from_theme (cursor);
meta_cursor_tracker_set_root_cursor (tracker, cursor_ref);
meta_cursor_reference_unref (cursor_ref);
cursor_sprite = meta_cursor_sprite_from_theme (cursor);
if (meta_is_wayland_compositor ())
manage_root_cursor_sprite_scale (screen, cursor_sprite);
meta_cursor_tracker_set_root_cursor (tracker, cursor_sprite);
g_object_unref (cursor_sprite);
/* Set a cursor for X11 applications that don't specify their own */
xcursor = meta_display_create_x_cursor (display, cursor);
@@ -1454,6 +1485,25 @@ meta_screen_get_monitor_index_for_rect (MetaScreen *screen,
return monitor->number;
}
const MetaMonitorInfo *
meta_screen_get_monitor_for_point (MetaScreen *screen,
int x,
int y)
{
int i;
if (screen->n_monitor_infos == 1)
return &screen->monitor_infos[0];
for (i = 0; i < screen->n_monitor_infos; i++)
{
if (POINT_IN_RECT (x, y, screen->monitor_infos[i].rect))
return &screen->monitor_infos[i];
}
return NULL;
}
const MetaMonitorInfo*
meta_screen_get_monitor_neighbor (MetaScreen *screen,
int which_monitor,
@@ -2051,7 +2101,7 @@ meta_screen_queue_workarea_recalc (MetaScreen *screen)
#ifdef WITH_VERBOSE_MODE
static char *
static const char *
meta_screen_corner_to_string (MetaScreenCorner corner)
{
switch (corner)

View File

@@ -1055,7 +1055,7 @@ stack_sync_to_xserver (MetaStack *stack)
all_root_children_stacked = g_array_new (FALSE, FALSE, sizeof (guint64));
x11_hidden_stack_ids = g_array_new (FALSE, FALSE, sizeof (guint64));
meta_topic (META_DEBUG_STACK, "Top to bottom: ");
meta_topic (META_DEBUG_STACK, "Bottom to top: ");
meta_push_no_msg_prefix ();
for (tmp = g_list_last(stack->sorted); tmp != NULL; tmp = tmp->prev)
@@ -1088,11 +1088,7 @@ stack_sync_to_xserver (MetaStack *stack)
if (w->hidden)
{
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
{
guint64 stack_id = top_level_window;
g_array_append_val (x11_hidden_stack_ids, stack_id);
}
g_array_append_val (x11_hidden_stack_ids, top_level_window);
continue;
}

View File

@@ -30,7 +30,7 @@
#define NUM_RANDOM_RUNS 10000
static void
init_random_ness ()
init_random_ness (void)
{
srand(time(NULL));
}
@@ -99,7 +99,7 @@ new_monitor_edge (int x, int y, int width, int height, int side_type)
}
static void
test_area ()
test_area (void)
{
MetaRectangle temp;
int i;
@@ -116,7 +116,7 @@ test_area ()
}
static void
test_intersect ()
test_intersect (void)
{
MetaRectangle a = {100, 200, 50, 40};
MetaRectangle b = { 0, 50, 110, 152};
@@ -144,7 +144,7 @@ test_intersect ()
}
static void
test_equal ()
test_equal (void)
{
MetaRectangle a = {10, 12, 4, 18};
MetaRectangle b = a;
@@ -163,7 +163,7 @@ test_equal ()
}
static void
test_overlap_funcs ()
test_overlap_funcs (void)
{
MetaRectangle temp1, temp2;
int i;
@@ -186,7 +186,7 @@ test_overlap_funcs ()
}
static void
test_basic_fitting ()
test_basic_fitting (void)
{
MetaRectangle temp1, temp2, temp3;
int i;
@@ -357,7 +357,7 @@ get_monitor_edges (int which_monitor_set, int which_strut_set)
#if 0
static void
test_merge_regions ()
test_merge_regions (void)
{
/* logarithmically distributed random number of struts (range?)
* logarithmically distributed random size of struts (up to screen size???)
@@ -579,7 +579,7 @@ verify_lists_are_equal (GList *code, GList *answer)
}
static void
test_regions_okay ()
test_regions_okay (void)
{
GList* region;
GList* tmp;
@@ -665,7 +665,7 @@ test_regions_okay ()
}
static void
test_region_fitting ()
test_region_fitting (void)
{
GList* region;
MetaRectangle rect;
@@ -709,7 +709,7 @@ test_region_fitting ()
}
static void
test_clamping_to_region ()
test_clamping_to_region (void)
{
GList* region;
MetaRectangle rect;
@@ -826,7 +826,7 @@ rect_overlaps_region (const GList *spanning_rects,
gboolean time_to_print = FALSE;
static void
test_clipping_to_region ()
test_clipping_to_region (void)
{
GList* region;
MetaRectangle rect, temp;
@@ -888,7 +888,7 @@ test_clipping_to_region ()
}
static void
test_shoving_into_region ()
test_shoving_into_region (void)
{
GList* region;
MetaRectangle rect, temp;
@@ -1005,7 +1005,7 @@ verify_edge_lists_are_equal (GList *code, GList *answer)
}
static void
test_find_onscreen_edges ()
test_find_onscreen_edges (void)
{
GList* edges;
GList* tmp;
@@ -1138,7 +1138,7 @@ test_find_onscreen_edges ()
}
static void
test_find_nonintersected_monitor_edges ()
test_find_nonintersected_monitor_edges (void)
{
GList* edges;
GList* tmp;
@@ -1227,7 +1227,7 @@ test_find_nonintersected_monitor_edges ()
}
static void
test_gravity_resize ()
test_gravity_resize (void)
{
MetaRectangle oldrect, rect, temp;
@@ -1329,7 +1329,7 @@ test_gravity_resize ()
#define EPSILON 0.000000001
static void
test_find_closest_point_to_line ()
test_find_closest_point_to_line (void)
{
double x1, y1, x2, y2, px, py, rx, ry;
double answer_x, answer_y;
@@ -1381,7 +1381,7 @@ test_find_closest_point_to_line ()
}
int
main()
main(void)
{
init_random_ness ();
test_area ();

View File

@@ -46,7 +46,7 @@
static void
meta_topic_real_valist (MetaDebugTopic topic,
const char *format,
va_list args);
va_list args) G_GNUC_PRINTF(2, 0);
#endif
static gint verbose_topics = 0;

View File

@@ -763,10 +763,22 @@ meta_window_update_desc (MetaWindow *window)
{
g_clear_pointer (&window->desc, g_free);
if (window->title)
window->desc = g_strdup_printf ("0x%lx (%.10s)", window->xwindow, window->title);
if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
{
if (window->title)
window->desc = g_strdup_printf ("0x%lx (%.10s)", window->xwindow, window->title);
else
window->desc = g_strdup_printf ("0x%lx", window->xwindow);
}
else
window->desc = g_strdup_printf ("0x%lx", window->xwindow);
{
guint64 small_stamp = window->stamp - G_GUINT64_CONSTANT(0x100000000);
if (window->title)
window->desc = g_strdup_printf ("W%" G_GUINT64_FORMAT " (%.10s)", small_stamp, window->title);
else
window->desc = g_strdup_printf ("W%" G_GUINT64_FORMAT , small_stamp);
}
}
static void
@@ -3183,12 +3195,23 @@ meta_window_make_fullscreen (MetaWindow *window)
if (!window->fullscreen)
{
meta_window_make_fullscreen_internal (window);
MetaRectangle old_frame_rect, old_buffer_rect;
meta_window_get_frame_rect (window, &old_frame_rect);
meta_window_get_buffer_rect (window, &old_buffer_rect);
meta_window_make_fullscreen_internal (window);
meta_window_move_resize_internal (window,
META_MOVE_RESIZE_MOVE_ACTION | META_MOVE_RESIZE_RESIZE_ACTION | META_MOVE_RESIZE_STATE_CHANGED,
(META_MOVE_RESIZE_MOVE_ACTION |
META_MOVE_RESIZE_RESIZE_ACTION |
META_MOVE_RESIZE_STATE_CHANGED |
META_MOVE_RESIZE_DONT_SYNC_COMPOSITOR),
NorthWestGravity,
window->unconstrained_rect);
meta_compositor_size_change_window (window->display->compositor,
window, META_SIZE_CHANGE_FULLSCREEN,
&old_frame_rect, &old_buffer_rect);
}
}
@@ -3199,7 +3222,7 @@ meta_window_unmake_fullscreen (MetaWindow *window)
if (window->fullscreen)
{
MetaRectangle target_rect;
MetaRectangle old_frame_rect, old_buffer_rect, target_rect;
meta_topic (META_DEBUG_WINDOW_OPS,
"Unfullscreening %s\n", window->desc);
@@ -3208,6 +3231,8 @@ meta_window_unmake_fullscreen (MetaWindow *window)
target_rect = window->saved_rect;
meta_window_frame_size_changed (window);
meta_window_get_frame_rect (window, &old_frame_rect);
meta_window_get_buffer_rect (window, &old_buffer_rect);
/* Window's size hints may have changed while maximized, making
* saved_rect invalid. #329152
@@ -3222,10 +3247,17 @@ meta_window_unmake_fullscreen (MetaWindow *window)
set_net_wm_state (window);
meta_window_move_resize_internal (window,
META_MOVE_RESIZE_MOVE_ACTION | META_MOVE_RESIZE_RESIZE_ACTION | META_MOVE_RESIZE_STATE_CHANGED,
(META_MOVE_RESIZE_MOVE_ACTION |
META_MOVE_RESIZE_RESIZE_ACTION |
META_MOVE_RESIZE_STATE_CHANGED |
META_MOVE_RESIZE_DONT_SYNC_COMPOSITOR),
NorthWestGravity,
target_rect);
meta_compositor_size_change_window (window->display->compositor,
window, META_SIZE_CHANGE_UNFULLSCREEN,
&old_frame_rect, &old_buffer_rect);
meta_window_update_layer (window);
g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_FULLSCREEN]);
@@ -3502,10 +3534,7 @@ meta_window_update_for_monitors_changed (MetaWindow *window)
{
const MetaMonitorInfo *old, *new;
if (window->type == META_WINDOW_DESKTOP)
return;
if (window->override_redirect)
if (window->override_redirect || window->type == META_WINDOW_DESKTOP)
{
meta_window_update_monitor (window, FALSE);
return;
@@ -4312,8 +4341,8 @@ set_workspace_state (MetaWindow *window,
GList *l;
for (l = window->screen->workspaces; l != NULL; l = l->next)
{
MetaWorkspace *workspace = l->data;
meta_workspace_remove_window (workspace, window);
MetaWorkspace *ws = l->data;
meta_workspace_remove_window (ws, window);
}
}
@@ -4327,8 +4356,8 @@ set_workspace_state (MetaWindow *window,
GList *l;
for (l = window->screen->workspaces; l != NULL; l = l->next)
{
MetaWorkspace *workspace = l->data;
meta_workspace_add_window (workspace, window);
MetaWorkspace *ws = l->data;
meta_workspace_add_window (ws, window);
}
}
@@ -6272,7 +6301,7 @@ find_ancestor_func (MetaWindow *window,
* so by traversing the @transient's ancestors until it either locates @window
* or reaches an ancestor that is not transient.
*
* Return Value: (transfer none): %TRUE if window is an ancestor of transient.
* Return Value: %TRUE if window is an ancestor of transient.
*/
gboolean
meta_window_is_ancestor_of_transient (MetaWindow *window,
@@ -7010,7 +7039,7 @@ meta_window_get_transient_for (MetaWindow *window)
* Returns pid of the process that created this window, if known (obtained from
* the _NET_WM_PID property).
*
* Return value: (transfer none): the pid, or -1 if not known.
* Return value: the pid, or -1 if not known.
*/
int
meta_window_get_pid (MetaWindow *window)

View File

@@ -1055,7 +1055,7 @@ meta_workspace_get_onmonitor_region (MetaWorkspace *workspace,
}
#ifdef WITH_VERBOSE_MODE
static char *
static const char *
meta_motion_direction_to_string (MetaMotionDirection direction)
{
switch (direction)

View File

@@ -57,6 +57,8 @@ typedef enum
typedef enum {
META_SIZE_CHANGE_MAXIMIZE,
META_SIZE_CHANGE_UNMAXIMIZE,
META_SIZE_CHANGE_FULLSCREEN,
META_SIZE_CHANGE_UNFULLSCREEN,
} MetaSizeChange;
MetaCompositor *meta_compositor_new (MetaDisplay *display);

View File

@@ -49,7 +49,7 @@ typedef enum
} MetaExitCode;
/* exit immediately */
void meta_exit (MetaExitCode code);
void meta_exit (MetaExitCode code) G_GNUC_NORETURN;
/* g_main_loop_quit() then fall out of main() */
void meta_quit (MetaExitCode code);

View File

@@ -9,6 +9,8 @@
<method name="TakeControl">
<arg name="force" type="b"/>
</method>
<method name="ReleaseControl">
</method>
<method name="TakeDevice">
<annotation name="org.gtk.GDBus.C.UnixFD" value="true"/>
<arg name="major" type="u" direction="in"/>

View File

@@ -25,7 +25,7 @@
#include <string.h>
#include <X11/extensions/sync.h>
char *client_id = "0";
const char *client_id = "0";
static gboolean wayland;
GHashTable *windows;

View File

@@ -1094,7 +1094,6 @@ main (int argc, char **argv)
if (all_tests)
{
GFile *test_dir = g_file_new_for_path (MUTTER_PKGDATADIR "/tests");
GError *error = NULL;
if (!find_metatests_in_directory (test_dir, tests, &error))
{
@@ -1120,7 +1119,7 @@ main (int argc, char **argv)
/* Then initalize mutter with a different set of arguments */
char *fake_args[] = { NULL, "--wayland" };
char *fake_args[] = { NULL, (char *)"--wayland" };
fake_args[0] = argv[0];
char **fake_argv = fake_args;
int fake_argc = 2;

View File

@@ -915,11 +915,9 @@ meta_theme_get_default (void)
switch (frame_type)
{
case META_FRAME_TYPE_NORMAL:
break;
case META_FRAME_TYPE_DIALOG:
case META_FRAME_TYPE_MODAL_DIALOG:
case META_FRAME_TYPE_ATTACHED:
layout->hide_buttons = TRUE;
break;
case META_FRAME_TYPE_MENU:
case META_FRAME_TYPE_UTILITY:

View File

@@ -138,12 +138,19 @@ meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
for (i = 0; i < n_rectangles; i++)
{
CoglError *error = NULL;
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (region, i, &rect);
cogl_wayland_texture_set_region_from_shm_buffer (buffer->texture,
rect.x, rect.y, rect.width, rect.height,
shm_buffer,
rect.x, rect.y, 0, NULL);
rect.x, rect.y, 0, &error);
if (error)
{
meta_warning ("Failed to set texture region: %s\n", error->message);
cogl_error_free (error);
}
}
wl_shm_buffer_end_access (shm_buffer);

View File

@@ -57,8 +57,6 @@ typedef struct _MetaWaylandDataSourceWayland
struct wl_resource *resource;
} MetaWaylandDataSourceWayland;
GType meta_wayland_data_source_wayland_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandDataSource, meta_wayland_data_source,
G_TYPE_OBJECT);
G_DEFINE_TYPE (MetaWaylandDataSourceWayland, meta_wayland_data_source_wayland,
@@ -114,7 +112,7 @@ struct wl_array *
meta_wayland_data_source_get_mime_types (const MetaWaylandDataSource *source)
{
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
meta_wayland_data_source_get_instance_private ((MetaWaylandDataSource *)source);
return &priv->mime_types;
}
@@ -405,8 +403,8 @@ destroy_data_device_origin (struct wl_listener *listener, void *data)
wl_container_of (listener, drag_grab, drag_origin_listener);
drag_grab->drag_origin = NULL;
data_device_end_drag_grab (drag_grab);
meta_wayland_data_device_set_dnd_source (&drag_grab->seat->data_device, NULL);
data_device_end_drag_grab (drag_grab);
}
static void
@@ -415,8 +413,8 @@ drag_grab_data_source_destroyed (gpointer data, GObject *where_the_object_was)
MetaWaylandDragGrab *drag_grab = data;
drag_grab->drag_data_source = NULL;
data_device_end_drag_grab (drag_grab);
meta_wayland_data_device_set_dnd_source (&drag_grab->seat->data_device, NULL);
data_device_end_drag_grab (drag_grab);
}
static void
@@ -537,11 +535,14 @@ data_device_start_drag (struct wl_client *client,
drag_source = wl_resource_get_user_data (source_resource);
if (icon_resource &&
meta_wayland_surface_set_role (icon_surface,
META_WAYLAND_SURFACE_ROLE_DND,
resource,
WL_DATA_DEVICE_ERROR_ROLE) != 0)
return;
!meta_wayland_surface_assign_role (icon_surface,
META_TYPE_WAYLAND_SURFACE_ROLE_DND))
{
wl_resource_post_error (resource, WL_DATA_DEVICE_ERROR_ROLE,
"wl_surface@%d already has a different role",
wl_resource_get_id (icon_resource));
return;
}
meta_wayland_pointer_set_focus (&seat->pointer, NULL);
meta_wayland_data_device_start_drag (data_device, client,
@@ -742,12 +743,14 @@ meta_wayland_data_device_set_dnd_source (MetaWaylandDataDevice *data_device,
return;
if (data_device->dnd_data_source)
g_object_remove_weak_pointer (G_OBJECT (source),
g_object_remove_weak_pointer (G_OBJECT (data_device->dnd_data_source),
(gpointer *)&data_device->dnd_data_source);
data_device->dnd_data_source = source;
g_object_add_weak_pointer (G_OBJECT (source),
(gpointer *)&data_device->dnd_data_source);
if (source)
g_object_add_weak_pointer (G_OBJECT (data_device->dnd_data_source),
(gpointer *)&data_device->dnd_data_source);
wl_signal_emit (&data_device->dnd_ownership_signal, source);
}
@@ -909,6 +912,12 @@ meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_device)
MetaWaylandDataSource *source;
focus_client = meta_wayland_keyboard_get_focus_client (&seat->keyboard);
if (focus_client == data_device->focus_client)
return;
data_device->focus_client = focus_client;
if (!focus_client)
return;
@@ -957,7 +966,7 @@ meta_wayland_data_source_has_mime_type (const MetaWaylandDataSource *source,
const gchar *mime_type)
{
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
meta_wayland_data_source_get_instance_private ((MetaWaylandDataSource *)source);
gchar **p;
wl_array_for_each (p, &priv->mime_types)

View File

@@ -55,13 +55,12 @@ struct _MetaWaylandDataDevice
struct wl_listener selection_data_source_listener;
struct wl_list resource_list;
MetaWaylandDragGrab *current_grab;
struct wl_client *focus_client;
struct wl_signal selection_ownership_signal;
struct wl_signal dnd_ownership_signal;
};
GType meta_wayland_data_source_get_type (void) G_GNUC_CONST;
void meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor);
void meta_wayland_data_device_init (MetaWaylandDataDevice *data_device);

View File

@@ -477,6 +477,34 @@ meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
return handled;
}
void
meta_wayland_keyboard_update_key_state (MetaWaylandKeyboard *keyboard,
char *key_vector,
int key_vector_len,
int offset)
{
gboolean mods_changed = FALSE;
int i;
for (i = offset; i < key_vector_len * 8; i++)
{
gboolean set = (key_vector[i/8] & (1 << (i % 8))) != 0;
/* The 'offset' parameter allows the caller to have the indices
* into key_vector to either be X-style (base 8) or evdev (base 0), or
* something else (unlikely). We subtract 'offset' to convert to evdev
* style, then add 8 to convert the "evdev" style keycode back to
* the X-style that xkbcommon expects.
*/
mods_changed |= xkb_state_update_key (keyboard->xkb_info.state,
i - offset + 8,
set ? XKB_KEY_DOWN : XKB_KEY_UP);
}
if (mods_changed)
notify_modifiers (keyboard);
}
static void
move_resources (struct wl_list *destination, struct wl_list *source)
{

View File

@@ -85,6 +85,10 @@ void meta_wayland_keyboard_update (MetaWaylandKeyboard *keyboard,
gboolean meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
const ClutterKeyEvent *event);
void meta_wayland_keyboard_update_key_state (MetaWaylandKeyboard *compositor,
char *key_vector,
int key_vector_len,
int offset);
void meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard,
MetaWaylandSurface *surface);

View File

@@ -67,6 +67,15 @@ bind_pointer_gestures (struct wl_client *client,
struct wl_resource *resource;
resource = wl_resource_create (client, &_wl_pointer_gestures_interface, version, id);
if (version != META__WL_POINTER_GESTURES_VERSION)
{
wl_resource_post_error (resource,
_WL_POINTER_GESTURES_ERROR_VERSION_MISMATCH,
"The client bound a non-supported version");
return;
}
wl_resource_set_implementation (resource, &pointer_gestures_interface,
NULL, NULL);
}
@@ -76,6 +85,6 @@ meta_wayland_pointer_gestures_init (MetaWaylandCompositor *compositor)
{
wl_global_create (compositor->wayland_display,
&_wl_pointer_gestures_interface,
META_WL_POINTER_GESTURES_VERSION,
META__WL_POINTER_GESTURES_VERSION,
NULL, bind_pointer_gestures);
}

View File

@@ -44,20 +44,44 @@
#include "config.h"
#include <clutter/clutter.h>
#include <cogl/cogl.h>
#include <cogl/cogl-wayland-server.h>
#include <linux/input.h>
#include "meta-wayland-pointer.h"
#include "meta-wayland-popup.h"
#include "meta-wayland-private.h"
#include "meta-wayland-surface.h"
#include "meta-wayland-buffer.h"
#include "meta-xwayland.h"
#include "meta-cursor.h"
#include "meta-cursor-tracker-private.h"
#include "meta-surface-actor-wayland.h"
#include "meta/meta-cursor-tracker.h"
#include "backends/meta-backend-private.h"
#include "backends/meta-cursor-tracker-private.h"
#include "backends/meta-cursor-renderer.h"
#include <string.h>
#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int (10)
struct _MetaWaylandSurfaceRoleCursor
{
MetaWaylandSurfaceRole parent;
int hot_x;
int hot_y;
MetaCursorSprite *cursor_sprite;
};
G_DEFINE_TYPE (MetaWaylandSurfaceRoleCursor,
meta_wayland_surface_role_cursor,
META_TYPE_WAYLAND_SURFACE_ROLE);
static void
meta_wayland_pointer_update_cursor_surface (MetaWaylandPointer *pointer);
static MetaWaylandPointerClient *
meta_wayland_pointer_client_new (void)
{
@@ -205,32 +229,6 @@ sync_focus_surface (MetaWaylandPointer *pointer)
}
static void
set_cursor_surface (MetaWaylandPointer *pointer,
MetaWaylandSurface *surface)
{
if (pointer->cursor_surface == surface)
return;
if (pointer->cursor_surface)
wl_list_remove (&pointer->cursor_surface_destroy_listener.link);
pointer->cursor_surface = surface;
if (pointer->cursor_surface)
wl_resource_add_destroy_listener (pointer->cursor_surface->resource,
&pointer->cursor_surface_destroy_listener);
}
static void
pointer_handle_cursor_surface_destroy (struct wl_listener *listener, void *data)
{
MetaWaylandPointer *pointer = wl_container_of (listener, pointer, cursor_surface_destroy_listener);
set_cursor_surface (pointer, NULL);
meta_wayland_pointer_update_cursor_surface (pointer);
}
static void
pointer_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
{
@@ -349,10 +347,19 @@ static const MetaWaylandPointerGrabInterface default_pointer_grab_interface = {
default_grab_button
};
static void
meta_wayland_pointer_on_cursor_changed (MetaCursorTracker *cursor_tracker,
MetaWaylandPointer *pointer)
{
if (pointer->cursor_surface)
meta_wayland_surface_update_outputs (pointer->cursor_surface);
}
void
meta_wayland_pointer_init (MetaWaylandPointer *pointer,
struct wl_display *display)
{
MetaCursorTracker *cursor_tracker = meta_cursor_tracker_get_for_screen (NULL);
ClutterDeviceManager *manager;
memset (pointer, 0, sizeof *pointer);
@@ -366,7 +373,6 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer,
pointer->focus_surface_listener.notify = pointer_handle_focus_surface_destroy;
pointer->cursor_surface = NULL;
pointer->cursor_surface_destroy_listener.notify = pointer_handle_cursor_surface_destroy;
pointer->default_grab.interface = &default_pointer_grab_interface;
pointer->default_grab.pointer = pointer;
@@ -375,17 +381,26 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer,
manager = clutter_device_manager_get_default ();
pointer->device = clutter_device_manager_get_core_device (manager, CLUTTER_POINTER_DEVICE);
pointer->cursor_tracker = meta_cursor_tracker_get_for_screen (NULL);
g_signal_connect (cursor_tracker,
"cursor-changed",
G_CALLBACK (meta_wayland_pointer_on_cursor_changed),
pointer);
}
void
meta_wayland_pointer_release (MetaWaylandPointer *pointer)
{
MetaCursorTracker *cursor_tracker = meta_cursor_tracker_get_for_screen (NULL);
g_signal_handlers_disconnect_by_func (cursor_tracker,
(gpointer) meta_wayland_pointer_on_cursor_changed,
pointer);
meta_wayland_pointer_set_focus (pointer, NULL);
set_cursor_surface (pointer, NULL);
g_clear_pointer (&pointer->pointer_clients, g_hash_table_unref);
pointer->display = NULL;
pointer->cursor_surface = NULL;
}
static int
@@ -727,34 +742,108 @@ meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer,
*sy = wl_fixed_from_double (yf) / surface->scale;
}
void
static void
meta_wayland_pointer_update_cursor_surface (MetaWaylandPointer *pointer)
{
if (pointer->cursor_tracker == NULL)
return;
MetaCursorTracker *cursor_tracker = meta_cursor_tracker_get_for_screen (NULL);
if (pointer->current)
{
MetaCursorReference *cursor;
MetaCursorSprite *cursor_sprite = NULL;
if (pointer->cursor_surface && pointer->cursor_surface->buffer)
if (pointer->cursor_surface)
{
struct wl_resource *buffer = pointer->cursor_surface->buffer->resource;
cursor = meta_cursor_reference_from_buffer (buffer,
pointer->hotspot_x,
pointer->hotspot_y);
MetaWaylandSurfaceRoleCursor *cursor_role =
META_WAYLAND_SURFACE_ROLE_CURSOR (pointer->cursor_surface->role);
cursor_sprite = cursor_role->cursor_sprite;
}
else
cursor = NULL;
meta_cursor_tracker_set_window_cursor (pointer->cursor_tracker, cursor);
if (cursor)
meta_cursor_reference_unref (cursor);
meta_cursor_tracker_set_window_cursor (cursor_tracker, cursor_sprite);
}
else
{
meta_cursor_tracker_unset_window_cursor (pointer->cursor_tracker);
meta_cursor_tracker_unset_window_cursor (cursor_tracker);
}
}
static void
update_cursor_sprite_texture (MetaWaylandSurface *surface)
{
MetaCursorRenderer *cursor_renderer =
meta_backend_get_cursor_renderer (meta_get_backend ());
MetaCursorTracker *cursor_tracker = meta_cursor_tracker_get_for_screen (NULL);
MetaWaylandSurfaceRoleCursor *cursor_role =
META_WAYLAND_SURFACE_ROLE_CURSOR (surface->role);
MetaCursorSprite *cursor_sprite = cursor_role->cursor_sprite;
ClutterBackend *clutter_backend = clutter_get_default_backend ();
CoglContext *cogl_context =
clutter_backend_get_cogl_context (clutter_backend);
CoglTexture *texture;
if (surface->buffer)
{
struct wl_resource *buffer;
buffer = surface->buffer->resource;
texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context,
buffer,
NULL);
meta_cursor_sprite_set_texture (cursor_sprite,
texture,
cursor_role->hot_x * surface->scale,
cursor_role->hot_y * surface->scale);
meta_cursor_renderer_realize_cursor_from_wl_buffer (cursor_renderer,
cursor_sprite,
buffer);
cogl_object_unref (texture);
}
else
{
meta_cursor_sprite_set_texture (cursor_sprite, NULL, 0, 0);
}
if (cursor_sprite == meta_cursor_tracker_get_displayed_cursor (cursor_tracker))
meta_cursor_renderer_force_update (cursor_renderer);
}
static void
cursor_sprite_prepare_at (MetaCursorSprite *cursor_sprite,
int x,
int y,
MetaWaylandSurfaceRoleCursor *cursor_role)
{
MetaWaylandSurfaceRole *role = META_WAYLAND_SURFACE_ROLE (cursor_role);
MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (role);
MetaDisplay *display = meta_get_display ();
MetaScreen *screen = display->screen;
const MetaMonitorInfo *monitor;
if (!meta_xwayland_is_xwayland_surface (surface))
{
monitor = meta_screen_get_monitor_for_point (screen, x, y);
if (monitor)
meta_cursor_sprite_set_texture_scale (cursor_sprite,
(float)monitor->scale / surface->scale);
}
meta_wayland_surface_update_outputs (surface);
}
static void
meta_wayland_pointer_set_cursor_surface (MetaWaylandPointer *pointer,
MetaWaylandSurface *cursor_surface)
{
MetaWaylandSurface *prev_cursor_surface;
prev_cursor_surface = pointer->cursor_surface;
pointer->cursor_surface = cursor_surface;
if (prev_cursor_surface != cursor_surface)
{
if (prev_cursor_surface)
meta_wayland_surface_update_outputs (prev_cursor_surface);
meta_wayland_pointer_update_cursor_surface (pointer);
}
}
@@ -763,7 +852,7 @@ pointer_set_cursor (struct wl_client *client,
struct wl_resource *resource,
uint32_t serial,
struct wl_resource *surface_resource,
int32_t x, int32_t y)
int32_t hot_x, int32_t hot_y)
{
MetaWaylandPointer *pointer = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface;
@@ -777,19 +866,38 @@ pointer_set_cursor (struct wl_client *client,
if (pointer->focus_serial - serial > G_MAXUINT32 / 2)
return;
if (surface)
if (surface &&
!meta_wayland_surface_assign_role (surface,
META_TYPE_WAYLAND_SURFACE_ROLE_CURSOR))
{
if (meta_wayland_surface_set_role (surface,
META_WAYLAND_SURFACE_ROLE_CURSOR,
resource,
WL_POINTER_ERROR_ROLE) != 0)
return;
wl_resource_post_error (resource, WL_POINTER_ERROR_ROLE,
"wl_surface@%d already has a different role",
wl_resource_get_id (surface_resource));
return;
}
pointer->hotspot_x = x;
pointer->hotspot_y = y;
set_cursor_surface (pointer, surface);
meta_wayland_pointer_update_cursor_surface (pointer);
if (surface)
{
MetaWaylandSurfaceRoleCursor *cursor_role;
cursor_role = META_WAYLAND_SURFACE_ROLE_CURSOR (surface->role);
if (!cursor_role->cursor_sprite)
{
cursor_role->cursor_sprite = meta_cursor_sprite_new ();
g_signal_connect_object (cursor_role->cursor_sprite,
"prepare-at",
G_CALLBACK (cursor_sprite_prepare_at),
cursor_role,
0);
}
cursor_role->hot_x = hot_x;
cursor_role->hot_y = hot_y;
update_cursor_sprite_texture (surface);
}
meta_wayland_pointer_set_cursor_surface (pointer, surface);
}
static void
@@ -853,3 +961,99 @@ meta_wayland_pointer_get_top_popup (MetaWaylandPointer *pointer)
grab = (MetaWaylandPopupGrab*)pointer->grab;
return meta_wayland_popup_grab_get_top_popup(grab);
}
static void
cursor_surface_role_assigned (MetaWaylandSurfaceRole *surface_role)
{
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
meta_wayland_surface_queue_pending_frame_callbacks (surface);
}
static void
cursor_surface_role_commit (MetaWaylandSurfaceRole *surface_role,
MetaWaylandPendingState *pending)
{
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
meta_wayland_surface_queue_pending_state_frame_callbacks (surface, pending);
if (pending->newly_attached)
update_cursor_sprite_texture (surface);
}
static gboolean
cursor_surface_role_is_on_output (MetaWaylandSurfaceRole *role,
MetaMonitorInfo *monitor)
{
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (role);
MetaWaylandPointer *pointer = &surface->compositor->seat->pointer;
MetaCursorTracker *cursor_tracker = meta_cursor_tracker_get_for_screen (NULL);
MetaCursorRenderer *cursor_renderer =
meta_backend_get_cursor_renderer (meta_get_backend ());
MetaWaylandSurfaceRoleCursor *cursor_role =
META_WAYLAND_SURFACE_ROLE_CURSOR (surface->role);
MetaCursorSprite *displayed_cursor_sprite;
MetaRectangle rect;
if (surface != pointer->cursor_surface)
return FALSE;
displayed_cursor_sprite =
meta_cursor_tracker_get_displayed_cursor (cursor_tracker);
if (!displayed_cursor_sprite)
return FALSE;
if (cursor_role->cursor_sprite != displayed_cursor_sprite)
return FALSE;
rect = meta_cursor_renderer_calculate_rect (cursor_renderer,
cursor_role->cursor_sprite);
return meta_rectangle_overlap (&rect, &monitor->rect);
}
static void
cursor_surface_role_dispose (GObject *object)
{
MetaWaylandSurfaceRoleCursor *cursor_role =
META_WAYLAND_SURFACE_ROLE_CURSOR (object);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (META_WAYLAND_SURFACE_ROLE (object));
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaWaylandPointer *pointer = &compositor->seat->pointer;
MetaCursorTracker *cursor_tracker = meta_cursor_tracker_get_for_screen (NULL);
g_signal_handlers_disconnect_by_func (cursor_tracker,
(gpointer) cursor_sprite_prepare_at,
cursor_role);
if (pointer->cursor_surface == surface)
pointer->cursor_surface = NULL;
meta_wayland_pointer_update_cursor_surface (pointer);
g_clear_object (&cursor_role->cursor_sprite);
G_OBJECT_CLASS (meta_wayland_surface_role_cursor_parent_class)->dispose (object);
}
static void
meta_wayland_surface_role_cursor_init (MetaWaylandSurfaceRoleCursor *role)
{
}
static void
meta_wayland_surface_role_cursor_class_init (MetaWaylandSurfaceRoleCursorClass *klass)
{
MetaWaylandSurfaceRoleClass *surface_role_class =
META_WAYLAND_SURFACE_ROLE_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
surface_role_class->assigned = cursor_surface_role_assigned;
surface_role_class->commit = cursor_surface_role_commit;
surface_role_class->is_on_output = cursor_surface_role_is_on_output;
object_class->dispose = cursor_surface_role_dispose;
}

View File

@@ -27,9 +27,16 @@
#include "meta-wayland-types.h"
#include "meta-wayland-pointer-gesture-swipe.h"
#include "meta-wayland-pointer-gesture-pinch.h"
#include "meta-wayland-surface.h"
#include <meta/meta-cursor-tracker.h>
#define META_TYPE_WAYLAND_SURFACE_ROLE_CURSOR (meta_wayland_surface_role_cursor_get_type ())
G_DECLARE_FINAL_TYPE (MetaWaylandSurfaceRoleCursor,
meta_wayland_surface_role_cursor,
META, WAYLAND_SURFACE_ROLE_CURSOR,
MetaWaylandSurfaceRole);
struct _MetaWaylandPointerGrabInterface
{
void (*focus) (MetaWaylandPointerGrab *grab,
@@ -65,10 +72,7 @@ struct _MetaWaylandPointer
guint32 focus_serial;
guint32 click_serial;
MetaCursorTracker *cursor_tracker;
MetaWaylandSurface *cursor_surface;
struct wl_listener cursor_surface_destroy_listener;
int hotspot_x, hotspot_y;
MetaWaylandPointerGrab *grab;
MetaWaylandPointerGrab default_grab;
@@ -120,8 +124,6 @@ void meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer,
wl_fixed_t *x,
wl_fixed_t *y);
void meta_wayland_pointer_update_cursor_surface (MetaWaylandPointer *pointer);
void meta_wayland_pointer_create_new_resource (MetaWaylandPointer *pointer,
struct wl_client *client,
struct wl_resource *seat_resource,

View File

@@ -372,15 +372,6 @@ meta_wayland_seat_set_input_focus (MetaWaylandSeat *seat,
meta_wayland_data_device_set_keyboard_focus (&seat->data_device);
}
void
meta_wayland_seat_update_cursor_surface (MetaWaylandSeat *seat)
{
if ((seat->capabilities & WL_SEAT_CAPABILITY_POINTER) == 0)
return;
meta_wayland_pointer_update_cursor_surface (&seat->pointer);
}
gboolean
meta_wayland_seat_get_grab_info (MetaWaylandSeat *seat,
MetaWaylandSurface *surface,

View File

@@ -58,7 +58,6 @@ void meta_wayland_seat_set_input_focus (MetaWaylandSeat *seat,
MetaWaylandSurface *surface);
void meta_wayland_seat_repick (MetaWaylandSeat *seat);
void meta_wayland_seat_update_cursor_surface (MetaWaylandSeat *seat);
gboolean meta_wayland_seat_get_grab_info (MetaWaylandSeat *seat,
MetaWaylandSurface *surface,

View File

@@ -55,6 +55,11 @@
#include "meta-surface-actor-wayland.h"
#include "meta-xwayland-private.h"
typedef struct _MetaWaylandSurfaceRolePrivate
{
MetaWaylandSurface *surface;
} MetaWaylandSurfaceRolePrivate;
typedef enum
{
META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE,
@@ -68,24 +73,92 @@ typedef struct
struct wl_listener sibling_destroy_listener;
} MetaWaylandSubsurfacePlacementOp;
int
meta_wayland_surface_set_role (MetaWaylandSurface *surface,
MetaWaylandSurfaceRole role,
struct wl_resource *error_resource,
uint32_t error_code)
G_DEFINE_TYPE (MetaWaylandSurface, meta_wayland_surface, G_TYPE_OBJECT);
G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandSurfaceRole,
meta_wayland_surface_role,
G_TYPE_OBJECT);
struct _MetaWaylandSurfaceRoleSubsurface
{
if (surface->role == META_WAYLAND_SURFACE_ROLE_NONE ||
surface->role == role)
MetaWaylandSurfaceRole parent;
};
G_DEFINE_TYPE (MetaWaylandSurfaceRoleSubsurface,
meta_wayland_surface_role_subsurface,
META_TYPE_WAYLAND_SURFACE_ROLE);
struct _MetaWaylandSurfaceRoleXdgSurface
{
MetaWaylandSurfaceRole parent;
};
G_DEFINE_TYPE (MetaWaylandSurfaceRoleXdgSurface,
meta_wayland_surface_role_xdg_surface,
META_TYPE_WAYLAND_SURFACE_ROLE);
struct _MetaWaylandSurfaceRoleXdgPopup
{
MetaWaylandSurfaceRole parent;
};
G_DEFINE_TYPE (MetaWaylandSurfaceRoleXdgPopup,
meta_wayland_surface_role_xdg_popup,
META_TYPE_WAYLAND_SURFACE_ROLE);
struct _MetaWaylandSurfaceRoleWlShellSurface
{
MetaWaylandSurfaceRole parent;
};
G_DEFINE_TYPE (MetaWaylandSurfaceRoleWlShellSurface,
meta_wayland_surface_role_wl_shell_surface,
META_TYPE_WAYLAND_SURFACE_ROLE);
struct _MetaWaylandSurfaceRoleDND
{
MetaWaylandSurfaceRole parent;
};
G_DEFINE_TYPE (MetaWaylandSurfaceRoleDND,
meta_wayland_surface_role_dnd,
META_TYPE_WAYLAND_SURFACE_ROLE);
static void
meta_wayland_surface_role_assigned (MetaWaylandSurfaceRole *surface_role);
static void
meta_wayland_surface_role_commit (MetaWaylandSurfaceRole *surface_role,
MetaWaylandPendingState *pending);
static gboolean
meta_wayland_surface_role_is_on_output (MetaWaylandSurfaceRole *surface_role,
MetaMonitorInfo *info);
gboolean
meta_wayland_surface_assign_role (MetaWaylandSurface *surface,
GType role_type)
{
if (!surface->role)
{
surface->role = role;
return 0;
MetaWaylandSurfaceRolePrivate *role_priv;
surface->role = g_object_new (role_type, NULL);
role_priv =
meta_wayland_surface_role_get_instance_private (surface->role);
role_priv->surface = surface;
meta_wayland_surface_role_assigned (surface->role);
return TRUE;
}
else if (G_OBJECT_TYPE (surface->role) != role_type)
{
return FALSE;
}
else
{
wl_resource_post_error (error_resource, error_code,
"wl_surface@%d already has a different role",
wl_resource_get_id (surface->resource));
return -1;
return TRUE;
}
}
@@ -167,18 +240,24 @@ surface_process_damage (MetaWaylandSurface *surface,
cairo_region_destroy (scaled_region);
}
static void
cursor_surface_commit (MetaWaylandSurface *surface,
MetaWaylandPendingState *pending)
void
meta_wayland_surface_queue_pending_state_frame_callbacks (MetaWaylandSurface *surface,
MetaWaylandPendingState *pending)
{
if (pending->newly_attached)
meta_wayland_seat_update_cursor_surface (surface->compositor->seat);
wl_list_insert_list (&surface->compositor->frame_callbacks,
&pending->frame_callback_list);
wl_list_init (&pending->frame_callback_list);
}
static void
dnd_surface_commit (MetaWaylandSurface *surface,
dnd_surface_commit (MetaWaylandSurfaceRole *surface_role,
MetaWaylandPendingState *pending)
{
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
meta_wayland_surface_queue_pending_state_frame_callbacks (surface, pending);
meta_wayland_data_device_update_dnd_surface (&surface->compositor->seat->data_device);
}
@@ -235,12 +314,28 @@ destroy_window (MetaWaylandSurface *surface)
}
static void
toplevel_surface_commit (MetaWaylandSurface *surface,
queue_surface_actor_frame_callbacks (MetaWaylandSurface *surface,
MetaWaylandPendingState *pending)
{
MetaSurfaceActorWayland *surface_actor =
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
meta_surface_actor_wayland_add_frame_callbacks (surface_actor,
&pending->frame_callback_list);
wl_list_init (&pending->frame_callback_list);
}
static void
toplevel_surface_commit (MetaWaylandSurfaceRole *surface_role,
MetaWaylandPendingState *pending)
{
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
MetaWindow *window = surface->window;
if (surface->role == META_WAYLAND_SURFACE_ROLE_WL_SHELL_SURFACE)
queue_surface_actor_frame_callbacks (surface, pending);
if (META_IS_WAYLAND_SURFACE_ROLE_WL_SHELL_SURFACE (surface->role))
{
/* For wl_shell, it's equivalent to an unmap. Semantics
* are poorly defined, so we can choose some that are
@@ -256,12 +351,6 @@ toplevel_surface_commit (MetaWaylandSurface *surface,
return;
}
}
else if (surface->role == META_WAYLAND_SURFACE_ROLE_XDG_POPUP)
{
/* Ignore commits if we couldn't grab the pointer */
if (!window)
return;
}
else
{
if (surface->buffer == NULL)
@@ -274,10 +363,11 @@ toplevel_surface_commit (MetaWaylandSurface *surface,
}
}
g_assert (window != NULL);
/* We resize X based surfaces according to X events */
if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
/* Update the state of the MetaWindow if we still have one. We might not if
* the window was unmanaged (for example popup destroyed, NULL buffer attached to
* wl_shell_surface wl_surface, xdg_surface object was destroyed, etc).
*/
if (window && window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
{
MetaRectangle geom = { 0 };
@@ -392,12 +482,16 @@ move_pending_state (MetaWaylandPendingState *from,
}
static void
subsurface_surface_commit (MetaWaylandSurface *surface,
subsurface_surface_commit (MetaWaylandSurfaceRole *surface_role,
MetaWaylandPendingState *pending)
{
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
MetaSurfaceActorWayland *surface_actor =
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
queue_surface_actor_frame_callbacks (surface, pending);
if (surface->buffer != NULL)
clutter_actor_show (CLUTTER_ACTOR (surface_actor));
else
@@ -495,8 +589,6 @@ static void
apply_pending_state (MetaWaylandSurface *surface,
MetaWaylandPendingState *pending)
{
MetaWaylandCompositor *compositor = surface->compositor;
if (pending->newly_attached)
{
if (!surface->buffer && surface->window)
@@ -540,42 +632,20 @@ apply_pending_state (MetaWaylandSurface *surface,
surface->input_region = NULL;
}
/* wl_surface.frame */
switch (surface->role)
if (surface->role)
{
case META_WAYLAND_SURFACE_ROLE_NONE:
case META_WAYLAND_SURFACE_ROLE_CURSOR:
case META_WAYLAND_SURFACE_ROLE_DND:
wl_list_insert_list (&compositor->frame_callbacks, &pending->frame_callback_list);
break;
case META_WAYLAND_SURFACE_ROLE_XDG_SURFACE:
case META_WAYLAND_SURFACE_ROLE_XDG_POPUP:
case META_WAYLAND_SURFACE_ROLE_WL_SHELL_SURFACE:
case META_WAYLAND_SURFACE_ROLE_SUBSURFACE:
meta_surface_actor_wayland_add_frame_callbacks (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor),
&pending->frame_callback_list);
break;
meta_wayland_surface_role_commit (surface->role, pending);
g_assert (wl_list_empty (&pending->frame_callback_list));
}
wl_list_init (&pending->frame_callback_list);
switch (surface->role)
else
{
case META_WAYLAND_SURFACE_ROLE_NONE:
break;
case META_WAYLAND_SURFACE_ROLE_CURSOR:
cursor_surface_commit (surface, pending);
break;
case META_WAYLAND_SURFACE_ROLE_DND:
dnd_surface_commit (surface, pending);
break;
case META_WAYLAND_SURFACE_ROLE_XDG_SURFACE:
case META_WAYLAND_SURFACE_ROLE_XDG_POPUP:
case META_WAYLAND_SURFACE_ROLE_WL_SHELL_SURFACE:
toplevel_surface_commit (surface, pending);
break;
case META_WAYLAND_SURFACE_ROLE_SUBSURFACE:
subsurface_surface_commit (surface, pending);
break;
/* Since there is no role assigned to the surface yet, keep frame
* callbacks queued until a role is assigned and we know how
* the surface will be drawn.
*/
wl_list_insert_list (&surface->pending_frame_callback_list,
&pending->frame_callback_list);
wl_list_init (&pending->frame_callback_list);
}
meta_surface_actor_wayland_sync_state (
@@ -853,7 +923,6 @@ set_surface_is_on_output (MetaWaylandSurface *surface,
static void
surface_handle_output_destroy (MetaWaylandOutput *wayland_output,
GParamSpec *pspec,
MetaWaylandSurface *surface)
{
set_surface_is_on_output (surface, wayland_output, FALSE);
@@ -884,16 +953,28 @@ set_surface_is_on_output (MetaWaylandSurface *surface,
}
}
static gboolean
actor_surface_is_on_output (MetaWaylandSurfaceRole *surface_role,
MetaMonitorInfo *monitor)
{
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
MetaSurfaceActorWayland *actor =
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
return meta_surface_actor_wayland_is_on_monitor (actor, monitor);
}
static void
update_surface_output_state (gpointer key, gpointer value, gpointer user_data)
{
MetaWaylandOutput *wayland_output = value;
MetaWaylandSurface *surface = user_data;
MetaSurfaceActorWayland *actor =
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
MetaMonitorInfo *monitor;
gboolean is_on_output;
g_assert (surface->role);
monitor = wayland_output->monitor_info;
if (!monitor)
{
@@ -901,7 +982,7 @@ update_surface_output_state (gpointer key, gpointer value, gpointer user_data)
return;
}
is_on_output = meta_surface_actor_wayland_is_on_monitor (actor, monitor);
is_on_output = meta_wayland_surface_role_is_on_output (surface->role, monitor);
set_surface_is_on_output (surface, wayland_output, is_on_output);
}
@@ -930,6 +1011,9 @@ wl_surface_destructor (struct wl_resource *resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
MetaWaylandCompositor *compositor = surface->compositor;
MetaWaylandFrameCallback *cb, *next;
g_clear_object (&surface->role);
/* If we still have a window at the time of destruction, that means that
* the client is disconnecting, as the resources are destroyed in a random
@@ -954,6 +1038,9 @@ wl_surface_destructor (struct wl_resource *resource)
g_hash_table_unref (surface->outputs);
wl_list_for_each_safe (cb, next, &surface->pending_frame_callback_list, link)
wl_resource_destroy (cb->resource);
if (surface->resource)
wl_resource_set_user_data (surface->resource, NULL);
@@ -968,7 +1055,7 @@ wl_surface_destructor (struct wl_resource *resource)
if (surface->gtk_surface)
wl_resource_destroy (surface->gtk_surface);
g_slice_free (MetaWaylandSurface, surface);
g_object_unref (surface);
meta_wayland_compositor_repick (compositor);
}
@@ -979,7 +1066,7 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
struct wl_resource *compositor_resource,
guint32 id)
{
MetaWaylandSurface *surface = g_slice_new0 (MetaWaylandSurface);
MetaWaylandSurface *surface = g_object_new (META_TYPE_WAYLAND_SURFACE, NULL);
surface->compositor = compositor;
surface->scale = 1;
@@ -990,6 +1077,8 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
surface->buffer_destroy_listener.notify = surface_handle_buffer_destroy;
surface->surface_actor = g_object_ref_sink (meta_surface_actor_wayland_new (surface));
wl_list_init (&surface->pending_frame_callback_list);
sync_drag_dest_funcs (surface);
surface->outputs = g_hash_table_new (NULL, NULL);
@@ -1279,11 +1368,14 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
return;
}
if (meta_wayland_surface_set_role (surface,
META_WAYLAND_SURFACE_ROLE_XDG_SURFACE,
surface_resource,
XDG_SHELL_ERROR_ROLE) != 0)
return;
if (!meta_wayland_surface_assign_role (surface,
META_TYPE_WAYLAND_SURFACE_ROLE_XDG_SURFACE))
{
wl_resource_post_error (resource, XDG_SHELL_ERROR_ROLE,
"wl_surface@%d already has a different role",
wl_resource_get_id (surface->resource));
return;
}
surface->xdg_surface = wl_resource_create (client, &xdg_surface_interface, wl_resource_get_version (resource), id);
wl_resource_set_implementation (surface->xdg_surface, &meta_wayland_xdg_surface_interface, surface, xdg_surface_destructor);
@@ -1387,11 +1479,14 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
return;
}
if (meta_wayland_surface_set_role (surface,
META_WAYLAND_SURFACE_ROLE_XDG_POPUP,
surface_resource,
XDG_SHELL_ERROR_ROLE) != 0)
return;
if (!meta_wayland_surface_assign_role (surface,
META_TYPE_WAYLAND_SURFACE_ROLE_XDG_POPUP))
{
wl_resource_post_error (resource, XDG_SHELL_ERROR_ROLE,
"wl_surface@%d already has a different role",
wl_resource_get_id (surface->resource));
return;
}
if (parent_surf == NULL ||
parent_surf->window == NULL ||
@@ -1420,15 +1515,15 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
surface,
xdg_popup_destructor);
surface->xdg_popup = popup_resource;
surface->xdg_shell_resource = resource;
if (!meta_wayland_pointer_can_popup (&seat->pointer, serial))
{
xdg_popup_send_popup_done (popup_resource);
return;
}
surface->xdg_popup = popup_resource;
surface->xdg_shell_resource = resource;
surface->popup.parent = parent_surf;
surface->popup.parent_destroy_listener.notify = handle_popup_parent_destroyed;
wl_resource_add_destroy_listener (parent_surf->resource,
@@ -1727,11 +1822,14 @@ wl_shell_get_shell_surface (struct wl_client *client,
return;
}
if (meta_wayland_surface_set_role (surface,
META_WAYLAND_SURFACE_ROLE_WL_SHELL_SURFACE,
surface_resource,
WL_SHELL_ERROR_ROLE) != 0)
return;
if (!meta_wayland_surface_assign_role (surface,
META_TYPE_WAYLAND_SURFACE_ROLE_WL_SHELL_SURFACE))
{
wl_resource_post_error (resource, WL_SHELL_ERROR_ROLE,
"wl_surface@%d already has a different role",
wl_resource_get_id (surface->resource));
return;
}
surface->wl_shell_surface = wl_resource_create (client, &wl_shell_surface_interface, wl_resource_get_version (resource), id);
wl_resource_set_implementation (surface->wl_shell_surface, &meta_wayland_wl_shell_surface_interface, surface, wl_shell_surface_destructor);
@@ -2076,11 +2174,17 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
return;
}
if (meta_wayland_surface_set_role (surface,
META_WAYLAND_SURFACE_ROLE_SUBSURFACE,
surface_resource,
WL_SHELL_ERROR_ROLE) != 0)
return;
if (!meta_wayland_surface_assign_role (surface,
META_TYPE_WAYLAND_SURFACE_ROLE_SUBSURFACE))
{
/* FIXME: There is no subcompositor "role" error yet, so lets just use something
* similar until there is.
*/
wl_resource_post_error (resource, WL_SHELL_ERROR_ROLE,
"wl_surface@%d already has a different role",
wl_resource_get_id (surface->resource));
return;
}
surface->wl_subsurface = wl_resource_create (client, &wl_subsurface_interface, wl_resource_get_version (resource), id);
wl_resource_set_implementation (surface->wl_subsurface, &meta_wayland_wl_subsurface_interface, surface, wl_subsurface_destructor);
@@ -2290,3 +2394,168 @@ meta_wayland_surface_get_toplevel_window (MetaWaylandSurface *surface)
return NULL;
}
static void
meta_wayland_surface_init (MetaWaylandSurface *surface)
{
}
static void
meta_wayland_surface_class_init (MetaWaylandSurfaceClass *klass)
{
}
static void
meta_wayland_surface_role_init (MetaWaylandSurfaceRole *role)
{
}
static void
meta_wayland_surface_role_class_init (MetaWaylandSurfaceRoleClass *klass)
{
}
static void
meta_wayland_surface_role_assigned (MetaWaylandSurfaceRole *surface_role)
{
META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role)->assigned (surface_role);
}
static void
meta_wayland_surface_role_commit (MetaWaylandSurfaceRole *surface_role,
MetaWaylandPendingState *pending)
{
META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role)->commit (surface_role,
pending);
}
static gboolean
meta_wayland_surface_role_is_on_output (MetaWaylandSurfaceRole *surface_role,
MetaMonitorInfo *monitor)
{
MetaWaylandSurfaceRoleClass *klass;
klass = META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role);
if (klass->is_on_output)
return klass->is_on_output (surface_role, monitor);
else
return FALSE;
}
MetaWaylandSurface *
meta_wayland_surface_role_get_surface (MetaWaylandSurfaceRole *role)
{
MetaWaylandSurfaceRolePrivate *priv =
meta_wayland_surface_role_get_instance_private (role);
return priv->surface;
}
void
meta_wayland_surface_queue_pending_frame_callbacks (MetaWaylandSurface *surface)
{
wl_list_insert_list (&surface->compositor->frame_callbacks,
&surface->pending_frame_callback_list);
wl_list_init (&surface->pending_frame_callback_list);
}
static void
default_role_assigned (MetaWaylandSurfaceRole *surface_role)
{
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
meta_wayland_surface_queue_pending_frame_callbacks (surface);
}
static void
actor_surface_assigned (MetaWaylandSurfaceRole *surface_role)
{
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
MetaSurfaceActorWayland *surface_actor =
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
meta_surface_actor_wayland_add_frame_callbacks (surface_actor,
&surface->pending_frame_callback_list);
wl_list_init (&surface->pending_frame_callback_list);
}
static void
meta_wayland_surface_role_dnd_init (MetaWaylandSurfaceRoleDND *role)
{
}
static void
meta_wayland_surface_role_dnd_class_init (MetaWaylandSurfaceRoleDNDClass *klass)
{
MetaWaylandSurfaceRoleClass *surface_role_class =
META_WAYLAND_SURFACE_ROLE_CLASS (klass);
surface_role_class->assigned = default_role_assigned;
surface_role_class->commit = dnd_surface_commit;
}
static void
meta_wayland_surface_role_xdg_surface_init (MetaWaylandSurfaceRoleXdgSurface *role)
{
}
static void
meta_wayland_surface_role_xdg_surface_class_init (MetaWaylandSurfaceRoleXdgSurfaceClass *klass)
{
MetaWaylandSurfaceRoleClass *surface_role_class =
META_WAYLAND_SURFACE_ROLE_CLASS (klass);
surface_role_class->assigned = actor_surface_assigned;
surface_role_class->commit = toplevel_surface_commit;
surface_role_class->is_on_output = actor_surface_is_on_output;
}
static void
meta_wayland_surface_role_xdg_popup_init (MetaWaylandSurfaceRoleXdgPopup *role)
{
}
static void
meta_wayland_surface_role_xdg_popup_class_init (MetaWaylandSurfaceRoleXdgPopupClass *klass)
{
MetaWaylandSurfaceRoleClass *surface_role_class =
META_WAYLAND_SURFACE_ROLE_CLASS (klass);
surface_role_class->assigned = actor_surface_assigned;
surface_role_class->commit = toplevel_surface_commit;
surface_role_class->is_on_output = actor_surface_is_on_output;
}
static void
meta_wayland_surface_role_wl_shell_surface_init (MetaWaylandSurfaceRoleWlShellSurface *role)
{
}
static void
meta_wayland_surface_role_wl_shell_surface_class_init (MetaWaylandSurfaceRoleWlShellSurfaceClass *klass)
{
MetaWaylandSurfaceRoleClass *surface_role_class =
META_WAYLAND_SURFACE_ROLE_CLASS (klass);
surface_role_class->assigned = actor_surface_assigned;
surface_role_class->commit = toplevel_surface_commit;
surface_role_class->is_on_output = actor_surface_is_on_output;
}
static void
meta_wayland_surface_role_subsurface_init (MetaWaylandSurfaceRoleSubsurface *role)
{
}
static void
meta_wayland_surface_role_subsurface_class_init (MetaWaylandSurfaceRoleSubsurfaceClass *klass)
{
MetaWaylandSurfaceRoleClass *surface_role_class =
META_WAYLAND_SURFACE_ROLE_CLASS (klass);
surface_role_class->assigned = actor_surface_assigned;
surface_role_class->commit = subsurface_surface_commit;
surface_role_class->is_on_output = actor_surface_is_on_output;
}

View File

@@ -30,24 +30,67 @@
#include <meta/meta-cursor-tracker.h>
#include "meta-wayland-types.h"
#include "meta-surface-actor.h"
#include "backends/meta-monitor-manager-private.h"
typedef struct _MetaWaylandPendingState MetaWaylandPendingState;
#define META_TYPE_WAYLAND_SURFACE (meta_wayland_surface_get_type ())
G_DECLARE_FINAL_TYPE (MetaWaylandSurface,
meta_wayland_surface,
META, WAYLAND_SURFACE,
GObject);
#define META_TYPE_WAYLAND_SURFACE_ROLE (meta_wayland_surface_role_get_type ())
G_DECLARE_DERIVABLE_TYPE (MetaWaylandSurfaceRole, meta_wayland_surface_role,
META, WAYLAND_SURFACE_ROLE, GObject);
struct _MetaWaylandSurfaceRoleClass
{
GObjectClass parent_class;
void (*assigned) (MetaWaylandSurfaceRole *surface_role);
void (*commit) (MetaWaylandSurfaceRole *surface_role,
MetaWaylandPendingState *pending);
gboolean (*is_on_output) (MetaWaylandSurfaceRole *surface_role,
MetaMonitorInfo *monitor);
};
struct _MetaWaylandSerial {
gboolean set;
uint32_t value;
};
typedef enum
{
META_WAYLAND_SURFACE_ROLE_NONE,
META_WAYLAND_SURFACE_ROLE_SUBSURFACE,
META_WAYLAND_SURFACE_ROLE_XDG_SURFACE,
META_WAYLAND_SURFACE_ROLE_XDG_POPUP,
META_WAYLAND_SURFACE_ROLE_WL_SHELL_SURFACE,
META_WAYLAND_SURFACE_ROLE_CURSOR,
META_WAYLAND_SURFACE_ROLE_DND,
} MetaWaylandSurfaceRole;
#define META_TYPE_WAYLAND_SURFACE_ROLE_SUBSURFACE (meta_wayland_surface_role_subsurface_get_type ())
G_DECLARE_FINAL_TYPE (MetaWaylandSurfaceRoleSubsurface,
meta_wayland_surface_role_subsurface,
META, WAYLAND_SURFACE_ROLE_SUBSURFACE,
MetaWaylandSurfaceRole);
typedef struct
#define META_TYPE_WAYLAND_SURFACE_ROLE_XDG_SURFACE (meta_wayland_surface_role_xdg_surface_get_type ())
G_DECLARE_FINAL_TYPE (MetaWaylandSurfaceRoleXdgSurface,
meta_wayland_surface_role_xdg_surface,
META, WAYLAND_SURFACE_ROLE_XDG_SURFACE,
MetaWaylandSurfaceRole);
#define META_TYPE_WAYLAND_SURFACE_ROLE_XDG_POPUP (meta_wayland_surface_role_xdg_popup_get_type ())
G_DECLARE_FINAL_TYPE (MetaWaylandSurfaceRoleXdgPopup,
meta_wayland_surface_role_xdg_popup,
META, WAYLAND_SURFACE_ROLE_XDG_POPUP,
MetaWaylandSurfaceRole);
#define META_TYPE_WAYLAND_SURFACE_ROLE_WL_SHELL_SURFACE (meta_wayland_surface_role_wl_shell_surface_get_type ())
G_DECLARE_FINAL_TYPE (MetaWaylandSurfaceRoleWlShellSurface,
meta_wayland_surface_role_wl_shell_surface,
META, WAYLAND_SURFACE_ROLE_WL_SHELL_SURFACE,
MetaWaylandSurfaceRole);
#define META_TYPE_WAYLAND_SURFACE_ROLE_DND (meta_wayland_surface_role_dnd_get_type ())
G_DECLARE_FINAL_TYPE (MetaWaylandSurfaceRoleDND,
meta_wayland_surface_role_dnd,
META, WAYLAND_SURFACE_ROLE_DND,
MetaWaylandSurfaceRole);
struct _MetaWaylandPendingState
{
/* wl_surface.attach */
gboolean newly_attached;
@@ -71,7 +114,7 @@ typedef struct
MetaRectangle new_geometry;
gboolean has_new_geometry;
} MetaWaylandPendingState;
};
struct _MetaWaylandDragDestFuncs
{
@@ -89,11 +132,13 @@ struct _MetaWaylandDragDestFuncs
struct _MetaWaylandSurface
{
GObject parent;
/* Generic stuff */
struct wl_resource *resource;
MetaWaylandCompositor *compositor;
MetaSurfaceActor *surface_actor;
MetaWaylandSurfaceRole role;
MetaWaylandSurfaceRole *role;
MetaWindow *window;
MetaWaylandBuffer *buffer;
struct wl_listener buffer_destroy_listener;
@@ -104,6 +149,11 @@ struct _MetaWaylandSurface
GList *subsurfaces;
GHashTable *outputs;
/* List of pending frame callbacks that needs to stay queued longer than one
* commit sequence, such as when it has not yet been assigned a role.
*/
struct wl_list pending_frame_callback_list;
struct {
const MetaWaylandDragDestFuncs *funcs;
} dnd;
@@ -166,10 +216,8 @@ MetaWaylandSurface *meta_wayland_surface_create (MetaWaylandCompositor *composit
struct wl_resource *compositor_resource,
guint32 id);
int meta_wayland_surface_set_role (MetaWaylandSurface *surface,
MetaWaylandSurfaceRole role,
struct wl_resource *error_resource,
uint32_t error_code);
gboolean meta_wayland_surface_assign_role (MetaWaylandSurface *surface,
GType role_type);
void meta_wayland_surface_set_window (MetaWaylandSurface *surface,
MetaWindow *window);
@@ -197,4 +245,11 @@ void meta_wayland_surface_update_outputs (MetaWaylandSurface *sur
MetaWindow * meta_wayland_surface_get_toplevel_window (MetaWaylandSurface *surface);
void meta_wayland_surface_queue_pending_frame_callbacks (MetaWaylandSurface *surface);
void meta_wayland_surface_queue_pending_state_frame_callbacks (MetaWaylandSurface *surface,
MetaWaylandPendingState *pending);
MetaWaylandSurface * meta_wayland_surface_role_get_surface (MetaWaylandSurfaceRole *role);
#endif

View File

@@ -44,6 +44,6 @@
#define META_XSERVER_VERSION 1
#define META_GTK_SHELL_VERSION 2
#define META_WL_SUBCOMPOSITOR_VERSION 1
#define META_WL_POINTER_GESTURES_VERSION 1
#define META__WL_POINTER_GESTURES_VERSION 1
#endif

View File

@@ -144,7 +144,7 @@ wl_compositor_create_region (struct wl_client *client,
meta_wayland_region_create (compositor, client, resource, id);
}
const static struct wl_compositor_interface meta_wayland_wl_compositor_interface = {
static const struct wl_compositor_interface meta_wayland_wl_compositor_interface = {
wl_compositor_create_surface,
wl_compositor_create_region
};
@@ -207,6 +207,28 @@ meta_wayland_compositor_handle_event (MetaWaylandCompositor *compositor,
return meta_wayland_seat_handle_event (compositor->seat, event);
}
/* meta_wayland_compositor_update_key_state:
* @compositor: the #MetaWaylandCompositor
* @key_vector: bit vector of key states
* @key_vector_len: length of @key_vector
* @offset: the key for the first evdev keycode is found at this offset in @key_vector
*
* This function is used to resynchronize the key state that Mutter
* is tracking with the actual keyboard state. This is useful, for example,
* to handle changes in key state when a nested compositor doesn't
* have focus. We need to fix up the XKB modifier tracking and deliver
* any modifier changes to clients.
*/
void
meta_wayland_compositor_update_key_state (MetaWaylandCompositor *compositor,
char *key_vector,
int key_vector_len,
int offset)
{
meta_wayland_keyboard_update_key_state (&compositor->seat->keyboard,
key_vector, key_vector_len, offset);
}
void
meta_wayland_compositor_destroy_frame_callbacks (MetaWaylandCompositor *compositor,
MetaWaylandSurface *surface)
@@ -250,6 +272,8 @@ set_gnome_env (const char *name,
}
}
static void meta_wayland_log_func (const char *, va_list) G_GNUC_PRINTF (1, 0);
static void
meta_wayland_log_func (const char *fmt,
va_list arg)
@@ -313,13 +337,13 @@ meta_wayland_init (void)
meta_wayland_pointer_gestures_init (compositor);
meta_wayland_seat_init (compositor);
if (!meta_xwayland_start (&compositor->xwayland_manager, compositor->wayland_display))
g_error ("Failed to start X Wayland");
compositor->display_name = wl_display_add_socket_auto (compositor->wayland_display);
if (compositor->display_name == NULL)
g_error ("Failed to create socket");
if (!meta_xwayland_start (&compositor->xwayland_manager, compositor->wayland_display))
g_error ("Failed to start X Wayland");
set_gnome_env ("DISPLAY", meta_wayland_get_xwayland_display_name (compositor));
set_gnome_env ("WAYLAND_DISPLAY", meta_wayland_get_wayland_display_name (compositor));
}

View File

@@ -39,6 +39,10 @@ void meta_wayland_compositor_update (MetaWaylandComp
const ClutterEvent *event);
gboolean meta_wayland_compositor_handle_event (MetaWaylandCompositor *compositor,
const ClutterEvent *event);
void meta_wayland_compositor_update_key_state (MetaWaylandCompositor *compositor,
char *key_vector,
int key_vector_len,
int offset);
void meta_wayland_compositor_repick (MetaWaylandCompositor *compositor);
void meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,

View File

@@ -66,7 +66,7 @@ meta_window_wayland_manage (MetaWindow *window)
0);
}
if (window->surface->role == META_WAYLAND_SURFACE_ROLE_XDG_POPUP)
if (META_IS_WAYLAND_SURFACE_ROLE_XDG_POPUP (window->surface->role))
{
MetaWaylandSurface *parent = window->surface->popup.parent;
@@ -361,6 +361,8 @@ meta_window_wayland_main_monitor_changed (MetaWindow *window,
/* Window size. */
scale_rect_size (&window->rect, scale_factor);
scale_rect_size (&window->unconstrained_rect, scale_factor);
scale_rect_size (&window->saved_rect, scale_factor);
/* Window geometry offset (XXX: Need a better place, see
* meta_window_wayland_move_resize). */

View File

@@ -33,13 +33,12 @@
#include <gio/gunixinputstream.h>
#include <gdk/gdkx.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xfixes.h>
#include <meta/errors.h>
#include "meta-xwayland-private.h"
#include "meta-xwayland-selection-private.h"
#include "meta-wayland-data-device.h"
GType meta_wayland_data_source_xwayland_get_type (void) G_GNUC_CONST;
#define INCR_CHUNK_SIZE (128 * 1024)
#define XDND_VERSION 5
@@ -87,6 +86,7 @@ struct _MetaWaylandDataSourceXWayland
MetaWaylandDataSource parent;
MetaSelectionBridge *selection;
guint has_utf8_string_atom : 1;
};
struct _MetaXWaylandSelection {
@@ -161,7 +161,6 @@ xdnd_send_enter (MetaXWaylandSelection *selection_data,
if (source_mime_types->size <= 3)
{
/* The mimetype atoms fit in this same message */
gchar **p;
gint i = 2;
wl_array_for_each (p, source_mime_types)
@@ -411,27 +410,33 @@ x11_data_write_cb (GObject *object,
MetaSelectionBridge *selection = user_data;
X11SelectionData *data = selection->x11_selection;
GError *error = NULL;
gboolean success = TRUE;
g_output_stream_write_finish (G_OUTPUT_STREAM (object), res, &error);
if (data->incr)
if (error)
{
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
{
g_error_free (error);
return;
}
g_warning ("Error writing from X11 selection: %s\n", error->message);
g_error_free (error);
success = FALSE;
}
if (success && data->incr)
{
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
XDeleteProperty (xdisplay, selection->window,
gdk_x11_get_xatom_by_name ("_META_SELECTION"));
}
if (error)
else
{
if (error->domain != G_IO_ERROR ||
error->code != G_IO_ERROR_CANCELLED)
g_warning ("Error writing from X11 selection: %s\n", error->message);
g_error_free (error);
x11_selection_data_finish (selection, success);
}
if (!data->incr)
x11_selection_data_finish (selection, TRUE);
}
static void
@@ -706,7 +711,8 @@ meta_x11_source_send (MetaWaylandDataSource *source,
MetaSelectionBridge *selection = source_xwayland->selection;
Atom type_atom;
if (strcmp (mime_type, "text/plain;charset=utf-8") == 0)
if (source_xwayland->has_utf8_string_atom &&
strcmp (mime_type, "text/plain;charset=utf-8") == 0)
type_atom = gdk_x11_get_xatom_by_name ("UTF8_STRING");
else
type_atom = gdk_x11_get_xatom_by_name (mime_type);
@@ -849,6 +855,8 @@ meta_xwayland_data_source_fetch_mimetype_list (MetaWaylandDataSource *source,
Window window,
Atom prop)
{
MetaWaylandDataSourceXWayland *source_xwayland =
META_WAYLAND_DATA_SOURCE_XWAYLAND (source);
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
gulong nitems_ret, bytes_after_ret, i;
Atom *atoms, type_ret, utf8_string;
@@ -882,10 +890,13 @@ meta_xwayland_data_source_fetch_mimetype_list (MetaWaylandDataSource *source,
const gchar *mime_type;
if (atoms[i] == utf8_string)
mime_type = "text/plain;charset=utf-8";
else
mime_type = gdk_x11_get_xatom_name (atoms[i]);
{
meta_wayland_data_source_add_mime_type (source,
"text/plain;charset=utf-8");
source_xwayland->has_utf8_string_atom = TRUE;
}
mime_type = gdk_x11_get_xatom_name (atoms[i]);
meta_wayland_data_source_add_mime_type (source, mime_type);
}
@@ -1279,6 +1290,9 @@ meta_xwayland_selection_handle_client_message (MetaWaylandCompositor *compositor
MetaWaylandDragGrab *drag_grab = compositor->seat->data_device.current_grab;
MetaWaylandSurface *drag_focus = meta_wayland_drag_grab_get_focus (drag_grab);
if (!drag_focus)
return FALSE;
if (event->message_type == xdnd_atoms[ATOM_DND_ENTER])
{
/* Bit 1 in data.l[1] determines whether there's 3 or less mimetype

View File

@@ -32,18 +32,38 @@
#include <sys/socket.h>
#include <sys/un.h>
#include "compositor/meta-surface-actor-wayland.h"
#define META_TYPE_WAYLAND_SURFACE_ROLE_XWAYLAND (meta_wayland_surface_role_xwayland_get_type ())
G_DECLARE_FINAL_TYPE (MetaWaylandSurfaceRoleXWayland,
meta_wayland_surface_role_xwayland,
META, WAYLAND_SURFACE_ROLE_XWAYLAND,
MetaWaylandSurfaceRole);
struct _MetaWaylandSurfaceRoleXWayland
{
MetaWaylandSurfaceRole parent;
};
G_DEFINE_TYPE (MetaWaylandSurfaceRoleXWayland,
meta_wayland_surface_role_xwayland,
META_TYPE_WAYLAND_SURFACE_ROLE);
static void
associate_window_with_surface (MetaWindow *window,
MetaWaylandSurface *surface)
{
MetaDisplay *display = window->display;
/* If the window has an existing surface, like if we're
* undecorating or decorating the window, then we need
* to detach the window from its old surface.
*/
if (window->surface)
window->surface->window = NULL;
if (!meta_wayland_surface_assign_role (surface,
META_TYPE_WAYLAND_SURFACE_ROLE_XWAYLAND))
{
wl_resource_post_error (surface->resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"wl_surface@%d already has a different role",
wl_resource_get_id (surface->resource));
return;
}
meta_wayland_surface_set_window (surface, window);
window->surface = surface;
@@ -61,6 +81,16 @@ associate_window_with_surface_id (MetaXWaylandManager *manager,
{
struct wl_resource *resource;
/* If the window has an existing surface, like if we're
* undecorating or decorating the window, then we need
* to detach the window from its old surface.
*/
if (window->surface)
{
meta_wayland_surface_set_window (window->surface, NULL);
window->surface = NULL;
}
resource = wl_client_get_object (manager->client, surface_id);
if (resource)
{
@@ -144,6 +174,15 @@ meta_xwayland_handle_wl_surface_id (MetaWindow *window,
}
}
gboolean
meta_xwayland_is_xwayland_surface (MetaWaylandSurface *surface)
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaXWaylandManager *manager = &compositor->xwayland_manager;
return wl_resource_get_client (surface->resource) == manager->client;
}
static gboolean
try_display (int display,
char **filename_out,
@@ -543,3 +582,53 @@ meta_xwayland_stop (MetaXWaylandManager *manager)
g_clear_pointer (&manager->lock_file, g_free);
}
}
static void
xwayland_surface_assigned (MetaWaylandSurfaceRole *surface_role)
{
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
/* See comment in xwayland_surface_commit for why we reply even though the
* surface may not be drawn the next frame.
*/
wl_list_insert_list (&surface->compositor->frame_callbacks,
&surface->pending_frame_callback_list);
wl_list_init (&surface->pending_frame_callback_list);
}
static void
xwayland_surface_commit (MetaWaylandSurfaceRole *surface_role,
MetaWaylandPendingState *pending)
{
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
/* For Xwayland windows, throttling frames when the window isn't actually
* drawn is less useful, because Xwayland still has to do the drawing sent
* from the application - the throttling would only be of sending us damage
* messages, so we simplify and send frame callbacks after the next paint of
* the screen, whether the window was drawn or not.
*
* Currently it may take a few frames before we draw the window, for not
* completely understood reasons, and in that case, not thottling frame
* callbacks to drawing has the happy side effect that we avoid showing the
* user the initial black frame from when the window is mapped empty.
*/
meta_wayland_surface_queue_pending_state_frame_callbacks (surface, pending);
}
static void
meta_wayland_surface_role_xwayland_init (MetaWaylandSurfaceRoleXWayland *role)
{
}
static void
meta_wayland_surface_role_xwayland_class_init (MetaWaylandSurfaceRoleXWaylandClass *klass)
{
MetaWaylandSurfaceRoleClass *surface_role_class =
META_WAYLAND_SURFACE_ROLE_CLASS (klass);
surface_role_class->assigned = xwayland_surface_assigned;
surface_role_class->commit = xwayland_surface_commit;
}

View File

@@ -28,8 +28,13 @@
#include <glib.h>
#include <meta/types.h>
#include "wayland/meta-wayland-types.h"
void
meta_xwayland_handle_wl_surface_id (MetaWindow *window,
guint32 surface_id);
gboolean
meta_xwayland_is_xwayland_surface (MetaWaylandSurface *surface);
#endif /* META_XWAYLAND_H */

View File

@@ -16,6 +16,10 @@
name and the version will be reset to 1.
</description>
<enum name="error">
<entry name="version_mismatch" value="0"/>
</enum>
<request name="get_swipe_gesture">
<description summary="get swipe gesture">
Create a swipe gesture object. See the

View File

@@ -691,7 +691,8 @@ meta_spew_event_print (MetaDisplay *display,
static gboolean
handle_window_focus_event (MetaDisplay *display,
MetaWindow *window,
XIEnterEvent *event)
XIEnterEvent *event,
unsigned long serial)
{
MetaWindow *focus_window;
#ifdef WITH_VERBOSE_MODE
@@ -726,7 +727,7 @@ handle_window_focus_event (MetaDisplay *display,
event->event, window_type,
meta_event_mode_to_string (event->mode),
meta_event_detail_to_string (event->mode),
event->serial);
serial);
#endif
/* FIXME our pointer tracking is broken; see how
@@ -770,7 +771,7 @@ handle_window_focus_event (MetaDisplay *display,
if (event->evtype == XI_FocusIn)
{
display->server_focus_window = event->event;
display->server_focus_serial = event->serial;
display->server_focus_serial = serial;
focus_window = window;
}
else if (event->evtype == XI_FocusOut)
@@ -784,7 +785,7 @@ handle_window_focus_event (MetaDisplay *display,
}
display->server_focus_window = None;
display->server_focus_serial = event->serial;
display->server_focus_serial = serial;
focus_window = NULL;
}
else
@@ -829,8 +830,9 @@ crossing_serial_is_ignored (MetaDisplay *display,
}
static gboolean
handle_input_xevent (MetaDisplay *display,
XIEvent *input_event)
handle_input_xevent (MetaDisplay *display,
XIEvent *input_event,
unsigned long serial)
{
XIEnterEvent *enter_event = (XIEnterEvent *) input_event;
Window modified;
@@ -867,7 +869,7 @@ handle_input_xevent (MetaDisplay *display,
/* Check if we've entered a window; do this even if window->has_focus to
* avoid races.
*/
if (window && !crossing_serial_is_ignored (display, input_event->serial) &&
if (window && !crossing_serial_is_ignored (display, serial) &&
enter_event->mode != XINotifyGrab &&
enter_event->mode != XINotifyUngrab &&
enter_event->detail != XINotifyInferior &&
@@ -892,7 +894,7 @@ handle_input_xevent (MetaDisplay *display,
break;
case XI_FocusIn:
case XI_FocusOut:
if (handle_window_focus_event (display, window, enter_event) &&
if (handle_window_focus_event (display, window, enter_event, serial) &&
enter_event->event == enter_event->root)
{
if (enter_event->evtype == XI_FocusIn &&
@@ -1736,7 +1738,7 @@ meta_display_handle_xevent (MetaDisplay *display,
}
#endif /* HAVE_XI23 */
if (handle_input_xevent (display, input_event))
if (handle_input_xevent (display, input_event, event->xany.serial))
{
bypass_gtk = bypass_compositor = TRUE;
goto out;

View File

@@ -182,6 +182,8 @@ argbdata_to_surface (gulong *argb_data, int w, int h)
}
}
cairo_surface_mark_dirty (surface);
return surface;
}

View File

@@ -312,8 +312,8 @@ meta_session_init (const char *previous_client_id,
prgname = g_get_prgname ();
prop1.name = SmProgram;
prop1.type = SmARRAY8;
prop1.name = (char *)SmProgram;
prop1.type = (char *)SmARRAY8;
prop1.num_vals = 1;
prop1.vals = &prop1val;
prop1val.value = (char *)prgname;
@@ -322,38 +322,38 @@ meta_session_init (const char *previous_client_id,
/* twm sets getuid() for this, but the SM spec plainly
* says pw_name, twm is on crack
*/
prop2.name = SmUserID;
prop2.type = SmARRAY8;
prop2.name = (char *)SmUserID;
prop2.type = (char *)SmARRAY8;
prop2.num_vals = 1;
prop2.vals = &prop2val;
prop2val.value = (char*) g_get_user_name ();
prop2val.length = strlen (prop2val.value);
prop3.name = SmRestartStyleHint;
prop3.type = SmCARD8;
prop3.name = (char *)SmRestartStyleHint;
prop3.type = (char *)SmCARD8;
prop3.num_vals = 1;
prop3.vals = &prop3val;
prop3val.value = &hint;
prop3val.length = 1;
sprintf (pid, "%d", getpid ());
prop4.name = SmProcessID;
prop4.type = SmARRAY8;
prop4.name = (char *)SmProcessID;
prop4.type = (char *)SmARRAY8;
prop4.num_vals = 1;
prop4.vals = &prop4val;
prop4val.value = pid;
prop4val.length = strlen (prop4val.value);
/* Always start in home directory */
prop5.name = SmCurrentDirectory;
prop5.type = SmARRAY8;
prop5.name = (char *)SmCurrentDirectory;
prop5.type = (char *)SmARRAY8;
prop5.num_vals = 1;
prop5.vals = &prop5val;
prop5val.value = (char*) g_get_home_dir ();
prop5val.length = strlen (prop5val.value);
prop6.name = "_GSM_Priority";
prop6.type = SmCARD8;
prop6.name = (char *)"_GSM_Priority";
prop6.type = (char *)SmCARD8;
prop6.num_vals = 1;
prop6.vals = &prop6val;
prop6val.value = &priority;
@@ -588,15 +588,15 @@ set_clone_restart_commands (void)
/* Restart (use same client ID) */
prop1.name = SmRestartCommand;
prop1.type = SmLISTofARRAY8;
prop1.name = (char *)SmRestartCommand;
prop1.type = (char *)SmLISTofARRAY8;
g_return_if_fail (client_id);
i = 0;
restartv[i] = (char *)prgname;
++i;
restartv[i] = "--sm-client-id";
restartv[i] = (char *)"--sm-client-id";
++i;
restartv[i] = client_id;
++i;
@@ -619,8 +619,8 @@ set_clone_restart_commands (void)
++i;
clonev[i] = NULL;
prop2.name = SmCloneCommand;
prop2.type = SmLISTofARRAY8;
prop2.name = (char *)SmCloneCommand;
prop2.type = (char *)SmLISTofARRAY8;
prop2.vals = g_new (SmPropValue, i);
i = 0;
@@ -635,16 +635,16 @@ set_clone_restart_commands (void)
/* Discard */
i = 0;
discardv[i] = "rm";
discardv[i] = (char *)"rm";
++i;
discardv[i] = "-f";
discardv[i] = (char *)"-f";
++i;
discardv[i] = (char*) full_save_file ();
++i;
discardv[i] = NULL;
prop3.name = SmDiscardCommand;
prop3.type = SmLISTofARRAY8;
prop3.name = (char *)SmDiscardCommand;
prop3.type = (char *)SmLISTofARRAY8;
prop3.vals = g_new (SmPropValue, i);
i = 0;
@@ -946,7 +946,15 @@ save_state (void)
/* Sticky */
if (window->on_all_workspaces_requested)
fputs (" <sticky/>\n", outfile);
{
fputs (" <sticky/>\n", outfile);
} else {
int n;
n = meta_workspace_index (window->workspace);
fprintf (outfile,
" <workspace index=\"%d\"/>\n", n);
}
/* Minimized */
if (window->minimized)
@@ -963,14 +971,6 @@ save_state (void)
window->saved_rect.height);
}
/* Workspaces we're on */
{
int n;
n = meta_workspace_index (window->workspace);
fprintf (outfile,
" <workspace index=\"%d\"/>\n", n);
}
/* Gravity */
{
int x, y, w, h;
@@ -1792,8 +1792,8 @@ warn_about_lame_clients_and_finish_interact (gboolean shutdown)
return;
}
columns = g_slist_prepend (columns, "Window");
columns = g_slist_prepend (columns, "Class");
columns = g_slist_prepend (columns, (gpointer)"Window");
columns = g_slist_prepend (columns, (gpointer)"Class");
lame = g_slist_sort (lame, (GCompareFunc) windows_cmp_by_title);
@@ -1803,7 +1803,7 @@ warn_about_lame_clients_and_finish_interact (gboolean shutdown)
MetaWindow *w = tmp->data;
lame_details = g_slist_prepend (lame_details,
w->res_class ? w->res_class : "");
w->res_class ? w->res_class : (gpointer)"");
lame_details = g_slist_prepend (lame_details,
w->title);

View File

@@ -1843,7 +1843,7 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
{ display->atom__NET_WM_WINDOW_TYPE, META_PROP_VALUE_ATOM_LIST, reload_net_wm_window_type, LOAD_INIT | INCLUDE_OR | FORCE_INIT },
{ display->atom__NET_WM_STRUT, META_PROP_VALUE_INVALID, reload_struts, NONE },
{ display->atom__NET_WM_STRUT_PARTIAL, META_PROP_VALUE_INVALID, reload_struts, NONE },
{ display->atom__NET_WM_BYPASS_COMPOSITOR, META_PROP_VALUE_CARDINAL, reload_bypass_compositor, NONE },
{ display->atom__NET_WM_BYPASS_COMPOSITOR, META_PROP_VALUE_CARDINAL, reload_bypass_compositor, LOAD_INIT | INCLUDE_OR },
{ display->atom__NET_WM_WINDOW_OPACITY, META_PROP_VALUE_CARDINAL, reload_window_opacity, LOAD_INIT | INCLUDE_OR },
{ 0 },
};

View File

@@ -542,13 +542,10 @@ meta_window_x11_manage (MetaWindow *window)
* For normal windows, do a full ConfigureRequest based on the
* window hints, as that's what the ICCCM says to do.
*/
priv->client_rect = window->rect;
window->buffer_rect = window->rect;
if (window->override_redirect)
{
priv->client_rect = window->rect;
window->buffer_rect = window->rect;
}
else
if (!window->override_redirect)
{
MetaRectangle rect;
MetaMoveResizeFlags flags;
@@ -1735,9 +1732,9 @@ meta_window_x11_update_input_region (MetaWindow *window)
region = cairo_region_create ();
}
else if (n_rects == 1 &&
(rects[0].x == 0 ||
rects[0].y == 0 ||
rects[0].width == priv->client_rect.width ||
(rects[0].x == 0 &&
rects[0].y == 0 &&
rects[0].width == priv->client_rect.width &&
rects[0].height == priv->client_rect.height))
{
/* This is the bounding region case. Keep the

View File

@@ -507,7 +507,7 @@ window_from_results (GetPropertyResults *results,
if (!validate_or_free_results (results, 32, XA_WINDOW, TRUE))
return FALSE;
*window_p = *(Window*) results->prop;
*window_p = *(uint32_t *) results->prop;
g_free (results->prop);
results->prop = NULL;
@@ -523,7 +523,7 @@ counter_from_results (GetPropertyResults *results,
TRUE))
return FALSE;
*counter_p = *(XSyncCounter*) results->prop;
*counter_p = *(uint32_t *) results->prop;
g_free (results->prop);
results->prop = NULL;