Compare commits

...

124 Commits

Author SHA1 Message Date
af45a50cb1 Bump version to 3.19.4
Update NEWS.
2016-01-21 23:04:22 +01:00
72d6efc0d5 Shut up some compiler warnings 2016-01-21 23:04:22 +01:00
e0ffef06dd theme: Support margins on titlebar title/buttons
GTK+ improved its CSS support, and the default theme started to make
use of it, so we must update our theming code accordingly. Add support
for margins where they make sense.
2016-01-21 23:04:22 +01:00
d5b69bcd54 theme: Consider minimum sizes
GTK+ improved its CSS support, and the default theme started to make
use of it, so we must update our theming code accordingly. Start by
supporting min-width/min-height where it makes sense.
2016-01-21 23:04:22 +01:00
ac8fe2d9b2 cursor-tracker: Port to GdkSeat API 2016-01-21 14:07:50 +01:00
e7a88dc6b2 meta-launcher: don't call g_object_unref() on NULL
g_object_unref() was called no matter what we got for value

https://bugzilla.gnome.org/show_bug.cgi?id=760670
2016-01-21 14:06:41 +01:00
bcdda506e1 MetaWaylandDataDevice: Don't set surface offset as anchor offset
Since we are using the surface actor to draw the DND icon, the offset
is already accounted for by MetaSurfaceActorWayland, and passing the
surface position offset would effectively double the actual offset,
causing the icon to be misplaced.

This patch always sets the anchor offset to (0, 0) when the icon is a
Wayland surface, and lets the surface actor deal with the offsetting.

https://bugzilla.gnome.org/show_bug.cgi?id=759222
2016-01-19 14:32:34 +01:00
9b26694bbc wayland: Implement DnD actions as per wl_data_device v3 changes
We now additionally send:
  - wl_data_offer.source_actions
  - wl_data_source.action
  - wl_data_offer.action
  - wl_data_source.dnd_drop_performed
  - wl_data_source.dnd_finished

The protocol changes allow for compositors to implement different policies
when chosing the action, mutter uses this to reimplement the same behavior
that GTK+ traditionally had:

  - Alt/Control/Shift modifiers change the chosen action to
    ask/copy/move respectively
  - Drags with middle button start out as "ask" by default

As mutter now also grabs the keyboard and unsets the window focus for these
purposes, the window focus is restored after the drag operation has
finished.

The Xdnd bridge code is also modified to cope with actions, so mixed
wayland-x11 scenarios are able to convey that information.

https://bugzilla.gnome.org/show_bug.cgi?id=760805
2016-01-19 13:55:33 +01:00
f053c09083 data-device: Refactor data source management by the drag grab
Move to a separate meta_wayland_drag_grab_set_source() so we keep
the weak pointer management in a single place.

https://bugzilla.gnome.org/show_bug.cgi?id=760805
2016-01-19 13:45:56 +01:00
ec9abaf1ef wayland: Add MetaWaylandKeyboardGrab and keyboard grab API
This will be useful during DnD, where mutter is expected to consume
keyboard events for either allowing changes in the selected DnD action,
or misc a11y features like keyboard-driven DnD.

Currently, the vtable contains 2 functions, key() will be used on every
key event we get from Clutter, modifiers() will notify of changes in the
keyboard modifiers (mouse buttons will never be set in the modifier mask)

https://bugzilla.gnome.org/show_bug.cgi?id=760805
2016-01-19 13:45:56 +01:00
6b88420465 wayland: Add "update" vfunc to MetaWaylandDragDestFuncs
This will be useful when an update is due but no motion event is to be
sent/received (eg. modifier changes during DnD).

https://bugzilla.gnome.org/show_bug.cgi?id=760805
2016-01-19 13:45:56 +01:00
fc0a834abb wayland: Emit wl_pointer.frame after .enter in pointer resource creation
This place was missing concordance with wl_pointer v5.
2016-01-19 11:51:36 +01:00
e30010b9f0 wayland: Rename meta_wayland_pointer_send_frame() to broadcast_frame
It's closer to what we mean here. And we can have a send_frame() helper
that does this for a single wl_resource.
2016-01-19 11:50:27 +01:00
935d76ba04 wayland: Implement wl_pointer.axis_source/axis_stop/axis_frame emission
As per the spec:
- wl_pointer.axis_source determines the current source of
  scroll events.
- wl_pointer.axis_stop determines when there's no further
  scroll events on the given axis.
- wl_pointer.axis_discrete is emitted on "wheel"
  scroll sources, measured in ticks.
- wl_pointer.frame is meant to coalesce events that logically belong
  together, e.g. axis events in this case.

Co-Authored-By: Peter Hutterer <peter.hutterer@who-t.net>

https://bugzilla.gnome.org/show_bug.cgi?id=760637
2016-01-14 19:27:48 +01:00
cc013e1daa Updated Lithuanian translation 2016-01-12 22:35:05 +02:00
a7a376ae1f xprops: Null-terminate property reply values
Some of the mutter code using these properties expects them to be
null-terminated whereas xcb does not use null-terminated strings:

http://xcb.freedesktop.org/XcbRationale/

This was in some cases resulting in the WM_CLASS property containing
garbage data which broke application matching, caused the hot-corner and
window-switcher to stop working, or was exposed as text in the UI.

https://bugzilla.gnome.org/show_bug.cgi?id=759658
2016-01-12 16:30:30 +01:00
5e57af6286 idle-monitor-native: Don't leak user active watches
This fixes an issue analogous to bug 760330 for the X11 backend,
except on this backend we wouldn't crash accessing free'd memory.

Instead we're leaking watches since we steal them from the hash table
which means that when they're removed in
_meta_idle_monitor_watch_fire() they're no longer there and thus
they're never free'd.

https://bugzilla.gnome.org/show_bug.cgi?id=760476
2016-01-11 11:23:54 -05:00
42b3a34f7b idle-monitor-xsync: fix crash if watch callback removes different watch
Right now the XSync based idle monitoring code, will fetch all active
watches into a list, and then call their watch callbacks one by one
as necessary.  If one watch callback invalidates another watch, the
list will contain free'd memory.

This commit makes sure to consult the hash table after ever call
of a watch callback, to ensure mutter never looks at freed memory.

Fixes crash reported on IRC by Laine Stump with his synergy setup.

https://bugzilla.gnome.org/show_bug.cgi?id=760330
2016-01-11 11:23:39 -05:00
19d814c887 cursor-renderer-native: Avoid a crash if we fail to allocate a gbm bo
https://bugzilla.gnome.org/show_bug.cgi?id=758613
2016-01-11 14:31:42 +01:00
46eb682c83 Revert "window: Remove old tiling code"
This reverts commit 8bded7d497.
2016-01-10 15:16:09 +01:00
3aea8d8ce6 Revert "Add "size states" which save window size information"
This reverts commit 2c7ef2269f.
2016-01-10 15:16:09 +01:00
40c3c69435 Revert "window: Add new tiling code"
This reverts commit 50e3e3b929.
2016-01-10 15:16:08 +01:00
8071e5b149 Revert "frame: Don't allow resizing of edges that are constrained"
This reverts commit 8a481b3e10.
2016-01-10 15:16:06 +01:00
8a481b3e10 frame: Don't allow resizing of edges that are constrained
https://bugzilla.gnome.org/show_bug.cgi?id=751857
2016-01-09 18:11:15 -08:00
50e3e3b929 window: Add new tiling code
The new tiling code, instead of based around "tiling states", is instead
based around constrained edges. This allows us to have windows that have
three constrained edges, but keep one free-floating, e.g. a window tiled
to the left has the left, top, and bottom edges constrained, but the
right edge can be left resizable.

This system also is easily extended to support corner tiling. We also,
using the new "size state" system, also keep normal, tiled, and
maximized sizes independently, allowing the maximize button to bounce
between maximized and tiled states without reverting to normal in
between. Dragging from the top will always restore the normal state,
though.

https://bugzilla.gnome.org/show_bug.cgi?id=751857
2016-01-09 18:09:30 -08:00
2c7ef2269f Add "size states" which save window size information
https://bugzilla.gnome.org/show_bug.cgi?id=751857
2016-01-09 18:08:35 -08:00
8bded7d497 window: Remove old tiling code
We'll soon replace this with a better scheme

https://bugzilla.gnome.org/show_bug.cgi?id=751857
2016-01-09 18:08:32 -08:00
9ebe3419c3 monitor-manager-xrandr: Don't query legacy properties
This never could have worked -- the Atom name it was querying was a root
window property, not an output property.
2016-01-09 18:06:18 -08:00
9385c835b8 native: Don't leak DRM plane resources 2016-01-07 19:42:19 +01:00
efef0c993b native: Implement DRM-based crtc rotation
We can know the rotation modes supported by the driver, so
export these as our supported modes, and ensure these modes
are honored on the CRTC primary plane upon apply_configuration().

It is worth noting however that not all hardware will be
capable of supporting all rotation modes (in fact, most of
them won't). A driver independent solution should be in
place to back up the rotation modes unsupported by the
drivers, so this is still a partial solution.

The cursor renderer has also been changed to default to
software-based rendering anytime the cursor enters a
rotated CRTC. Another solution would be actually rotating
the DRM cursor planes, but then it requires applying rotation on
these per-CRTC, and actually transforming the pointer position by
the output matrix. This brings marginal gains, so we use the
"sw" rendered cursor, which will be transformed together with
the primary plane.

https://bugzilla.gnome.org/show_bug.cgi?id=745079
2016-01-07 17:03:44 +01:00
3a2cd3389a window: Re-evaluate window visibility when making it transient
In case a window is hidden when we're ordered to make it transient to
a different parent we must re-evaluate its visibility status or we'll
get into an inconsistent state where the parent is visible and the
child isn't.

https://bugzilla.gnome.org/show_bug.cgi?id=759297
2016-01-06 18:56:07 +01:00
88acfb8e60 window: Focus windows on button press regardless of modifier state
This seems like a more generally useful and intuitive behavior. Note
that, in X sessions, this is what already happened in practice since
meta_display_begin_grab_op() calls meta_window_grab_all_keys() which,
on X11, does meta_window_focus().

https://bugzilla.gnome.org/show_bug.cgi?id=756789
2016-01-05 20:42:05 +01:00
8e22dce5d7 window: Remove a spurious meta_verbose()
This was duplicated here by mistake in the big re-work commit
7a109a18af .

https://bugzilla.gnome.org/show_bug.cgi?id=756789
2016-01-05 20:42:04 +01:00
e0906a77aa ui/frames: Don't focus if the button press is on the client area
This is a really old behavior introduced in commit
585e362526 which is inconsistent since
it only applies to SSD windows.

If we really want this, we should focus the window elsewhere so that
it applies consistently to all windows.

https://bugzilla.gnome.org/show_bug.cgi?id=756789
2016-01-05 20:42:02 +01:00
053f5088df window-x11: Fix unredirection for windows that explicitly set bounding
Some applications, like Chromium, explicitly set their bounding region
to the client area when full-screen. Detect this case, and allow us to
fullscreen when this happens.
2016-01-04 08:32:09 -08:00
75b992c7d0 tests: Add test for testing that setting a parent affects the stack
A new test is added that tests that xdg_surface.set_parent (referred to
as "transient for" in X11 terminology) affects the stack immediately.

https://bugzilla.gnome.org/show_bug.cgi?id=755606
2015-12-23 14:59:36 +08:00
213f0fa160 window: Update the stack after setting the transient_for field
Don't update the stack until after setting the window->transient_for
field. Updating before will cause the stack transient-for constraint to
be missing until the next time constraints are applied.

https://bugzilla.gnome.org/show_bug.cgi?id=755606
2015-12-23 14:59:36 +08:00
5054b2a99c tests: Don't rely on latency for actually showing Wayland windows
The test runner sends a "show" command to the test clients and assumes
this was enough work done by the client to enable the compositor to map
the window. Now that we wait to show a Wayland window until the first
buffer is attached (see bug 750552), we need to make sure that we attach
a buffer before assuming that we have the final stacking order.

So, to in order to continue relying on "show" to be enough to actually
show a window, let the test client wait until it has drawn the first
frame.

This makes the tests using Wayland clients test non-flaky.

https://bugzilla.gnome.org/show_bug.cgi?id=754711
2015-12-23 12:19:36 +08:00
d455de32a0 Bump version to 3.19.3
Update NEWS.
2015-12-17 01:21:40 +01:00
e7390cff83 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:46:41 +01:00
49ea6486e2 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-15 15:49:13 +01:00
996aeaef41 backends: Fix cut'n'paste error in click method setting
GDesktopTouchpadScrollMethod was used instead of GDesktopTouchpadClickMethod
which became visible now that the former has been removed from
gsettings-desktop-schemas.

https://bugzilla.gnome.org/show_bug.cgi?id=759304
2015-12-15 14:41:51 +01:00
a27b2597b9 backends: Force 2-finger scroll by default if available
When the touchpad is two-finger scrolling capable, always enable it.

When the touchpad only supports edge scrolling (usually older devices, and
usually smaller devices), allow disabling the edge scrolling.

This requires a newer gsettings-desktop-schemas as the scroll-method key
was removed, and the edge-scroll-enabled key added.

https://bugzilla.gnome.org/show_bug.cgi?id=759304
2015-12-15 14:38:23 +01:00
0e8ca1a042 default-plugin: port to non deprecated API
https://bugzilla.gnome.org/show_bug.cgi?id=759374
2015-12-15 08:39:57 +00:00
f5f26c9cff Update .gitignore 2015-12-14 15:17:40 -08:00
91ac69382d wayland: Fix up touch coordinates on HiDPI 2015-12-14 14:52:23 -08:00
8cc345fcf5 window: Allow minimizing windows which don't advertise support for it
Wine removes the minimize func from its Motif hints on full-screen
windows, because, as the Win32 API literally says, the minimize button
is indeed not visible on full-screen windows.

Given that this code was added to prevent minimizing a panel by
accident, I don't necessarily think that it's relevant anymore.

https://bugzilla.gnome.org/show_bug.cgi?id=758186
2015-12-05 10:46:21 -08:00
96b5042dda core: Unset "pointer emulating" sequence lazily
Unsetting it in meta_display_handle_event() will make the pointer
emulation checks fail on TOUCH_END event handlers across clutter
actors, the sequence should still be considered as pointer emulating
at that time.

As we don't have a way to hook this post clutter event handling,
instead unset/reset it lazily on the next pointer emulating TOUCH_BEGIN
event, the checks would already fail on other sequences, even if the
pointer emulating touch ended earlier. The only extra thing we need
to take care about is sequence collision, at which point it's safe to
just unset the stored sequence if its new incarnation isn't flagged/
deemed as pointer emulating.

https://bugzilla.gnome.org/show_bug.cgi?id=756754
2015-12-04 11:47:01 +01:00
428c687b5a wayland: Clean up wl_pointer_send_enter/leave code
Be consistent and always use a helper, and fix the naming so
broadcast means to actually broadcast.

https://bugzilla.gnome.org/show_bug.cgi?id=755503
2015-12-03 16:11:37 +08:00
82bdd1e353 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:15:37 +01:00
4bebc5e5fa 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:15:23 +01:00
be5643cee7 wayland: Use xdg shell protocol from wayland-protocols
Use the xdg_shell XML file installed by wayland-protocols instead of
our own copy. This protocol has yet to go through any unstable naming,
but since we had an outdated (though wire compatible) version, some
minor changes were needed.

https://bugzilla.gnome.org/show_bug.cgi?id=758633
2015-11-26 16:55:35 +08:00
2ee1c5fa61 wayland: Use pointer gestures protocol from wayand-protocols
Remove our own copy of the pointer gestures protocol, and us the one
installed by wayland-protocols. This also means the new fixed unstable
naming conventions are used for the new version of the protocol, which
is reflected in the change. No functional changes were made, it is only
a rename.

https://bugzilla.gnome.org/show_bug.cgi?id=758633
2015-11-26 16:55:35 +08:00
c625d2ee9d core: Make meta_window_handle_ungrabbed_event() touch-aware
This fixes the effects of this function on touchscreens in wayland
(most notably, window raising & focusing).
2015-11-25 18:00:36 +01:00
3078f70f90 wayland: Fetch keyboard event codes from ClutterEvents
When running as a native compositor, we can just do that. However, the
previous code must stay for whenever it's run as a X11 client.

https://bugzilla.gnome.org/show_bug.cgi?id=758239
2015-11-25 18:00:36 +01:00
7309b20c25 wayland: Fetch pointer button event codes from the ClutterEvent
When running as a native compositor, we can just do that. However, the
previous code must stay for whenever it's run as a X11 client.

Additionally, the fallback switch{} that transforms clutter 1-indexed
buttons into input.h event codes had to be adapted to the change introduced
in clutter commit 83b738c0e, where the 4-7 button range is kept clear for
compatibility with the X11 backend.

https://bugzilla.gnome.org/show_bug.cgi?id=758239
2015-11-25 17:56:51 +01:00
c16a5ec1cf KMS/Wayland: Correct refresh rate units
On the wire, Wayland specifies the refresh rate in milliHz. Mutter sends
the refresh rate in Hz, which confuses clients, e.g. weston-info:
interface: 'wl_output', version: 2, name: 4
	mode:
		width: 2560 px, height: 1440 px, refresh: 0 Hz,
		flags: current preferred
interface: 'wl_output', version: 2, name: 5
	mode:
		width: 3200 px, height: 1800 px, refresh: 0 Hz,
		flags: current preferred

and xrandr:
XWAYLAND0 connected 2560x1440+3200+0 600mm x 340mm
   2560x1440@0.1Hz   0.05*+
XWAYLAND1 connected 3200x1800+0+0 290mm x 170mm
   3200x1800@0.1Hz   0.03*+

Export the refresh rate in the correct units. For improved precision,
perform the KMS intermediate calculations in milliHz as well, and
account for interlaced/doublescan modes.

This is also consistent with what GTK+ expects:
      timings->refresh_interval = 16667; /* default to 1/60th of a second */

      /* We pick a random output out of the outputs that the window touches
       * The rate here is in milli-hertz */
      int refresh_rate = _gdk_wayland_screen_get_output_refresh_rate (wayland_display->screen,
                                                                      impl->outputs->data);
      if (refresh_rate != 0)
        timings->refresh_interval = G_GINT64_CONSTANT(1000000000) / refresh_rate;

Where the 'refresh_rate' given is exactly what's come off the wire.
1000000000/60000 comes out as 16667, whereas divided by 60 is ...
substantially less.

https://bugzilla.gnome.org/show_bug.cgi?id=758653
2015-11-25 15:35:25 +01:00
f3e1964362 Bump version to 3.19.2
Update NEWS.
2015-11-25 00:34:28 +01:00
9b9083180f theme: Shut up some GTK+ warnings
GTK+ started to complain when the state parameter passed to any
gtk_style_context_get*() method mismatches the context's current
state a while ago.
2015-11-24 23:46:14 +01:00
7606f79a1e 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:54:48 +01:00
99c0b82b15 window: do not force placing window if it is not mapped
When managing window, we queue showing the window.
Under wayland, if we commit surface quickly enough,
the showing is unqueued and commit procedure takes care
of mapping and placing the window. In the oposite case,
queue is processed before client sets all we need and
then we have wrong size of window, which leads to broken placement.
Therefore force placement in queue only if the window should already
be mapped. If it is not mapped, we don't care where it is anyway.

https://bugzilla.gnome.org/show_bug.cgi?id=751887
2015-11-16 10:21:09 +08:00
ca7c1d5e02 launcher: Fix drm device detection for non pci devices
On Odroid U2 (exynos4412) the drm device is not bound to pci.
Open the detection to platform device of the drm subsystem, exclusive of
control devices.

https://bugzilla.gnome.org/show_bug.cgi?id=754911
2015-11-12 14:09:02 -05:00
4a770907c1 theme: Update style hierarchy (again)
GTK+ has updated some more widgets to use element names, so do some
catching up again ...
2015-11-12 01:04:24 +01:00
049f1556dc Updated POTFILES.skip 2015-11-10 01:18:27 +01:00
7b20d151ed data: drop mutter-wayland.desktop
It's not needed since we can automatically figure things out
based on logind.

https://bugzilla.gnome.org/show_bug.cgi?id=741666
2015-11-09 10:25:40 -05:00
8ec0c99ff4 core: start as wayland display server when XDG_SESSION_TYPE=wayland
This commit gets rid of the need for --display-server and
--wayland when mutter detects that a wayland session is registered.

https://bugzilla.gnome.org/show_bug.cgi?id=741666
2015-11-09 10:25:11 -05:00
cf3ee327a0 meta-backend: include stdlib.h
Otherwise build fails with missing declaration
warning for exit().
2015-11-06 23:10:41 -05:00
3ec3cc248d 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:03:59 -05:00
7fb3ecc12c 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:03:59 -05:00
4c9af7267d Revert "Force cursor update after applying configuration"
This reverts commit 33150569cd.

This was a stow-a-away sitting in my local tree.
2015-11-06 16:24:34 -05:00
db4355ba1e core: move backend setting to helper function
This paves the way for making the backend setting
be more automatic.

https://bugzilla.gnome.org/show_bug.cgi?id=741666
2015-11-06 16:22:40 -05:00
33150569cd Force cursor update after applying configuration
The qxl kms driver has a bug where the cursor gets hidden
implicitly after a drmModeSetCrtc call.

This commit works around the bug by forcing a drmModeSetCursor2
call after the drmModeSetCrtc calls.

This is pretty hacky and won't ever go upstream.

https://bugzilla.gnome.org/show_bug.cgi?id=746078
2015-11-06 14:26:46 -05:00
af2a13ded4 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 17:47:00 +01:00
8b200de35a 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 17:47:00 +01:00
57ae203aab 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 17:47:00 +01:00
bff75b64be 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 17:47:00 +01:00
8899b9da01 Bump version to 3.19.1
Update NEWS.
2015-10-29 14:56:06 +01:00
76e816a14f 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 14:33:34 +01:00
2750db2a89 theme: Set object-name on style contexts
The default theme started to use them in GTK+ commit 371f50, so
we need to update the style contexts to keep matching the style
of client-side decorations.

https://bugzilla.gnome.org/show_bug.cgi?id=757101
2015-10-27 09:42:49 +01:00
86a913d37a 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:13:26 +02:00
2857fdbdb8 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:13:26 +02:00
69a7d5ff02 Updated Romanian Translation 2015-10-22 19:15:59 +02:00
a4f763ac3b wayland-surface: disconnect signals on destroy
Otherwise signal handlers will be called on garbage

https://bugzilla.gnome.org/show_bug.cgi?id=756548
2015-10-19 17:21:59 -07:00
f2afa7aa6c mutter: don't show the resize popup for 2 x 2 size increments
In a HiDPI environment, all gtk+ apps will report a 2 x 2 size
increment to avoid odd size. But that does not mean they are
resizing in cells like terminals, so they resize popup should
not be shown.

Ideally, we should ignore <= scale x scale increments, but in
practice scale is 1 or 2, and even in a lo-dpi setting a 2 x 2
increment makes little sense so let's keep the patch simple.

https://bugzilla.gnome.org/show_bug.cgi?id=746420
2015-10-19 17:21:59 -07:00
a5d2555196 wayland: Make it possible to trigger popups through pointer/keyboard/touch
Right now we just check the pointer serial, so the popup will be
immediately dismissed if the client passes a serial corresponding to
another input device.

Abstract this a bit further and add a meta_wayland_seat_can_popup() call
that will check the serial all input devices. This makes it possible to
trigger menus through touch or keyboard devices.

https://bugzilla.gnome.org/show_bug.cgi?id=756296
2015-10-17 18:52:52 +02:00
dd5a4ecdf9 wayland: Store key press/release serials on MetaWaylandKeyboard
https://bugzilla.gnome.org/show_bug.cgi?id=756296
2015-10-17 18:52:15 +02:00
43a1d43f2b 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:57:26 +02:00
d6d377a447 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 11:31:51 +08:00
ffd95c2ad5 theme: Complete removal of "fringe" titlebar button support
We have been ignoring those buttons since 3.16 after they had been
broken in the default theme for a couple of versions. As nobody
appears to miss them, it's time to remove them for good.
2015-10-16 04:13:14 +02:00
72be89dfb9 theme: Reset button style state when done drawing
We use a single style context to draw titlebar buttons, updating
its state according to each button's prelight state as necessary.
This assumes that the original state is neither ACTIVE nor PRELIGHT,
which means we need to reset the state after drawing to avoid
propagating the state of the last-drawn button.
2015-10-16 04:04:34 +02:00
2feeb57dee iconcache: Mark surfaces as dirty after changing data
This is required to tell cairo to update its cached areas.
2015-10-16 04:04:31 +02:00
9c81b718f9 Bump version to 3.18.1
Update NEWS.
2015-10-15 19:06:54 +02:00
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
5b5ceede2b wayland: Fix variable declaration
Storage class always goes first.
2015-09-24 03:08:23 +02:00
4e63c95c02 testboxes: Don't avoid parameter list 2015-09-24 03:08:23 +02:00
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
bc00f118f3 Avoid shadowing existing variables 2015-09-24 03:08:22 +02:00
5801b5518f Annotate functions to improve compiler diagnostics 2015-09-24 03:01:51 +02:00
25a796afc6 Fix constness warnings 2015-09-24 03:01:51 +02:00
27b37407d0 Don't duplicate declarations from G_DEFINE_TYPE 2015-09-24 03:01:51 +02:00
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
89 changed files with 4190 additions and 3671 deletions

10
.gitignore vendored
View File

@ -64,12 +64,10 @@ src/meta-dbus-idle-monitor.[ch]
src/meta-dbus-login1.[ch]
src/gtk-shell-protocol.c
src/gtk-shell-server-protocol.h
src/xdg-shell-protocol.c
src/xdg-shell-server-protocol.h
src/pointer-gestures-protocol.c
src/pointer-gestures-server-protocol.h
src/xserver-protocol.c
src/xserver-server-protocol.h
src/xdg-shell-unstable-v*-protocol.c
src/xdg-shell-unstable-v*-server-protocol.h
src/pointer-gestures-unstable-v*-protocol.c
src/pointer-gestures-unstable-v*-server-protocol.h
src/meta/meta-version.h
doc/reference/*.args
doc/reference/*.bak

75
NEWS
View File

@ -1,3 +1,78 @@
3.19.4
======
* Fix updating stacking order when setting transient_for [Jonas; #755606]
* Support screen rotation when supported by the driver [Carlos; #745079]
* Protect against broken WM_CLASS property implementations [Sebastian; #759658]
* Handle wl_pointer v5 events on wayland [Carlos; #760637]
* Implement DND actions on wayland [Carlos; #760805]
* Misc. bug fixes [Jonas, Rui, Ray, Marek; #754711, #756789, #759297, #758613,
#760330, #760476, #759222, #760670]
Contributors:
Jonas Ådahl, Marek Chalupa, Carlos Garnacho, Sebastian Keller, Rui Matos,
Florian Müllner, Jasper St. Pierre, Ray Strode
Translations:
Aurimas Černius [lt]
3.19.3
======
* Correct refresh rate units on KMS/Wayland [Daniel; #758653]
* 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 touch pointer emulation on wayland [Carlos; #756754]
* Allow minimizing windows that don't advertise supporting it [Jasper; #758186]
* Force 2-finger scroll by default if available [Bastien; #759304]
* Fix crash during XWayland initialization [Marek; #751845]
* Ensure to send a ConfigureNotify to just mapped windows [Rui; #759492]
* Misc. bug fixes and cleanups [Carlos, Jonas, Lionel; #758239, #758633,
#755503, #759374]
Contributors:
Jonas Ådahl, Marek Chalupa, Carlos Garnacho, Lionel Landwerlin, Rui Matos,
Bastien Nocera, Daniel Stone, Jasper St. Pierre
3.19.2
======
* Fix crash on monitor unplug [Rui; #756796]
* Exit cleanly on initialization errors [Owen; #757311]
* Allow to determine backend setting from session type [Ray; #741666]
* Fix DRM device detection for non-PCI devices [Alban; #754911]
* Don't force placement of windows without buffer on wayland [Marek; #751887]
* Fix initialization of bypass compositor hint [Rui; #758544]
Contributors:
Alban Browaeys, Marek Chalupa, Rui Matos, Florian Müllner, Ray Strode,
Owen W. Taylor
3.19.1
======
* wayland: Allow to trigger popups through keyboard/touch [Carlos; #756296]
* Fix modifiers-only input source switching on Ubuntu [Alberts; #756543]
* Misc. bug fixes [Jonas, Rui, Giovanni, Florian; #756675, #756660, #746420,
#756548, #756796, #757101, #757148]
Contributors:
Jonas Ådahl, Giovanni Campagna, Carlos Garnacho, Rui Matos,
Alberts Muktupāvels, Florian Müllner
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]

View File

@ -1,8 +1,8 @@
AC_PREREQ(2.62)
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [18])
m4_define([mutter_micro_version], [0])
m4_define([mutter_minor_version], [19])
m4_define([mutter_micro_version], [4])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@ -46,6 +46,7 @@ IT_PROG_INTLTOOL([0.41])
AC_PROG_CC
AC_PROG_CC_C_O
AC_PROG_INSTALL
AC_PROG_SED
AC_HEADER_STDC
PKG_PROG_PKG_CONFIG([0.21])
@ -58,12 +59,12 @@ CANBERRA_GTK_VERSION=0.26
CLUTTER_PACKAGE=clutter-1.0
MUTTER_PC_MODULES="
gtk+-3.0 >= 3.9.11
gtk+-3.0 >= 3.19.7
gio-unix-2.0 >= 2.35.1
pango >= 1.2.0
cairo >= 1.10.0
gsettings-desktop-schemas >= 3.15.92
$CLUTTER_PACKAGE >= 1.23.4
gsettings-desktop-schemas >= 3.19.3
$CLUTTER_PACKAGE >= 1.25.1
cogl-1.0 >= 1.17.1
upower-glib >= 0.99.0
gnome-desktop-3.0
@ -219,6 +220,10 @@ AS_IF([test "$have_wayland" = "yes"], [
[AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols])])
AC_SUBST([WAYLAND_SCANNER])
AC_DEFINE([HAVE_WAYLAND],[1],[Define if you want to enable Wayland support])
PKG_CHECK_MODULES(WAYLAND_PROTOCOLS, [wayland-protocols >= 1.0],
[ac_wayland_protocols_pkgdatadir=`$PKG_CONFIG --variable=pkgdatadir wayland-protocols`])
AC_SUBST(WAYLAND_PROTOCOLS_DATADIR, $ac_wayland_protocols_pkgdatadir)
])
AM_CONDITIONAL([HAVE_WAYLAND],[test "$have_wayland" = "yes"])

View File

@ -1,6 +1,5 @@
desktopfiles_in_files = \
mutter.desktop.in \
mutter-wayland.desktop.in
mutter.desktop.in
desktopfilesdir = $(datadir)/applications
desktopfiles_DATA = $(desktopfiles_in_files:.desktop.in=.desktop)

View File

@ -1,17 +0,0 @@
[Desktop Entry]
Type=Application
_Name=Mutter (wayland compositor)
Exec=mutter --wayland --display-server
NoDisplay=true
# name of loadable control center module
X-GNOME-WMSettingsModule=metacity
# name we put on the WM spec check window
X-GNOME-WMName=Mutter
# back compat only
X-GnomeWMSettingsLibrary=metacity
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=mutter
X-GNOME-Bugzilla-Component=general
X-GNOME-Autostart-Phase=WindowManager
X-GNOME-Provides=windowmanager
X-GNOME-Autostart-Notify=true

View File

@ -1 +1,2 @@
data/mutter-wayland.desktop.in
# List of source files that should NOT be translated.
# Please keep this file sorted alphabetically.

114
po/lt.po
View File

@ -13,8 +13,8 @@ msgstr ""
"Project-Id-Version: lt\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-28 11:14+0000\n"
"PO-Revision-Date: 2015-02-28 21:34+0200\n"
"POT-Creation-Date: 2016-01-05 13:43+0000\n"
"PO-Revision-Date: 2016-01-05 18:04+0200\n"
"Last-Translator: Aurimas Černius <aurisc4@gmail.com>\n"
"Language-Team: Lietuvių <gnome-lt@lists.akl.lt>\n"
"Language: lt\n"
@ -23,7 +23,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n"
"%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Gtranslator 2.91.6\n"
"X-Generator: Poedit 1.8.6\n"
#: ../data/50-mutter-navigation.xml.in.h:1
msgid "Navigation"
@ -31,39 +31,39 @@ msgstr "Navigacija"
#: ../data/50-mutter-navigation.xml.in.h:2
msgid "Move window to workspace 1"
msgstr "Perkelti langą į darbalaukį Nr.1"
msgstr "Perkelti langą į darbo sritį Nr.1"
#: ../data/50-mutter-navigation.xml.in.h:3
msgid "Move window to workspace 2"
msgstr "Perkelti langą į darbalaukį Nr.2"
msgstr "Perkelti langą į darbo sritį Nr.2"
#: ../data/50-mutter-navigation.xml.in.h:4
msgid "Move window to workspace 3"
msgstr "Perkelti langą į darbalaukį Nr.3"
msgstr "Perkelti langą į darbo sritį Nr.3"
#: ../data/50-mutter-navigation.xml.in.h:5
msgid "Move window to workspace 4"
msgstr "Perkelti langą į darbalaukį Nr.4"
msgstr "Perkelti langą į darbo sritį Nr.4"
#: ../data/50-mutter-navigation.xml.in.h:6
msgid "Move window to last workspace"
msgstr "Perkelti langą į pastarąjį darbalaukį"
msgstr "Perkelti langą į pastarąją darbo sritį"
#: ../data/50-mutter-navigation.xml.in.h:7
msgid "Move window one workspace to the left"
msgstr "Perkelti langą į kairiau esan darbalaukį"
msgstr "Perkelti langą į kairiau esančią darbo sritį"
#: ../data/50-mutter-navigation.xml.in.h:8
msgid "Move window one workspace to the right"
msgstr "Perkelti langą į dešiniau esan darbalaukį"
msgstr "Perkelti langą į dešiniau esančią darbo sritį"
#: ../data/50-mutter-navigation.xml.in.h:9
msgid "Move window one workspace up"
msgstr "Perkelti langą į aukščiau esan darbalaukį"
msgstr "Perkelti langą į aukščiau esančią darbo sritį"
#: ../data/50-mutter-navigation.xml.in.h:10
msgid "Move window one workspace down"
msgstr "Perkelti langą į žemiau esan darbalaukį"
msgstr "Perkelti langą į žemiau esančią darbo sritį"
#: ../data/50-mutter-navigation.xml.in.h:11
msgid "Move window one monitor to the left"
@ -143,39 +143,39 @@ msgstr "Paslėpti visus įprastinius langus"
#: ../data/50-mutter-navigation.xml.in.h:30
msgid "Switch to workspace 1"
msgstr "Persijungti į darbalaukį Nr.1"
msgstr "Persijungti į darbo sritį Nr.1"
#: ../data/50-mutter-navigation.xml.in.h:31
msgid "Switch to workspace 2"
msgstr "Persijungti į darbalaukį Nr.2"
msgstr "Persijungti į darbo sritį Nr.2"
#: ../data/50-mutter-navigation.xml.in.h:32
msgid "Switch to workspace 3"
msgstr "Persijungti į darbalaukį Nr.3"
msgstr "Persijungti į darbo sritį Nr.3"
#: ../data/50-mutter-navigation.xml.in.h:33
msgid "Switch to workspace 4"
msgstr "Persijungti į darbalaukį Nr.4"
msgstr "Persijungti į darbo sritį Nr.4"
#: ../data/50-mutter-navigation.xml.in.h:34
msgid "Switch to last workspace"
msgstr "Persijungti į pastarąjį darbalaukį"
msgstr "Persijungti į pastarąją darbo sritį"
#: ../data/50-mutter-navigation.xml.in.h:35
msgid "Move to workspace left"
msgstr "Perkelti į darbalaukį kairėje"
msgstr "Perkelti į darbo sritį kairėje"
#: ../data/50-mutter-navigation.xml.in.h:36
msgid "Move to workspace right"
msgstr "Perkelti į darbalaukį dešinėje"
msgstr "Perkelti į darbo sritį dešinėje"
#: ../data/50-mutter-navigation.xml.in.h:37
msgid "Move to workspace above"
msgstr "Perkelti į darbalaukį viršuje"
msgstr "Perkelti į darbo sritį viršuje"
#: ../data/50-mutter-navigation.xml.in.h:38
msgid "Move to workspace below"
msgstr "Perkelti į darbalaukį apačioje"
msgstr "Perkelti į darbo sritį apačioje"
#: ../data/50-mutter-system.xml.in.h:1
msgid "System"
@ -235,7 +235,7 @@ msgstr "Keisti lango dydį"
#: ../data/50-mutter-windows.xml.in.h:12
msgid "Toggle window on all workspaces or one"
msgstr "Perjungti lango buvimo visuose darbalaukiuose būseną"
msgstr "Perjungti lango buvimo visose darbo srityse būseną"
#: ../data/50-mutter-windows.xml.in.h:13
msgid "Raise window if covered, otherwise lower it"
@ -272,7 +272,7 @@ msgstr "Mutter"
#: ../data/org.gnome.mutter.gschema.xml.in.h:1
msgid "Modifier to use for extended window management operations"
msgstr "Klavišas, naudojamas kartu su specialiais lango valdymo veiksmais"
msgstr "Klavišas, naudojamas kartu su specialiomis lango tvarkymo operacijomis"
#: ../data/org.gnome.mutter.gschema.xml.in.h:2
msgid ""
@ -315,7 +315,7 @@ msgstr ""
#: ../data/org.gnome.mutter.gschema.xml.in.h:7
msgid "Workspaces are managed dynamically"
msgstr "Darbalaukiai valdomi dinamiškai"
msgstr "Darbo sritys tvarkomos dinamiškai"
#: ../data/org.gnome.mutter.gschema.xml.in.h:8
msgid ""
@ -323,21 +323,21 @@ msgid ""
"static number of workspaces (determined by the num-workspaces key in org."
"gnome.desktop.wm.preferences)."
msgstr ""
"Nusako, ar darbastaliai yra valdomi dinamiškai, ar yra pastovus darbalaukių "
"skaičius (nusakomas raktu num-workspaces schemoje org.gnome.desktop.wm."
"preferences)."
"Nusako, ar darbo sritys yra tvarkomos dinamiškai, ar yra pastovus darbo "
"sričių skaičius (nusakomas raktu num-workspaces schemoje org.gnome.desktop."
"wm.preferences)."
#: ../data/org.gnome.mutter.gschema.xml.in.h:9
msgid "Workspaces only on primary"
msgstr "Darbalaukiai tik pagrindiniame"
msgstr "Darbo sritys tik pagrindiniame"
#: ../data/org.gnome.mutter.gschema.xml.in.h:10
msgid ""
"Determines whether workspace switching should happen for windows on all "
"monitors or only for windows on the primary monitor."
msgstr ""
"Nusako, ar darbalaukių perjungimas turi įvykti langams viusose monitoriuose, "
"ar tik langams pagrindiniame monitoriuje."
"Nusako, ar darbo sričių perjungimas turi įvykti langams visuose "
"monitoriuose, ar tik langams pagrindiniame monitoriuje."
#: ../data/org.gnome.mutter.gschema.xml.in.h:11
msgid "No tab popup"
@ -438,46 +438,41 @@ msgid "Switch to VT 7"
msgstr "Persijungti į VT 7"
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:8
#| msgid "Switch to VT 1"
msgid "Switch to VT 8"
msgstr "Persijungti į VT 8"
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:9
#| msgid "Switch to VT 1"
msgid "Switch to VT 9"
msgstr "Persijungti į VT 9"
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:10
#| msgid "Switch to VT 1"
msgid "Switch to VT 10"
msgstr "Persijungti į VT 10"
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:11
#| msgid "Switch to VT 1"
msgid "Switch to VT 11"
msgstr "Persijungti į VT 11"
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:12
#| msgid "Switch to VT 1"
msgid "Switch to VT 12"
msgstr "Persijungti į VT 12"
#: ../src/backends/meta-monitor-manager.c:364
#: ../src/backends/meta-monitor-manager.c:518
msgid "Built-in display"
msgstr "Integruotas vaizduoklis"
#: ../src/backends/meta-monitor-manager.c:391
#: ../src/backends/meta-monitor-manager.c:544
msgid "Unknown"
msgstr "Nežinomas"
#: ../src/backends/meta-monitor-manager.c:393
#: ../src/backends/meta-monitor-manager.c:546
msgid "Unknown Display"
msgstr "Nežinomas vaizduoklis"
#. 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:554
#, c-format
msgid "%s %s"
msgstr "%s %s"
@ -489,7 +484,7 @@ msgstr "%s %s"
msgid ""
"Another compositing manager is already running on screen %i on display \"%s"
"\"."
msgstr "Kita kompozicijos valdyklė jau veikia ekrane %i vaizduoklyje „%s“."
msgstr "Kita kompozicijos tvarkytuvė jau veikia ekrane %i vaizduoklyje „%s“."
#: ../src/core/bell.c:185
msgid "Bell event"
@ -518,40 +513,40 @@ msgstr "_Laukti"
msgid "_Force Quit"
msgstr "_Priverstinai išeiti"
#: ../src/core/display.c:562
#: ../src/core/display.c:563
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Nepavyko atverti X Window sistemos ekrano „%s“\n"
#: ../src/core/main.c:176
#: ../src/core/main.c:180
msgid "Disable connection to session manager"
msgstr "Išjungti susijungimą su sesijos valdykle"
msgstr "Išjungti susijungimą su sesijos tvarkytuve"
#: ../src/core/main.c:182
#: ../src/core/main.c:186
msgid "Replace the running window manager"
msgstr "Pakeisti veikiančią langų valdyklę"
msgstr "Pakeisti veikiančią langų tvarkytuvę"
#: ../src/core/main.c:188
#: ../src/core/main.c:192
msgid "Specify session management ID"
msgstr "Nurodyti sesijos valdymo ID"
msgstr "Nurodyti sesijos tvarkymo ID"
#: ../src/core/main.c:193
#: ../src/core/main.c:197
msgid "X Display to use"
msgstr "Naudotinas X ekranas"
#: ../src/core/main.c:199
#: ../src/core/main.c:203
msgid "Initialize session from savefile"
msgstr "Inicializuoti sesiją iš išsaugojimo failo"
#: ../src/core/main.c:205
#: ../src/core/main.c:209
msgid "Make X calls synchronous"
msgstr "Sinchronizuoti X iškvietimus"
#: ../src/core/main.c:212
#: ../src/core/main.c:216
msgid "Run as a wayland compositor"
msgstr "Vykdyti kaip wayland kompozitorių"
#: ../src/core/main.c:220
#: ../src/core/main.c:224
msgid "Run as a full display server, rather than nested"
msgstr "Vykdyti kaip visą vaizduoklio serverį, o ne vidinį"
@ -580,24 +575,21 @@ msgstr "Parodyti versiją"
msgid "Mutter plugin to use"
msgstr "Naudojamas Mutter įskiepis"
#: ../src/core/prefs.c:2004
#: ../src/core/prefs.c:1997
#, c-format
msgid "Workspace %d"
msgstr "Darbalaukis %d"
msgstr "Darbo sritis %d"
#: ../src/core/screen.c:525
#: ../src/core/screen.c:526
#, c-format
#| msgid ""
#| "Screen %d on display \"%s\" already has a window manager; try using the --"
#| "replace option to replace the current window manager.\n"
msgid ""
"Display \"%s\" already has a window manager; try using the --replace option "
"to replace the current window manager."
msgstr ""
"Vaizduoklis „%s“ jau turi langų valdyklę; pabandykite pakeisti esamą langų "
"valdyklę naudodami parametrą --replace."
"Vaizduoklis „%s“ jau turi langų tvarkytuvę; pabandykite pakeisti esamą langų "
"tvarkytuvę, naudodami parametrą --replace."
#: ../src/core/screen.c:607
#: ../src/core/screen.c:608
#, c-format
msgid "Screen %d on display '%s' is invalid\n"
msgstr "Ekranas %d vaizduoklyje „%s“ netinkamas\n"

3395
po/ro.po

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,7 @@ dist_stacking_DATA = \
tests/stacking/basic-wayland.metatest \
tests/stacking/minimized.metatest \
tests/stacking/mixed-windows.metatest \
tests/stacking/set-parent.metatest \
tests/stacking/override-redirect.metatest
mutter-all.test: tests/mutter-all.test.in

View File

@ -45,19 +45,17 @@ mutter_built_sources = \
if HAVE_WAYLAND
mutter_built_sources += \
pointer-gestures-protocol.c \
pointer-gestures-server-protocol.h \
pointer-gestures-unstable-v1-protocol.c \
pointer-gestures-unstable-v1-server-protocol.h \
gtk-shell-protocol.c \
gtk-shell-server-protocol.h \
xdg-shell-protocol.c \
xdg-shell-server-protocol.h \
xdg-shell-unstable-v5-protocol.c \
xdg-shell-unstable-v5-server-protocol.h \
$(NULL)
endif
wayland_protocols = \
wayland/protocol/pointer-gestures.xml \
wayland/protocol/gtk-shell.xml \
wayland/protocol/xdg-shell.xml \
$(NULL)
libmutter_la_SOURCES = \
@ -481,6 +479,20 @@ $(dbus_login1_built_sources) : Makefile.am org.freedesktop.login1.xml
--generate-c-code meta-dbus-login1 \
$(srcdir)/org.freedesktop.login1.xml
.SECONDEXPANSION:
define protostability
$(shell echo $1 | sed 's/.*\(\<unstable\>\|\<stable\>\).*/\1/')
endef
define protoname
$(shell echo $1 | sed 's/\([a-z\-]\+\)-[a-z]\+-v[0-9]\+/\1/')
endef
%-protocol.c : $(WAYLAND_PROTOCOLS_DATADIR)/$$(call protostability,$$*)/$$(call protoname,$$*)/$$*.xml
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
%-server-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/$$(call protostability,$$*)/$$(call protoname,$$*)/$$*.xml
$(AM_V_GEN)$(WAYLAND_SCANNER) server-header < $< > $@
%-protocol.c : $(srcdir)/wayland/protocol/%.xml
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
%-server-protocol.h : $(srcdir)/wayland/protocol/%.xml

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

@ -27,6 +27,8 @@
#include "meta-cursor-renderer.h"
#include <meta/meta-backend.h>
#include <backends/meta-backend-private.h>
#include <backends/meta-monitor-manager-private.h>
#include <meta/util.h>
#include <cogl/cogl.h>
@ -116,6 +118,14 @@ meta_cursor_renderer_calculate_rect (MetaCursorRenderer *renderer,
};
}
static gboolean
is_cursor_in_monitors_area (int x, int y)
{
MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (meta_get_backend ());
return meta_monitor_manager_get_monitor_at_point (monitor_manager,
(gfloat) x, (gfloat) y) >= 0;
}
static void
update_cursor (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite)
@ -124,6 +134,11 @@ update_cursor (MetaCursorRenderer *renderer,
gboolean handled_by_backend;
gboolean should_redraw = FALSE;
/* do not render cursor if it is not on any monitor. Such situation
* can occur e. g. after monitor hot-plug */
if (!is_cursor_in_monitors_area (priv->current_x, priv->current_y))
return;
if (cursor_sprite)
meta_cursor_sprite_prepare_at (cursor_sprite,
priv->current_x,

View File

@ -54,8 +54,6 @@ struct _MetaCursorRendererClass
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,

View File

@ -361,12 +361,12 @@ get_pointer_position_gdk (int *x,
int *y,
int *mods)
{
GdkDeviceManager *gmanager;
GdkSeat *gseat;
GdkDevice *gdevice;
GdkScreen *gscreen;
gmanager = gdk_display_get_device_manager (gdk_display_get_default ());
gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID);
gseat = gdk_display_get_default_seat (gdk_display_get_default ());
gdevice = gdk_seat_get_pointer (gseat);
gdk_device_get_position (gdevice, &gscreen, x, y);
if (mods)

View File

@ -60,8 +60,6 @@ struct _MetaCursorSprite
gboolean theme_dirty;
};
GType meta_cursor_sprite_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE (MetaCursorSprite, meta_cursor_sprite, G_TYPE_OBJECT)
static const char *

View File

@ -63,9 +63,9 @@ struct _MetaInputSettingsClass
void (* set_invert_scroll) (MetaInputSettings *settings,
ClutterInputDevice *device,
gboolean inverted);
void (* set_scroll_method) (MetaInputSettings *settings,
ClutterInputDevice *device,
GDesktopTouchpadScrollMethod mode);
void (* set_edge_scroll) (MetaInputSettings *settings,
ClutterInputDevice *device,
gboolean enabled);
void (* set_scroll_button) (MetaInputSettings *settings,
ClutterInputDevice *device,
guint button);

View File

@ -395,11 +395,11 @@ update_touchpad_tap_enabled (MetaInputSettings *input_settings,
}
static void
update_touchpad_scroll_method (MetaInputSettings *input_settings,
ClutterInputDevice *device)
update_touchpad_edge_scroll (MetaInputSettings *input_settings,
ClutterInputDevice *device)
{
MetaInputSettingsClass *input_settings_class;
GDesktopTouchpadScrollMethod method;
gboolean edge_scroll_enabled;
MetaInputSettingsPrivate *priv;
if (device &&
@ -408,19 +408,19 @@ update_touchpad_scroll_method (MetaInputSettings *input_settings,
priv = meta_input_settings_get_instance_private (input_settings);
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
method = g_settings_get_enum (priv->touchpad_settings, "scroll-method");
edge_scroll_enabled = g_settings_get_boolean (priv->touchpad_settings, "edge-scrolling-enabled");
if (device)
{
settings_device_set_uint_setting (input_settings, device,
input_settings_class->set_scroll_method,
method);
settings_device_set_bool_setting (input_settings, device,
input_settings_class->set_edge_scroll,
edge_scroll_enabled);
}
else
{
settings_set_uint_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
(ConfigUintFunc) input_settings_class->set_scroll_method,
method);
settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
(ConfigBoolFunc) input_settings_class->set_edge_scroll,
edge_scroll_enabled);
}
}
@ -429,7 +429,7 @@ update_touchpad_click_method (MetaInputSettings *input_settings,
ClutterInputDevice *device)
{
MetaInputSettingsClass *input_settings_class;
GDesktopTouchpadScrollMethod method;
GDesktopTouchpadClickMethod method;
MetaInputSettingsPrivate *priv;
if (device &&
@ -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);
@ -647,8 +645,8 @@ meta_input_settings_changed_cb (GSettings *settings,
update_touchpad_tap_enabled (input_settings, NULL);
else if (strcmp (key, "send-events") == 0)
update_touchpad_send_events (input_settings, NULL);
else if (strcmp (key, "scroll-method") == 0)
update_touchpad_scroll_method (input_settings, NULL);
else if (strcmp (key, "edge-scrolling-enabled") == 0)
update_touchpad_edge_scroll (input_settings, NULL);
else if (strcmp (key, "click-method") == 0)
update_touchpad_click_method (input_settings, NULL);
}
@ -773,7 +771,7 @@ apply_device_settings (MetaInputSettings *input_settings,
update_device_natural_scroll (input_settings, device);
update_touchpad_tap_enabled (input_settings, device);
update_touchpad_send_events (input_settings, device);
update_touchpad_scroll_method (input_settings, device);
update_touchpad_edge_scroll (input_settings, device);
update_touchpad_click_method (input_settings, device);
update_trackball_scroll_button (input_settings, device);

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

@ -414,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

@ -37,6 +37,8 @@
#include "meta-cursor-renderer-native.h"
#include "meta-launcher.h"
#include <stdlib.h>
struct _MetaBackendNativePrivate
{
MetaLauncher *launcher;
@ -327,8 +329,15 @@ static void
meta_backend_native_init (MetaBackendNative *native)
{
MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native);
GError *error = NULL;
priv->launcher = meta_launcher_new (&error);
if (priv->launcher == NULL)
{
g_warning ("Can't initialize KMS backend: %s\n", error->message);
exit (1);
}
priv->launcher = meta_launcher_new ();
priv->barrier_manager = meta_barrier_manager_native_new ();
priv->up_client = up_client_new ();

View File

@ -258,6 +258,9 @@ has_valid_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 FALSE;
switch (cursor_priv->pending_bo_state)
{
case META_CURSOR_GBM_BO_STATE_NONE:
@ -273,6 +276,32 @@ has_valid_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite)
return FALSE;
}
static gboolean
cursor_over_transformed_crtc (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite)
{
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);
rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite);
for (i = 0; i < n_crtcs; i++)
{
if (!meta_rectangle_overlap (&rect, &crtcs[i].rect))
continue;
if (crtcs[i].transform != META_MONITOR_TRANSFORM_NORMAL)
return TRUE;
}
return FALSE;
}
static gboolean
should_have_hw_cursor (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite)
@ -282,6 +311,9 @@ should_have_hw_cursor (MetaCursorRenderer *renderer,
if (!cursor_sprite)
return FALSE;
if (cursor_over_transformed_crtc (renderer, cursor_sprite))
return FALSE;
texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
if (!texture)
return FALSE;

View File

@ -164,56 +164,36 @@ meta_idle_monitor_native_init (MetaIdleMonitorNative *monitor_native)
monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch);
}
typedef struct {
MetaIdleMonitorNative *monitor_native;
GList *fired_watches;
} CheckNativeClosure;
static gboolean
check_native_watch (gpointer key,
gpointer value,
gpointer user_data)
{
MetaIdleMonitorWatchNative *watch_native = value;
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_native;
CheckNativeClosure *closure = user_data;
gboolean steal;
if (watch->timeout_msec == 0)
{
closure->fired_watches = g_list_prepend (closure->fired_watches, watch);
steal = TRUE;
}
else
{
g_source_set_ready_time (watch_native->timeout_source,
closure->monitor_native->last_event_time +
watch->timeout_msec * 1000);
steal = FALSE;
}
return steal;
}
static void
fire_native_watch (gpointer watch,
gpointer data)
{
_meta_idle_monitor_watch_fire (watch);
}
void
meta_idle_monitor_native_reset_idletime (MetaIdleMonitor *monitor)
{
MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor);
CheckNativeClosure closure;
GList *node, *watch_ids;
monitor_native->last_event_time = g_get_monotonic_time ();
closure.monitor_native = monitor_native;
closure.fired_watches = NULL;
g_hash_table_foreach_steal (monitor->watches, check_native_watch, &closure);
watch_ids = g_hash_table_get_keys (monitor->watches);
g_list_foreach (closure.fired_watches, fire_native_watch, NULL);
g_list_free (closure.fired_watches);
for (node = watch_ids; node != NULL; node = node->next)
{
guint watch_id = GPOINTER_TO_UINT (node->data);
MetaIdleMonitorWatchNative *watch;
watch = g_hash_table_lookup (monitor->watches, GUINT_TO_POINTER (watch_id));
if (!watch)
continue;
if (watch->base.timeout_msec == 0)
{
_meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch);
}
else
{
g_source_set_ready_time (watch->timeout_source,
monitor_native->last_event_time +
watch->base.timeout_msec * 1000);
}
}
g_list_free (watch_ids);
}

View File

@ -154,30 +154,30 @@ device_set_click_method (struct libinput_device *libinput_device,
}
static void
meta_input_settings_native_set_scroll_method (MetaInputSettings *settings,
ClutterInputDevice *device,
GDesktopTouchpadScrollMethod mode)
meta_input_settings_native_set_edge_scroll (MetaInputSettings *settings,
ClutterInputDevice *device,
gboolean edge_scrolling_enabled)
{
enum libinput_config_scroll_method scroll_method = 0;
struct libinput_device *libinput_device;
enum libinput_config_scroll_method supported;
libinput_device = clutter_evdev_input_device_get_libinput_device (device);
supported = libinput_device_config_scroll_get_methods (libinput_device);
switch (mode)
if (supported & LIBINPUT_CONFIG_SCROLL_2FG)
{
case G_DESKTOP_TOUCHPAD_SCROLL_METHOD_DISABLED:
scroll_method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
break;
case G_DESKTOP_TOUCHPAD_SCROLL_METHOD_EDGE_SCROLLING:
scroll_method = LIBINPUT_CONFIG_SCROLL_EDGE;
break;
case G_DESKTOP_TOUCHPAD_SCROLL_METHOD_TWO_FINGER_SCROLLING:
scroll_method = LIBINPUT_CONFIG_SCROLL_2FG;
break;
default:
g_assert_not_reached ();
return;
}
}
else if (supported & LIBINPUT_CONFIG_SCROLL_EDGE &&
edge_scrolling_enabled)
{
scroll_method = LIBINPUT_CONFIG_SCROLL_EDGE;
}
else
{
scroll_method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
}
device_set_scroll_method (libinput_device, scroll_method);
}
@ -252,7 +252,7 @@ meta_input_settings_native_class_init (MetaInputSettingsNativeClass *klass)
input_settings_class->set_left_handed = meta_input_settings_native_set_left_handed;
input_settings_class->set_tap_enabled = meta_input_settings_native_set_tap_enabled;
input_settings_class->set_invert_scroll = meta_input_settings_native_set_invert_scroll;
input_settings_class->set_scroll_method = meta_input_settings_native_set_scroll_method;
input_settings_class->set_edge_scroll = meta_input_settings_native_set_edge_scroll;
input_settings_class->set_scroll_button = meta_input_settings_native_set_scroll_button;
input_settings_class->set_click_method = meta_input_settings_native_set_click_method;
input_settings_class->set_keyboard_repeat = meta_input_settings_native_set_keyboard_repeat;

View File

@ -54,30 +54,22 @@ struct _MetaLauncher
gboolean session_active;
};
static void
report_error_and_die (const char *prefix,
GError *error)
{
/* if a function returns due to g_return_val_if_fail,
* then the error may not be set */
if (error)
g_error ("%s: %s", prefix, error->message);
else
g_error ("%s", prefix);
/* the error is not freed, but it is ok as g_error aborts the process */
}
static Login1Session *
get_session_proxy (GCancellable *cancellable)
get_session_proxy (GCancellable *cancellable,
GError **error)
{
char *proxy_path;
char *session_id;
Login1Session *session_proxy;
GError *error = NULL;
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);
@ -85,9 +77,9 @@ get_session_proxy (GCancellable *cancellable)
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
"org.freedesktop.login1",
proxy_path,
cancellable, &error);
cancellable, error);
if (!session_proxy)
report_error_and_die ("Failed getting session proxy", error);
g_prefix_error(error, "Could not get session proxy: ");
free (proxy_path);
@ -95,16 +87,16 @@ get_session_proxy (GCancellable *cancellable)
}
static Login1Seat *
get_seat_proxy (GCancellable *cancellable)
get_seat_proxy (GCancellable *cancellable,
GError **error)
{
GError *error = 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);
cancellable, error);
if (!seat)
report_error_and_die ("Could not get seat proxy", error);
g_prefix_error(error, "Could not get seat proxy: ");
return seat;
}
@ -112,12 +104,12 @@ get_seat_proxy (GCancellable *cancellable)
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);
@ -305,7 +297,7 @@ get_primary_gpu_path (const gchar *seat_name)
for (tmp = devices; tmp != NULL; tmp = tmp->next)
{
GUdevDevice *pci_device;
GUdevDevice *platform_device = NULL, *pci_device = NULL;
GUdevDevice *dev = tmp->data;
gint boot_vga;
const gchar *device_seat;
@ -332,20 +324,28 @@ get_primary_gpu_path (const gchar *seat_name)
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)
platform_device = g_udev_device_get_parent_with_subsystem (dev, "platform", NULL);
if (platform_device != NULL)
{
/* found the boot_vga device */
path = g_strdup (g_udev_device_get_device_file (dev));
g_object_unref (platform_device);
break;
}
pci_device = g_udev_device_get_parent_with_subsystem (dev, "pci", NULL);
if (pci_device != NULL)
{
/* 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");
if (boot_vga == 1)
{
/* found the boot_vga device */
path = g_strdup (g_udev_device_get_device_file (dev));
break;
}
g_object_unref (pci_device);
}
}
g_list_free_full (devices, g_object_unref);
@ -357,69 +357,114 @@ out:
return path;
}
static void
static gboolean
get_kms_fd (Login1Session *session_proxy,
const gchar *seat_id,
int *fd_out)
const gchar *seat_id,
int *fd_out,
GError **error)
{
int major, minor;
int fd;
gchar *path;
GError *error = NULL;
path = get_primary_gpu_path (seat_id);
g_autofree gchar *path = get_primary_gpu_path (seat_id);
if (!path)
g_error ("could not find drm kms device");
{
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_NOT_FOUND,
"could not find drm kms device");
return FALSE;
}
if (!get_device_info_from_path (path, &major, &minor))
g_error ("Could not stat %s: %m", path);
{
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_NOT_FOUND,
"Could not get device info for path %s: %m", path);
return FALSE;
}
g_free (path);
if (!take_device (session_proxy, major, minor, &fd, NULL, &error))
report_error_and_die ("Could not open DRM device", error);
if (!take_device (session_proxy, major, minor, &fd, NULL, error))
{
g_prefix_error (error, "Could not open DRM device: ");
return FALSE;
}
*fd_out = fd;
return TRUE;
}
static gchar *
get_seat_id (void)
get_seat_id (GError **error)
{
char *session_id, *seat_id = NULL;
char *session_id, *seat_id;
int r;
if (sd_pid_get_session (0, &session_id) < 0)
return NULL;
r = sd_pid_get_session (0, &session_id);
if (r < 0)
{
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_NOT_FOUND,
"Could not get session for PID: %s", g_strerror (-r));
return NULL;
}
/* on error the seat_id will remain NULL */
sd_session_get_seat (session_id, &seat_id);
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 (void)
meta_launcher_new (GError **error)
{
MetaLauncher *self = NULL;
Login1Session *session_proxy;
char *seat_id;
GError *error = 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);
if (!login1_session_call_take_control_sync (session_proxy, FALSE, NULL, &error))
report_error_and_die ("Could not take control", error);
session_proxy = get_session_proxy (NULL, error);
if (!session_proxy)
goto fail;
seat_id = get_seat_id ();
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)
g_error ("Failed getting 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;
get_kms_fd (session_proxy, seat_id, &kms_fd);
free (seat_id);
self = g_slice_new0 (MetaLauncher);
self->session_proxy = session_proxy;
self->seat_proxy = get_seat_proxy (NULL);
self->seat_proxy = seat_proxy;
self->session_active = TRUE;
@ -429,8 +474,16 @@ meta_launcher_new (void)
self);
g_signal_connect (self->session_proxy, "notify::active", G_CALLBACK (on_active_changed), self);
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

@ -42,6 +42,8 @@
#include <gudev/gudev.h>
#define ALL_TRANSFORMS (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)
typedef struct {
drmModeConnector *connector;
@ -66,6 +68,9 @@ typedef struct {
uint32_t underscan_prop_id;
uint32_t underscan_hborder_prop_id;
uint32_t underscan_vborder_prop_id;
uint32_t primary_plane_id;
uint32_t rotation_prop_id;
uint32_t rotation_map[ALL_TRANSFORMS];
} MetaCRTCKms;
struct _MetaMonitorManagerKms
@ -429,6 +434,137 @@ get_output_scale (MetaMonitorManager *manager,
return compute_scale (output);
}
static int
find_property_index (MetaMonitorManager *manager,
drmModeObjectPropertiesPtr props,
const gchar *prop_name,
drmModePropertyPtr *found)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
unsigned int i;
for (i = 0; i < props->count_props; i++)
{
drmModePropertyPtr prop;
prop = drmModeGetProperty (manager_kms->fd, props->props[i]);
if (!prop)
continue;
if (strcmp (prop->name, prop_name) == 0)
{
*found = prop;
return i;
}
drmModeFreeProperty (prop);
}
return -1;
}
static void
parse_transforms (MetaMonitorManager *manager,
drmModePropertyPtr prop,
MetaCRTC *crtc)
{
MetaCRTCKms *crtc_kms = crtc->driver_private;
int i;
for (i = 0; i < prop->count_enums; i++)
{
int cur = -1;
if (strcmp (prop->enums[i].name, "rotate-0") == 0)
cur = META_MONITOR_TRANSFORM_NORMAL;
else if (strcmp (prop->enums[i].name, "rotate-90") == 0)
cur = META_MONITOR_TRANSFORM_90;
else if (strcmp (prop->enums[i].name, "rotate-180") == 0)
cur = META_MONITOR_TRANSFORM_180;
else if (strcmp (prop->enums[i].name, "rotate-270") == 0)
cur = META_MONITOR_TRANSFORM_270;
if (cur != -1)
{
crtc->all_transforms |= 1 << cur;
crtc_kms->rotation_map[cur] = 1 << prop->enums[i].value;
}
}
}
static gboolean
is_primary_plane (MetaMonitorManager *manager,
drmModeObjectPropertiesPtr props)
{
drmModePropertyPtr prop;
int idx;
idx = find_property_index (manager, props, "type", &prop);
if (idx < 0)
return FALSE;
drmModeFreeProperty (prop);
return props->prop_values[idx] == DRM_PLANE_TYPE_PRIMARY;
}
static void
init_crtc_rotations (MetaMonitorManager *manager,
MetaCRTC *crtc,
unsigned int idx)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
drmModeObjectPropertiesPtr props;
drmModePlaneRes *planes;
drmModePlane *drm_plane;
MetaCRTCKms *crtc_kms;
unsigned int i;
crtc_kms = crtc->driver_private;
planes = drmModeGetPlaneResources(manager_kms->fd);
if (planes == NULL)
return;
for (i = 0; i < planes->count_planes; i++)
{
drmModePropertyPtr prop;
drm_plane = drmModeGetPlane (manager_kms->fd, planes->planes[i]);
if (!drm_plane)
continue;
if ((drm_plane->possible_crtcs & (1 << idx)))
{
props = drmModeObjectGetProperties (manager_kms->fd,
drm_plane->plane_id,
DRM_MODE_OBJECT_PLANE);
if (props && is_primary_plane (manager, props))
{
int rotation_idx;
crtc_kms->primary_plane_id = drm_plane->plane_id;
rotation_idx = find_property_index (manager, props, "rotation", &prop);
if (rotation_idx >= 0)
{
crtc_kms->rotation_prop_id = props->props[rotation_idx];
parse_transforms (manager, prop, crtc);
drmModeFreeProperty (prop);
}
}
if (props)
drmModeFreeObjectProperties (props);
}
drmModeFreePlane (drm_plane);
}
drmModeFreePlaneResources (planes);
}
static void
meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
{
@ -496,8 +632,18 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_mode->name = g_strndup (mode->name, DRM_DISPLAY_MODE_LEN);
meta_mode->width = mode->hdisplay;
meta_mode->height = mode->vdisplay;
meta_mode->refresh_rate = (1000 * mode->clock /
((float)mode->htotal * mode->vtotal));
/* Calculate refresh rate in milliHz first for extra precision. */
meta_mode->refresh_rate = (mode->clock * 1000000LL) / mode->htotal;
meta_mode->refresh_rate += (mode->vtotal / 2);
meta_mode->refresh_rate /= mode->vtotal;
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
meta_mode->refresh_rate *= 2;
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
meta_mode->refresh_rate /= 2;
if (mode->vscan > 1)
meta_mode->refresh_rate /= mode->vscan;
meta_mode->refresh_rate /= 1000.0;
meta_mode->driver_private = g_slice_dup (drmModeModeInfo, mode);
meta_mode->driver_notify = (GDestroyNotify)meta_monitor_mode_destroy_notify;
@ -546,6 +692,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_crtc->driver_private = g_new0 (MetaCRTCKms, 1);
meta_crtc->driver_notify = (GDestroyNotify) meta_crtc_destroy_notify;
find_crtc_properties (manager_kms, meta_crtc);
init_crtc_rotations (manager, meta_crtc, i);
drmModeFreeCrtc (crtc);
}
@ -928,6 +1075,7 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
{
MetaCRTCInfo *crtc_info = crtcs[i];
MetaCRTC *crtc = crtc_info->crtc;
MetaCRTCKms *crtc_kms = crtc->driver_private;
CoglKmsCrtc *cogl_crtc;
crtc->is_dirty = TRUE;
@ -1000,6 +1148,13 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
crtc->current_mode = mode;
crtc->transform = crtc_info->transform;
}
if (crtc->all_transforms & (1 << crtc->transform))
drmModeObjectSetProperty (manager_kms->fd,
crtc_kms->primary_plane_id,
DRM_MODE_OBJECT_PLANE,
crtc_kms->rotation_prop_id,
crtc_kms->rotation_map[crtc->transform]);
}
/* Disable CRTCs not mentioned in the list (they have is_dirty == FALSE,
@ -1152,6 +1307,8 @@ meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms)
manager_kms->fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
drmSetClientCap (manager_kms->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
const char *subsystems[2] = { "drm", NULL };
manager_kms->udev = g_udev_client_new (subsystems);
g_signal_connect (manager_kms->udev, "uevent",

View File

@ -82,6 +82,7 @@ struct _MetaBackendX11Private
gchar *keymap_layouts;
gchar *keymap_variants;
gchar *keymap_options;
int locked_group;
};
typedef struct _MetaBackendX11Private MetaBackendX11Private;
@ -297,15 +298,23 @@ handle_host_xevent (MetaBackend *backend,
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;
}
@ -441,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 ();
@ -450,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)
@ -763,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);
}
@ -776,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);
}
@ -795,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);
}

View File

@ -107,20 +107,6 @@ set_alarm_enabled (Display *dpy,
XSyncChangeAlarm (dpy, alarm, XSyncCAEvents, &attr);
}
static void
check_x11_watch (gpointer data,
gpointer user_data)
{
MetaIdleMonitorWatchXSync *watch_xsync = data;
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_xsync;
XSyncAlarm alarm = (XSyncAlarm) user_data;
if (watch_xsync->xalarm != alarm)
return;
_meta_idle_monitor_watch_fire (watch);
}
static char *
counter_name_for_device (int device_id)
{
@ -327,13 +313,38 @@ meta_idle_monitor_xsync_init (MetaIdleMonitorXSync *monitor_xsync)
monitor_xsync->alarms = g_hash_table_new (NULL, NULL);
}
static void
check_x11_watches (MetaIdleMonitor *monitor,
XSyncAlarm alarm)
{
GList *node, *watch_ids;
/* we get the keys and do explicit look ups in case
* an early iteration of the loop ends up leading
* to watches from later iterations getting invalidated
*/
watch_ids = g_hash_table_get_keys (monitor->watches);
for (node = watch_ids; node != NULL; node = node->next)
{
guint watch_id = GPOINTER_TO_UINT (node->data);
MetaIdleMonitorWatchXSync *watch;
watch = g_hash_table_lookup (monitor->watches, GUINT_TO_POINTER (watch_id));
if (watch && watch->xalarm == alarm)
_meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch);
}
g_list_free (watch_ids);
}
void
meta_idle_monitor_xsync_handle_xevent (MetaIdleMonitor *monitor,
XSyncAlarmNotifyEvent *alarm_event)
{
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor);
XSyncAlarm alarm;
GList *watches;
gboolean has_alarm;
if (alarm_event->state != XSyncAlarmActive)
@ -358,10 +369,5 @@ meta_idle_monitor_xsync_handle_xevent (MetaIdleMonitor *monitor,
}
if (has_alarm)
{
watches = g_hash_table_get_values (monitor->watches);
g_list_foreach (watches, check_x11_watch, (gpointer) alarm);
g_list_free (watches);
}
check_x11_watches (monitor, alarm);
}

View File

@ -199,9 +199,9 @@ meta_input_settings_x11_set_invert_scroll (MetaInputSettings *settings,
}
static void
meta_input_settings_x11_set_scroll_method (MetaInputSettings *settings,
ClutterInputDevice *device,
GDesktopTouchpadScrollMethod mode)
meta_input_settings_x11_set_edge_scroll (MetaInputSettings *settings,
ClutterInputDevice *device,
gboolean edge_scroll_enabled)
{
guchar values[3] = { 0 }; /* 2fg, edge, button. The last value is unused */
guchar *available;
@ -211,26 +211,21 @@ meta_input_settings_x11_set_scroll_method (MetaInputSettings *setting
if (!available)
return;
switch (mode)
if (available[0])
{
case G_DESKTOP_TOUCHPAD_SCROLL_METHOD_DISABLED:
break;
case G_DESKTOP_TOUCHPAD_SCROLL_METHOD_EDGE_SCROLLING:
values[1] = 1;
break;
case G_DESKTOP_TOUCHPAD_SCROLL_METHOD_TWO_FINGER_SCROLLING:
values[0] = 1;
break;
default:
g_assert_not_reached ();
}
else if (available[1] && edge_scroll_enabled)
{
values[1] = 1;
}
else
{
/* Disabled */
}
if ((values[0] && !available[0]) || (values[1] && !available[1]))
g_warning ("Device '%s' does not support scroll mode %d\n",
clutter_input_device_get_device_name (device), mode);
else
change_property (device, "libinput Scroll Method Enabled",
XA_INTEGER, 8, &values, 3);
change_property (device, "libinput Scroll Method Enabled",
XA_INTEGER, 8, &values, 3);
meta_XFree (available);
}
@ -321,7 +316,7 @@ meta_input_settings_x11_class_init (MetaInputSettingsX11Class *klass)
input_settings_class->set_left_handed = meta_input_settings_x11_set_left_handed;
input_settings_class->set_tap_enabled = meta_input_settings_x11_set_tap_enabled;
input_settings_class->set_invert_scroll = meta_input_settings_x11_set_invert_scroll;
input_settings_class->set_scroll_method = meta_input_settings_x11_set_scroll_method;
input_settings_class->set_edge_scroll = meta_input_settings_x11_set_edge_scroll;
input_settings_class->set_scroll_button = meta_input_settings_x11_set_scroll_button;
input_settings_class->set_click_method = meta_input_settings_x11_set_click_method;
input_settings_class->set_keyboard_repeat = meta_input_settings_x11_set_keyboard_repeat;

View File

@ -419,12 +419,6 @@ read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
}
if (!result)
{
edid_atom = XInternAtom (manager_xrandr->xdisplay, "XFree86_DDC_EDID1_RAWDATA", FALSE);
result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
}
if (result)
{
if (len > 0 && len % 128 == 0)
@ -637,6 +631,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 +831,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 +856,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 +881,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 +1160,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 +1178,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 +1188,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

@ -33,8 +33,6 @@ struct _MetaCursorRendererX11Nested
MetaCursorRenderer parent;
};
GType meta_cursor_renderer_x11_nested_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE (MetaCursorRendererX11Nested, meta_cursor_renderer_x11_nested,
META_TYPE_CURSOR_RENDERER);

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

@ -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;
}
/**

View File

@ -255,6 +255,31 @@ get_actor_private (MetaWindowActor *actor)
return priv;
}
static ClutterTimeline *
actor_animate (ClutterActor *actor,
ClutterAnimationMode mode,
guint duration,
const gchar *first_property,
...)
{
va_list args;
ClutterTransition *transition;
clutter_actor_save_easing_state (actor);
clutter_actor_set_easing_mode (actor, mode);
clutter_actor_set_easing_duration (actor, duration);
va_start (args, first_property);
g_object_set_valist (G_OBJECT (actor), first_property, args);
va_end (args);
transition = clutter_actor_get_transition (actor, first_property);
clutter_actor_restore_easing_state (actor);
return CLUTTER_TIMELINE (transition);
}
static void
on_switch_workspace_effect_complete (ClutterTimeline *timeline, gpointer data)
{
@ -271,7 +296,10 @@ on_switch_workspace_effect_complete (ClutterTimeline *timeline, gpointer data)
if (apriv->orig_parent)
{
clutter_actor_reparent (a, apriv->orig_parent);
g_object_ref (a);
clutter_actor_remove_child (clutter_actor_get_parent (a), a);
clutter_actor_add_child (apriv->orig_parent, a);
g_object_unref (a);
apriv->orig_parent = NULL;
}
@ -360,11 +388,10 @@ switch_workspace (MetaPlugin *plugin,
MetaScreen *screen;
MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv;
GList *l;
ClutterActor *workspace0 = clutter_group_new ();
ClutterActor *workspace1 = clutter_group_new ();
ClutterActor *workspace0 = clutter_actor_new ();
ClutterActor *workspace1 = clutter_actor_new ();
ClutterActor *stage;
int screen_width, screen_height;
ClutterAnimation *animation;
screen = meta_plugin_get_screen (plugin);
stage = meta_get_stage_for_screen (screen);
@ -373,17 +400,15 @@ switch_workspace (MetaPlugin *plugin,
&screen_width,
&screen_height);
clutter_actor_set_anchor_point (workspace1,
screen_width,
screen_height);
clutter_actor_set_pivot_point (workspace1, 1.0, 1.0);
clutter_actor_set_position (workspace1,
screen_width,
screen_height);
clutter_actor_set_scale (workspace1, 0.0, 0.0);
clutter_container_add_actor (CLUTTER_CONTAINER (stage), workspace1);
clutter_container_add_actor (CLUTTER_CONTAINER (stage), workspace0);
clutter_actor_add_child (stage, workspace1);
clutter_actor_add_child (stage, workspace0);
if (from == to)
{
@ -406,12 +431,15 @@ switch_workspace (MetaPlugin *plugin,
if (win_workspace == to || win_workspace == from)
{
ClutterActor *parent = win_workspace == to ? workspace1 : workspace0;
apriv->orig_parent = clutter_actor_get_parent (actor);
clutter_actor_reparent (actor,
win_workspace == to ? workspace1 : workspace0);
clutter_actor_show_all (actor);
clutter_actor_raise_top (actor);
g_object_ref (actor);
clutter_actor_remove_child (clutter_actor_get_parent (actor), actor);
clutter_actor_add_child (parent, actor);
clutter_actor_show (actor);
clutter_actor_set_child_below_sibling (parent, actor, NULL);
g_object_unref (actor);
}
else if (win_workspace < 0)
{
@ -431,23 +459,21 @@ switch_workspace (MetaPlugin *plugin,
priv->desktop1 = workspace0;
priv->desktop2 = workspace1;
animation = clutter_actor_animate (workspace0, CLUTTER_EASE_IN_SINE,
SWITCH_TIMEOUT,
"scale-x", 1.0,
"scale-y", 1.0,
NULL);
priv->tml_switch_workspace1 = clutter_animation_get_timeline (animation);
priv->tml_switch_workspace1 = actor_animate (workspace0, CLUTTER_EASE_IN_SINE,
SWITCH_TIMEOUT,
"scale-x", 1.0,
"scale-y", 1.0,
NULL);
g_signal_connect (priv->tml_switch_workspace1,
"completed",
G_CALLBACK (on_switch_workspace_effect_complete),
plugin);
animation = clutter_actor_animate (workspace1, CLUTTER_EASE_IN_SINE,
SWITCH_TIMEOUT,
"scale-x", 0.0,
"scale-y", 0.0,
NULL);
priv->tml_switch_workspace2 = clutter_animation_get_timeline (animation);
priv->tml_switch_workspace2 = actor_animate (workspace1, CLUTTER_EASE_IN_SINE,
SWITCH_TIMEOUT,
"scale-x", 0.0,
"scale-y", 0.0,
NULL);
}
@ -504,19 +530,17 @@ minimize (MetaPlugin *plugin, MetaWindowActor *window_actor)
if (type == META_WINDOW_NORMAL)
{
ClutterAnimation *animation;
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
ActorPrivate *apriv = get_actor_private (window_actor);
animation = clutter_actor_animate (actor,
CLUTTER_EASE_IN_SINE,
MINIMIZE_TIMEOUT,
"scale-x", 0.0,
"scale-y", 0.0,
"x", (double)icon_geometry.x,
"y", (double)icon_geometry.y,
NULL);
apriv->tml_minimize = clutter_animation_get_timeline (animation);
apriv->tml_minimize = actor_animate (actor,
CLUTTER_EASE_IN_SINE,
MINIMIZE_TIMEOUT,
"scale-x", 0.0,
"scale-y", 0.0,
"x", (double)icon_geometry.x,
"y", (double)icon_geometry.y,
NULL);
data->plugin = plugin;
data->actor = actor;
g_signal_connect (apriv->tml_minimize, "completed",
@ -561,7 +585,6 @@ map (MetaPlugin *plugin, MetaWindowActor *window_actor)
if (type == META_WINDOW_NORMAL)
{
ClutterAnimation *animation;
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
ActorPrivate *apriv = get_actor_private (window_actor);
@ -570,14 +593,13 @@ map (MetaPlugin *plugin, MetaWindowActor *window_actor)
clutter_actor_set_scale (actor, 0.5, 0.5);
clutter_actor_show (actor);
animation = clutter_actor_animate (actor,
CLUTTER_EASE_OUT_QUAD,
MAP_TIMEOUT,
"opacity", 255,
"scale-x", 1.0,
"scale-y", 1.0,
NULL);
apriv->tml_map = clutter_animation_get_timeline (animation);
apriv->tml_map = actor_animate (actor,
CLUTTER_EASE_OUT_QUAD,
MAP_TIMEOUT,
"opacity", 255,
"scale-x", 1.0,
"scale-y", 1.0,
NULL);
data->actor = actor;
data->plugin = plugin;
g_signal_connect (apriv->tml_map, "completed",
@ -618,18 +640,16 @@ destroy (MetaPlugin *plugin, MetaWindowActor *window_actor)
if (type == META_WINDOW_NORMAL)
{
ClutterAnimation *animation;
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
ActorPrivate *apriv = get_actor_private (window_actor);
animation = clutter_actor_animate (actor,
CLUTTER_EASE_OUT_QUAD,
DESTROY_TIMEOUT,
"opacity", 0,
"scale-x", 0.8,
"scale-y", 0.8,
NULL);
apriv->tml_destroy = clutter_animation_get_timeline (animation);
apriv->tml_destroy = actor_animate (actor,
CLUTTER_EASE_OUT_QUAD,
DESTROY_TIMEOUT,
"opacity", 0,
"scale-x", 0.8,
"scale-y", 0.8,
NULL);
data->plugin = plugin;
data->actor = actor;
g_signal_connect (apriv->tml_destroy, "completed",
@ -702,7 +722,9 @@ show_tile_preview (MetaPlugin *plugin,
clutter_actor_show (preview->actor);
window_actor = CLUTTER_ACTOR (meta_window_get_compositor_private (window));
clutter_actor_lower (preview->actor, window_actor);
clutter_actor_set_child_below_sibling (clutter_actor_get_parent (preview->actor),
preview->actor,
window_actor);
preview->tile_rect = *tile_rect;
}

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

@ -182,10 +182,25 @@ meta_display_handle_event (MetaDisplay *display,
sequence = clutter_event_get_event_sequence (event);
/* Set the pointer emulating sequence on touch begin, if eligible */
if (event->type == CLUTTER_TOUCH_BEGIN &&
!display->pointer_emulating_sequence &&
sequence_is_pointer_emulated (display, event))
display->pointer_emulating_sequence = sequence;
if (event->type == CLUTTER_TOUCH_BEGIN)
{
if (sequence_is_pointer_emulated (display, event))
{
/* This is the new pointer emulating sequence */
display->pointer_emulating_sequence = sequence;
}
else if (display->pointer_emulating_sequence == sequence)
{
/* This sequence was "pointer emulating" in a prior incarnation,
* but now it isn't. We unset the pointer emulating sequence at
* this point so the current sequence is not mistaken as pointer
* emulating, while we've ensured that it's been deemed
* "pointer emulating" throughout all of the event processing
* of the previous incarnation.
*/
display->pointer_emulating_sequence = NULL;
}
}
#ifdef HAVE_WAYLAND
MetaWaylandCompositor *compositor = NULL;
@ -206,8 +221,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;
}
@ -335,11 +350,6 @@ meta_display_handle_event (MetaDisplay *display,
}
#endif
/* Unset the pointer emulating sequence after its end event is processed */
if (event->type == CLUTTER_TOUCH_END &&
display->pointer_emulating_sequence == sequence)
display->pointer_emulating_sequence = NULL;
display->current_time = CurrentTime;
return bypass_clutter;
}

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

@ -80,6 +80,10 @@
#ifdef HAVE_WAYLAND
#include "wayland/meta-wayland.h"
# endif
#if defined(HAVE_NATIVE_BACKEND) && defined(HAVE_WAYLAND)
#include <systemd/sd-login.h>
#endif
/*
@ -291,6 +295,95 @@ on_sigterm (gpointer user_data)
return G_SOURCE_REMOVE;
}
#if defined(HAVE_WAYLAND) && defined(HAVE_NATIVE_BACKEND)
static char *
find_logind_session_type (void)
{
char **sessions;
char *session_id;
char *session_type;
int ret, i;
ret = sd_pid_get_session (0, &session_id);
if (ret == 0 && session_id != NULL)
{
ret = sd_session_get_type (session_id, &session_type);
free (session_id);
if (ret < 0)
session_type = NULL;
goto out;
}
session_type = NULL;
ret = sd_uid_get_sessions (getuid (), TRUE, &sessions);
if (ret < 0 || sessions == NULL)
goto out;
for (i = 0; sessions[i] != NULL; i++)
{
ret = sd_session_get_type (sessions[i], &session_type);
if (ret < 0)
continue;
if (g_strcmp0 (session_type, "x11") == 0||
g_strcmp0 (session_type, "wayland") == 0)
break;
g_clear_pointer (&session_type, (GDestroyNotify) free);
}
for (i = 0; sessions[i] != NULL; i++)
free (sessions[i]);
free (sessions);
out:
return session_type;
}
static gboolean
check_for_wayland_session_type (void)
{
char *session_type = NULL;
gboolean is_wayland = FALSE;
session_type = find_logind_session_type ();
if (session_type != NULL)
{
is_wayland = g_strcmp0 (session_type, "wayland") == 0;
free (session_type);
}
return is_wayland;
}
#endif
static void
init_backend (void)
{
gboolean session_type_is_wayland = FALSE;
#if defined(HAVE_WAYLAND) && defined(HAVE_NATIVE_BACKEND)
session_type_is_wayland = check_for_wayland_session_type ();
#endif
#if defined(CLUTTER_WINDOWING_EGL) && defined(HAVE_NATIVE_BACKEND)
if (opt_display_server || session_type_is_wayland)
clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
else
#endif
clutter_set_windowing_backend (CLUTTER_WINDOWING_X11);
#ifdef HAVE_WAYLAND
meta_set_is_wayland_compositor (opt_wayland || session_type_is_wayland);
#endif
}
/**
* meta_init: (skip)
*
@ -323,16 +416,7 @@ meta_init (void)
if (g_getenv ("MUTTER_DEBUG"))
meta_set_debugging (TRUE);
#if defined(CLUTTER_WINDOWING_EGL) && defined(HAVE_NATIVE_BACKEND)
if (opt_display_server)
clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
else
#endif
clutter_set_windowing_backend (CLUTTER_WINDOWING_X11);
#ifdef HAVE_WAYLAND
meta_set_is_wayland_compositor (opt_wayland);
#endif
init_backend ();
if (g_get_home_dir ())
if (chdir (g_get_home_dir ()) < 0)

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;
@ -1431,42 +1477,11 @@ button_function_from_string (const char *str)
return META_BUTTON_FUNCTION_MAXIMIZE;
else if (strcmp (str, "close") == 0)
return META_BUTTON_FUNCTION_CLOSE;
else if (strcmp (str, "shade") == 0)
return META_BUTTON_FUNCTION_SHADE;
else if (strcmp (str, "above") == 0)
return META_BUTTON_FUNCTION_ABOVE;
else if (strcmp (str, "stick") == 0)
return META_BUTTON_FUNCTION_STICK;
else
/* don't know; give up */
return META_BUTTON_FUNCTION_LAST;
}
static MetaButtonFunction
button_opposite_function (MetaButtonFunction ofwhat)
{
switch (ofwhat)
{
case META_BUTTON_FUNCTION_SHADE:
return META_BUTTON_FUNCTION_UNSHADE;
case META_BUTTON_FUNCTION_UNSHADE:
return META_BUTTON_FUNCTION_SHADE;
case META_BUTTON_FUNCTION_ABOVE:
return META_BUTTON_FUNCTION_UNABOVE;
case META_BUTTON_FUNCTION_UNABOVE:
return META_BUTTON_FUNCTION_ABOVE;
case META_BUTTON_FUNCTION_STICK:
return META_BUTTON_FUNCTION_UNSTICK;
case META_BUTTON_FUNCTION_UNSTICK:
return META_BUTTON_FUNCTION_STICK;
default:
return META_BUTTON_FUNCTION_LAST;
}
}
static gboolean
button_layout_handler (GVariant *value,
gpointer *result,
@ -1510,12 +1525,6 @@ button_layout_handler (GVariant *value,
if (i > 0 && strcmp("spacer", buttons[b]) == 0)
{
new_layout.left_buttons_has_spacer[i-1] = TRUE;
f = button_opposite_function (f);
if (f != META_BUTTON_FUNCTION_LAST)
{
new_layout.left_buttons_has_spacer[i-2] = TRUE;
}
}
else
{
@ -1524,11 +1533,6 @@ button_layout_handler (GVariant *value,
new_layout.left_buttons[i] = f;
used[f] = TRUE;
++i;
f = button_opposite_function (f);
if (f != META_BUTTON_FUNCTION_LAST)
new_layout.left_buttons[i++] = f;
}
else
{
@ -1572,11 +1576,6 @@ button_layout_handler (GVariant *value,
if (i > 0 && strcmp("spacer", buttons[b]) == 0)
{
new_layout.right_buttons_has_spacer[i-1] = TRUE;
f = button_opposite_function (f);
if (f != META_BUTTON_FUNCTION_LAST)
{
new_layout.right_buttons_has_spacer[i-2] = TRUE;
}
}
else
{
@ -1585,12 +1584,6 @@ button_layout_handler (GVariant *value,
new_layout.right_buttons[i] = f;
used[f] = TRUE;
++i;
f = button_opposite_function (f);
if (f != META_BUTTON_FUNCTION_LAST)
new_layout.right_buttons[i++] = f;
}
else
{

View File

@ -2100,7 +2100,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
@ -1567,8 +1579,10 @@ implement_showing (MetaWindow *window,
* windows we might want to know where they are on the screen,
* so we should place the window even if we're hiding it rather
* than showing it.
* Force placing windows only when they should be already mapped,
* see #751887
*/
if (!window->placed)
if (!window->placed && client_window_should_be_mapped (window))
meta_window_force_placement (window);
meta_window_hide (window);
@ -3183,12 +3197,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 +3224,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 +3233,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 +3249,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 +3536,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 +4343,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 +4358,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);
}
}
@ -5271,6 +5302,11 @@ meta_window_recalc_features (MetaWindow *window)
meta_window_recalc_skip_features (window);
/* To prevent users from losing windows, let's prevent users from
* minimizing skip-taskbar windows through the window decorations. */
if (window->skip_taskbar)
window->has_minimize_func = FALSE;
meta_topic (META_DEBUG_WINDOW_OPS,
"Window %s decorated = %d border_only = %d has_close = %d has_minimize = %d has_maximize = %d has_move = %d has_shade = %d skip_taskbar = %d skip_pager = %d\n",
window->desc,
@ -6272,7 +6308,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 +7046,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)
@ -7381,14 +7417,14 @@ meta_window_set_transient_for (MetaWindow *window,
}
}
/* update stacking constraints */
if (!window->override_redirect)
meta_stack_update_transient (window->screen->stack, window);
/* We know this won't create a reference cycle because we check for loops */
g_clear_object (&window->transient_for);
window->transient_for = parent ? g_object_ref (parent) : NULL;
/* update stacking constraints */
if (!window->override_redirect)
meta_stack_update_transient (window->screen->stack, window);
/* possibly change its group. We treat being a window's transient as
* equivalent to making it your group leader, to work around shortcomings
* in programs such as xmms-- see #328211.
@ -7399,7 +7435,7 @@ meta_window_set_transient_for (MetaWindow *window,
meta_window_group_leader_changed (window);
if (!window->constructing && !window->override_redirect)
meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
meta_window_queue (window, META_QUEUE_MOVE_RESIZE | META_QUEUE_CALC_SHOWING);
if (meta_window_appears_focused (window) && window->transient_for != NULL)
meta_window_propagate_focus_appearance (window, TRUE);
@ -7638,13 +7674,29 @@ meta_window_handle_ungrabbed_event (MetaWindow *window,
MetaDisplay *display = window->display;
gboolean unmodified;
gboolean is_window_grab;
ClutterModifierType grab_mods, event_mods;
gfloat x, y;
guint button;
if (window->frame && meta_ui_frame_handle_event (window->frame->ui_frame, event))
return;
if (event->type != CLUTTER_BUTTON_PRESS)
if (event->type != CLUTTER_BUTTON_PRESS &&
event->type != CLUTTER_TOUCH_BEGIN)
return;
if (event->type == CLUTTER_TOUCH_BEGIN)
{
ClutterEventSequence *sequence;
button = 1;
sequence = clutter_event_get_event_sequence (event);
if (!meta_display_is_pointer_emulating_sequence (window->display, sequence))
return;
}
else
button = clutter_event_get_button (event);
if (display->grab_op != META_GRAB_OP_NONE)
return;
@ -7655,6 +7707,22 @@ meta_window_handle_ungrabbed_event (MetaWindow *window,
if (window->override_redirect)
return;
/* Don't focus panels--they must explicitly request focus.
* See bug 160470
*/
if (window->type != META_WINDOW_DOCK)
{
meta_topic (META_DEBUG_FOCUS,
"Focusing %s due to button %u press (display.c)\n",
window->desc, button);
meta_window_focus (window, event->any.time);
}
else
/* However, do allow terminals to lose focus due to new
* window mappings after the user clicks on a panel.
*/
display->allow_terminal_deactivation = TRUE;
/* We have three passive button grabs:
* - on any button, without modifiers => focuses and maybe raises the window
* - on resize button, with modifiers => start an interactive resizing
@ -7675,9 +7743,12 @@ meta_window_handle_ungrabbed_event (MetaWindow *window,
* care about. Just let the event through.
*/
ClutterModifierType grab_mods = meta_display_get_window_grab_modifiers (display);
unmodified = (event->button.modifier_state & grab_mods) == 0;
is_window_grab = (event->button.modifier_state & grab_mods) == grab_mods;
grab_mods = meta_display_get_window_grab_modifiers (display);
event_mods = clutter_event_get_state (event);
unmodified = (event_mods & grab_mods) == 0;
is_window_grab = (event_mods & grab_mods) == grab_mods;
clutter_event_get_coords (event, &x, &y);
if (unmodified)
{
@ -7686,27 +7757,8 @@ meta_window_handle_ungrabbed_event (MetaWindow *window,
else
meta_topic (META_DEBUG_FOCUS,
"Not raising window on click due to don't-raise-on-click option\n");
/* Don't focus panels--they must explicitly request focus.
* See bug 160470
*/
if (window->type != META_WINDOW_DOCK)
{
meta_topic (META_DEBUG_FOCUS,
"Focusing %s due to unmodified button %u press (display.c)\n",
window->desc, event->button.button);
meta_window_focus (window, event->any.time);
}
else
/* However, do allow terminals to lose focus due to new
* window mappings after the user clicks on a panel.
*/
display->allow_terminal_deactivation = TRUE;
meta_verbose ("Allowing events time %u\n",
(unsigned int)event->button.time);
}
else if (is_window_grab && (int) event->button.button == meta_prefs_get_mouse_button_resize ())
else if (is_window_grab && (int) button == meta_prefs_get_mouse_button_resize ())
{
if (window->has_resize_func)
{
@ -7717,10 +7769,10 @@ meta_window_handle_ungrabbed_event (MetaWindow *window,
meta_window_get_frame_rect (window, &frame_rect);
west = event->button.x < (frame_rect.x + 1 * frame_rect.width / 3);
east = event->button.x > (frame_rect.x + 2 * frame_rect.width / 3);
north = event->button.y < (frame_rect.y + 1 * frame_rect.height / 3);
south = event->button.y > (frame_rect.y + 2 * frame_rect.height / 3);
west = x < (frame_rect.x + 1 * frame_rect.width / 3);
east = x > (frame_rect.x + 2 * frame_rect.width / 3);
north = y < (frame_rect.y + 1 * frame_rect.height / 3);
south = y > (frame_rect.y + 2 * frame_rect.height / 3);
if (west)
op |= META_GRAB_OP_WINDOW_DIR_WEST;
@ -7738,23 +7790,21 @@ meta_window_handle_ungrabbed_event (MetaWindow *window,
op,
TRUE,
FALSE,
event->button.button,
button,
0,
event->any.time,
event->button.x,
event->button.y);
x, y);
}
}
else if (is_window_grab && (int) event->button.button == meta_prefs_get_mouse_button_menu ())
else if (is_window_grab && (int) button == meta_prefs_get_mouse_button_menu ())
{
if (meta_prefs_get_raise_on_click ())
meta_window_raise (window);
meta_window_show_menu (window,
META_WINDOW_MENU_WM,
event->button.x,
event->button.y);
x, y);
}
else if (is_window_grab && (int) event->button.button == 1)
else if (is_window_grab && (int) button == 1)
{
if (window->has_move_func)
{
@ -7764,11 +7814,10 @@ meta_window_handle_ungrabbed_event (MetaWindow *window,
META_GRAB_OP_MOVING,
TRUE,
FALSE,
event->button.button,
button,
0,
event->any.time,
event->button.x,
event->button.y);
x, y);
}
}
}

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

@ -372,12 +372,6 @@ typedef enum
* @META_BUTTON_FUNCTION_MINIMIZE: Minimize
* @META_BUTTON_FUNCTION_MAXIMIZE: Maximize
* @META_BUTTON_FUNCTION_CLOSE: Close
* @META_BUTTON_FUNCTION_SHADE: Shade
* @META_BUTTON_FUNCTION_ABOVE: Above
* @META_BUTTON_FUNCTION_STICK: Stick
* @META_BUTTON_FUNCTION_UNSHADE: Unshade
* @META_BUTTON_FUNCTION_UNABOVE: Unabove
* @META_BUTTON_FUNCTION_UNSTICK: Unstick
* @META_BUTTON_FUNCTION_LAST: Marks the end of the #MetaButtonFunction enumeration
*
* Function a window button can have. Note, you can't add stuff here
@ -390,12 +384,6 @@ typedef enum
META_BUTTON_FUNCTION_MINIMIZE,
META_BUTTON_FUNCTION_MAXIMIZE,
META_BUTTON_FUNCTION_CLOSE,
META_BUTTON_FUNCTION_SHADE,
META_BUTTON_FUNCTION_ABOVE,
META_BUTTON_FUNCTION_STICK,
META_BUTTON_FUNCTION_UNSHADE,
META_BUTTON_FUNCTION_UNABOVE,
META_BUTTON_FUNCTION_UNSTICK,
META_BUTTON_FUNCTION_APPMENU,
META_BUTTON_FUNCTION_LAST
} MetaButtonFunction;
@ -405,10 +393,10 @@ typedef enum
/* Keep array size in sync with MAX_BUTTONS_PER_CORNER */
/**
* MetaButtonLayout:
* @left_buttons: (array fixed-size=11):
* @right_buttons: (array fixed-size=11):
* @left_buttons_has_spacer: (array fixed-size=11):
* @right_buttons_has_spacer: (array fixed-size=11):
* @left_buttons: (array fixed-size=5):
* @right_buttons: (array fixed-size=5):
* @left_buttons_has_spacer: (array fixed-size=5):
* @right_buttons_has_spacer: (array fixed-size=5):
*/
typedef struct _MetaButtonLayout MetaButtonLayout;
struct _MetaButtonLayout

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

@ -0,0 +1,14 @@
new_client 1 wayland
create 1/1
show 1/1
create 1/2
show 1/2
wait
assert_stacking 1/1 1/2
set_parent 1/1 2
wait
assert_stacking 1/2 1/1
local_activate 1/2
assert_stacking 1/2 1/1

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;
@ -41,6 +41,16 @@ lookup_window (const char *window_id)
return window;
}
static void
on_after_paint (GdkFrameClock *clock,
GMainLoop *loop)
{
g_signal_handlers_disconnect_by_func (clock,
(gpointer) on_after_paint,
loop);
g_main_loop_quit (loop);
}
static void
process_line (const char *line)
{
@ -126,6 +136,31 @@ process_line (const char *line)
}
}
else if (strcmp (argv[0], "set_parent") == 0)
{
if (argc != 3)
{
g_print ("usage: menu <window-id> <parent-id>");
goto out;
}
GtkWidget *window = lookup_window (argv[1]);
if (!window)
{
g_print ("unknown window %s", argv[1]);
goto out;
}
GtkWidget *parent_window = lookup_window (argv[2]);
if (!parent_window)
{
g_print ("unknown parent window %s", argv[2]);
goto out;
}
gtk_window_set_transient_for (GTK_WINDOW (window),
GTK_WINDOW (parent_window));
}
else if (strcmp (argv[0], "show") == 0)
{
if (argc != 2)
@ -135,10 +170,25 @@ process_line (const char *line)
}
GtkWidget *window = lookup_window (argv[1]);
GdkWindow *gdk_window = gtk_widget_get_window (window);
if (!window)
goto out;
gtk_widget_show (window);
/* When a Wayland client, we cannot be really sure that the window has
* been mappable until after we have painted. So, in order to have the
* test runner rely on the "show" command to have done what the client
* needs to do in order for a window to be mappable compositor side, lets
* wait with returning until after the first frame.
*/
GdkFrameClock *frame_clock = gdk_window_get_frame_clock (gdk_window);
GMainLoop *loop = g_main_loop_new (NULL, FALSE);
g_signal_connect (frame_clock, "after-paint",
G_CALLBACK (on_after_paint),
loop);
g_main_loop_run (loop);
g_main_loop_unref (loop);
}
else if (strcmp (argv[0], "hide") == 0)
{

View File

@ -767,6 +767,23 @@ test_case_do (TestCase *test,
NULL))
return FALSE;
}
else if (strcmp (argv[0], "set_parent") == 0)
{
if (argc != 3)
BAD_COMMAND("usage: %s <client-id>/<window-id> <parent-window-id>",
argv[0]);
TestClient *client;
const char *window_id;
if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error))
return FALSE;
if (!test_client_do (client, error,
"set_parent", window_id,
argv[2],
NULL))
return FALSE;
}
else if (strcmp (argv[0], "show") == 0 ||
strcmp (argv[0], "hide") == 0 ||
strcmp (argv[0], "activate") == 0 ||
@ -1094,7 +1111,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 +1136,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

@ -970,12 +970,6 @@ meta_frame_left_click_event (MetaUIFrame *frame,
case META_FRAME_CONTROL_UNMAXIMIZE:
case META_FRAME_CONTROL_MINIMIZE:
case META_FRAME_CONTROL_DELETE:
case META_FRAME_CONTROL_SHADE:
case META_FRAME_CONTROL_UNSHADE:
case META_FRAME_CONTROL_ABOVE:
case META_FRAME_CONTROL_UNABOVE:
case META_FRAME_CONTROL_STICK:
case META_FRAME_CONTROL_UNSTICK:
case META_FRAME_CONTROL_MENU:
case META_FRAME_CONTROL_APPMENU:
frame->grab_button = event->button;
@ -1074,7 +1068,10 @@ handle_button_press_event (MetaUIFrame *frame,
control = get_control (frame, event->x, event->y);
/* focus on click, even if click was on client area */
/* don't do the rest of this if on client area */
if (control == META_FRAME_CONTROL_CLIENT_AREA)
return FALSE; /* not on the frame, just passed through from client */
if (event->button == 1 &&
!(control == META_FRAME_CONTROL_MINIMIZE ||
control == META_FRAME_CONTROL_DELETE ||
@ -1086,10 +1083,6 @@ handle_button_press_event (MetaUIFrame *frame,
meta_window_focus (frame->meta_window, event->time);
}
/* don't do the rest of this if on client area */
if (control == META_FRAME_CONTROL_CLIENT_AREA)
return FALSE; /* not on the frame, just passed through from client */
/* We want to shade even if we have a GrabOp, since we'll have a move grab
* if we double click the titlebar.
*/
@ -1154,24 +1147,6 @@ handle_button_release_event (MetaUIFrame *frame,
case META_FRAME_CONTROL_DELETE:
meta_window_delete (frame->meta_window, event->time);
break;
case META_FRAME_CONTROL_SHADE:
meta_window_shade (frame->meta_window, event->time);
break;
case META_FRAME_CONTROL_UNSHADE:
meta_window_unshade (frame->meta_window, event->time);
break;
case META_FRAME_CONTROL_ABOVE:
meta_window_make_above (frame->meta_window);
break;
case META_FRAME_CONTROL_UNABOVE:
meta_window_unmake_above (frame->meta_window);
break;
case META_FRAME_CONTROL_STICK:
meta_window_stick (frame->meta_window);
break;
case META_FRAME_CONTROL_UNSTICK:
meta_window_unstick (frame->meta_window);
break;
default:
break;
}
@ -1220,18 +1195,6 @@ meta_ui_frame_update_prelit_control (MetaUIFrame *frame,
break;
case META_FRAME_CONTROL_UNMAXIMIZE:
break;
case META_FRAME_CONTROL_SHADE:
break;
case META_FRAME_CONTROL_UNSHADE:
break;
case META_FRAME_CONTROL_ABOVE:
break;
case META_FRAME_CONTROL_UNABOVE:
break;
case META_FRAME_CONTROL_STICK:
break;
case META_FRAME_CONTROL_UNSTICK:
break;
case META_FRAME_CONTROL_RESIZE_SE:
cursor = META_CURSOR_SE_RESIZE;
break;
@ -1270,12 +1233,6 @@ meta_ui_frame_update_prelit_control (MetaUIFrame *frame,
case META_FRAME_CONTROL_MINIMIZE:
case META_FRAME_CONTROL_MAXIMIZE:
case META_FRAME_CONTROL_DELETE:
case META_FRAME_CONTROL_SHADE:
case META_FRAME_CONTROL_UNSHADE:
case META_FRAME_CONTROL_ABOVE:
case META_FRAME_CONTROL_UNABOVE:
case META_FRAME_CONTROL_STICK:
case META_FRAME_CONTROL_UNSTICK:
case META_FRAME_CONTROL_UNMAXIMIZE:
/* leave control set */
break;
@ -1487,24 +1444,6 @@ meta_ui_frame_paint (MetaUIFrame *frame,
case META_FRAME_CONTROL_UNMAXIMIZE:
button_type = META_BUTTON_TYPE_MAXIMIZE;
break;
case META_FRAME_CONTROL_SHADE:
button_type = META_BUTTON_TYPE_SHADE;
break;
case META_FRAME_CONTROL_UNSHADE:
button_type = META_BUTTON_TYPE_UNSHADE;
break;
case META_FRAME_CONTROL_ABOVE:
button_type = META_BUTTON_TYPE_ABOVE;
break;
case META_FRAME_CONTROL_UNABOVE:
button_type = META_BUTTON_TYPE_UNABOVE;
break;
case META_FRAME_CONTROL_STICK:
button_type = META_BUTTON_TYPE_STICK;
break;
case META_FRAME_CONTROL_UNSTICK:
button_type = META_BUTTON_TYPE_UNSTICK;
break;
case META_FRAME_CONTROL_DELETE:
button_type = META_BUTTON_TYPE_CLOSE;
break;
@ -1624,24 +1563,6 @@ control_rect (MetaFrameControl control,
case META_FRAME_CONTROL_UNMAXIMIZE:
rect = &fgeom->max_rect.visible;
break;
case META_FRAME_CONTROL_SHADE:
rect = &fgeom->shade_rect.visible;
break;
case META_FRAME_CONTROL_UNSHADE:
rect = &fgeom->unshade_rect.visible;
break;
case META_FRAME_CONTROL_ABOVE:
rect = &fgeom->above_rect.visible;
break;
case META_FRAME_CONTROL_UNABOVE:
rect = &fgeom->unabove_rect.visible;
break;
case META_FRAME_CONTROL_STICK:
rect = &fgeom->stick_rect.visible;
break;
case META_FRAME_CONTROL_UNSTICK:
rect = &fgeom->unstick_rect.visible;
break;
case META_FRAME_CONTROL_RESIZE_SE:
break;
case META_FRAME_CONTROL_RESIZE_S:
@ -1726,36 +1647,6 @@ get_control (MetaUIFrame *frame, int root_x, int root_y)
return META_FRAME_CONTROL_MAXIMIZE;
}
if (POINT_IN_RECT (x, y, fgeom.shade_rect.clickable))
{
return META_FRAME_CONTROL_SHADE;
}
if (POINT_IN_RECT (x, y, fgeom.unshade_rect.clickable))
{
return META_FRAME_CONTROL_UNSHADE;
}
if (POINT_IN_RECT (x, y, fgeom.above_rect.clickable))
{
return META_FRAME_CONTROL_ABOVE;
}
if (POINT_IN_RECT (x, y, fgeom.unabove_rect.clickable))
{
return META_FRAME_CONTROL_UNABOVE;
}
if (POINT_IN_RECT (x, y, fgeom.stick_rect.clickable))
{
return META_FRAME_CONTROL_STICK;
}
if (POINT_IN_RECT (x, y, fgeom.unstick_rect.clickable))
{
return META_FRAME_CONTROL_UNSTICK;
}
/* South resize always has priority over north resize,
* in case of overlap.
*/

View File

@ -39,12 +39,6 @@ typedef enum
META_FRAME_CONTROL_MINIMIZE,
META_FRAME_CONTROL_MAXIMIZE,
META_FRAME_CONTROL_UNMAXIMIZE,
META_FRAME_CONTROL_SHADE,
META_FRAME_CONTROL_UNSHADE,
META_FRAME_CONTROL_ABOVE,
META_FRAME_CONTROL_UNABOVE,
META_FRAME_CONTROL_STICK,
META_FRAME_CONTROL_UNSTICK,
META_FRAME_CONTROL_RESIZE_SE,
META_FRAME_CONTROL_RESIZE_S,
META_FRAME_CONTROL_RESIZE_SW,

View File

@ -60,6 +60,16 @@ struct _MetaFrameLayout
/** Border/padding of titlebar buttons */
GtkBorder button_border;
/** Margin of title */
GtkBorder title_margin;
/** Margin of titlebar buttons */
GtkBorder button_margin;
/** Min size of titlebar region */
GtkRequisition titlebar_min_size;
/** Min size of titlebar buttons */
GtkRequisition button_min_size;
/** Size of images in buttons */
guint icon_size;
@ -115,7 +125,7 @@ struct _MetaFrameGeometry
/* used for a memset hack */
#define ADDRESS_OF_BUTTON_RECTS(fgeom) (((char*)(fgeom)) + G_STRUCT_OFFSET (MetaFrameGeometry, close_rect))
#define LENGTH_OF_BUTTON_RECTS (G_STRUCT_OFFSET (MetaFrameGeometry, unstick_rect) + sizeof (MetaButtonSpace) - G_STRUCT_OFFSET (MetaFrameGeometry, close_rect))
#define LENGTH_OF_BUTTON_RECTS (G_STRUCT_OFFSET (MetaFrameGeometry, appmenu_rect) + sizeof (MetaButtonSpace) - G_STRUCT_OFFSET (MetaFrameGeometry, close_rect))
/* The button rects (if changed adjust memset hack) */
MetaButtonSpace close_rect;
@ -123,12 +133,6 @@ struct _MetaFrameGeometry
MetaButtonSpace min_rect;
MetaButtonSpace menu_rect;
MetaButtonSpace appmenu_rect;
MetaButtonSpace shade_rect;
MetaButtonSpace above_rect;
MetaButtonSpace stick_rect;
MetaButtonSpace unshade_rect;
MetaButtonSpace unabove_rect;
MetaButtonSpace unstick_rect;
/* End of button rects (if changed adjust memset hack) */
/* Saved button layout */
@ -158,12 +162,6 @@ typedef enum
META_BUTTON_TYPE_MINIMIZE,
META_BUTTON_TYPE_MENU,
META_BUTTON_TYPE_APPMENU,
META_BUTTON_TYPE_SHADE,
META_BUTTON_TYPE_ABOVE,
META_BUTTON_TYPE_STICK,
META_BUTTON_TYPE_UNSHADE,
META_BUTTON_TYPE_UNABOVE,
META_BUTTON_TYPE_UNSTICK,
META_BUTTON_TYPE_LAST
} MetaButtonType;

View File

@ -79,10 +79,14 @@ meta_frame_layout_get_borders (const MetaFrameLayout *layout,
if (!layout->has_title)
text_height = 0;
else
text_height = layout->title_margin.top + text_height + layout->title_margin.bottom;
buttons_height = layout->icon_size +
layout->button_border.top + layout->button_border.bottom;
content_height = MAX (buttons_height, text_height) +
buttons_height = MAX ((int)layout->icon_size, layout->button_min_size.height) +
layout->button_margin.top + layout->button_border.top +
layout->button_margin.bottom + layout->button_border.bottom;
content_height = MAX (buttons_height, text_height);
content_height = MAX (content_height, layout->titlebar_min_size.height) +
layout->titlebar_border.top + layout->titlebar_border.bottom;
borders->visible.top = layout->frame_border.top + content_height;
@ -177,17 +181,6 @@ rect_for_function (MetaFrameGeometry *fgeom,
return &fgeom->close_rect;
else
return NULL;
case META_BUTTON_FUNCTION_STICK:
case META_BUTTON_FUNCTION_SHADE:
case META_BUTTON_FUNCTION_ABOVE:
case META_BUTTON_FUNCTION_UNSTICK:
case META_BUTTON_FUNCTION_UNSHADE:
case META_BUTTON_FUNCTION_UNABOVE:
/* Fringe buttons that used to be supported by theme versions >v1;
* if we want to support them again, we need to return the
* correspondings rects here
*/
return NULL;
case META_BUTTON_FUNCTION_LAST:
return NULL;
@ -245,6 +238,16 @@ get_padding_and_border (GtkStyleContext *style,
border->bottom += tmp.bottom;
}
static void
get_min_size (GtkStyleContext *style,
GtkRequisition *requisition)
{
gtk_style_context_get (style, gtk_style_context_get_state (style),
"min-width", &requisition->width,
"min-height", &requisition->height,
NULL);
}
static void
scale_border (GtkBorder *border,
double factor)
@ -262,6 +265,7 @@ meta_frame_layout_sync_with_style (MetaFrameLayout *layout,
{
GtkStyleContext *style;
GtkBorder border;
GtkRequisition requisition;
int border_radius, max_radius;
meta_style_info_set_flags (style_info, flags);
@ -292,14 +296,25 @@ meta_frame_layout_sync_with_style (MetaFrameLayout *layout,
max_radius = MIN (layout->frame_border.bottom, layout->frame_border.right);
layout->bottom_right_corner_rounded_radius = MAX (border_radius, max_radius);
get_min_size (style, &layout->titlebar_min_size);
get_padding_and_border (style, &layout->titlebar_border);
scale_border (&layout->titlebar_border, layout->title_scale);
style = style_info->styles[META_STYLE_ELEMENT_TITLE];
gtk_style_context_get_margin (style, gtk_style_context_get_state (style),
&layout->title_margin);
scale_border (&layout->title_margin, layout->title_scale);
style = style_info->styles[META_STYLE_ELEMENT_BUTTON];
get_min_size (style, &layout->button_min_size);
get_padding_and_border (style, &layout->button_border);
scale_border (&layout->button_border, layout->title_scale);
gtk_style_context_get_margin (style, gtk_style_context_get_state (style),
&layout->button_margin);
scale_border (&layout->button_margin, layout->title_scale);
style = style_info->styles[META_STYLE_ELEMENT_IMAGE];
get_min_size (style, &requisition);
get_padding_and_border (style, &border);
scale_border (&border, layout->title_scale);
@ -307,6 +322,18 @@ meta_frame_layout_sync_with_style (MetaFrameLayout *layout,
layout->button_border.right += border.right;
layout->button_border.top += border.top;
layout->button_border.bottom += border.bottom;
gtk_style_context_get_margin (style, gtk_style_context_get_state (style),
&border);
layout->button_border.left += border.left;
layout->button_border.right += border.right;
layout->button_border.top += border.top;
layout->button_border.bottom += border.bottom;
layout->button_min_size.width = MAX(layout->button_min_size.width,
requisition.width);
layout->button_min_size.height = MAX(layout->button_min_size.height,
requisition.height);
}
static void
@ -370,9 +397,9 @@ meta_frame_layout_calc_geometry (MetaFrameLayout *layout,
(fgeom->content_border.right + borders.invisible.right);
content_height = borders.visible.top - fgeom->content_border.top - fgeom->content_border.bottom;
button_width = layout->icon_size +
button_width = MAX ((int)layout->icon_size, layout->button_min_size.width) +
layout->button_border.left + layout->button_border.right;
button_height = layout->icon_size +
button_height = MAX ((int)layout->icon_size, layout->button_min_size.height) +
layout->button_border.top + layout->button_border.bottom;
button_width *= scale;
button_height *= scale;
@ -433,11 +460,15 @@ meta_frame_layout_calc_geometry (MetaFrameLayout *layout,
space_used_by_buttons = 0;
space_used_by_buttons += layout->button_margin.left * scale * n_left;
space_used_by_buttons += button_width * n_left;
space_used_by_buttons += layout->button_margin.right * scale * n_left;
space_used_by_buttons += (button_width * 0.75) * n_left_spacers;
space_used_by_buttons += layout->titlebar_spacing * scale * MAX (n_left - 1, 0);
space_used_by_buttons += layout->button_margin.left * scale * n_right;
space_used_by_buttons += button_width * n_right;
space_used_by_buttons += layout->button_margin.right * scale * n_right;
space_used_by_buttons += (button_width * 0.75) * n_right_spacers;
space_used_by_buttons += layout->titlebar_spacing * scale * MAX (n_right - 1, 0);
@ -457,22 +488,10 @@ meta_frame_layout_calc_geometry (MetaFrameLayout *layout,
}
/* Otherwise we need to shave out a button. Shave
* above, stick, shade, min, max, close, then menu (menu is most useful);
* min, max, close, then menu (menu is most useful);
* prefer the default button locations.
*/
if (strip_button (left_func_rects, &n_left, &fgeom->above_rect))
continue;
else if (strip_button (right_func_rects, &n_right, &fgeom->above_rect))
continue;
else if (strip_button (left_func_rects, &n_left, &fgeom->stick_rect))
continue;
else if (strip_button (right_func_rects, &n_right, &fgeom->stick_rect))
continue;
else if (strip_button (left_func_rects, &n_left, &fgeom->shade_rect))
continue;
else if (strip_button (right_func_rects, &n_right, &fgeom->shade_rect))
continue;
else if (strip_button (left_func_rects, &n_left, &fgeom->min_rect))
if (strip_button (left_func_rects, &n_left, &fgeom->min_rect))
continue;
else if (strip_button (right_func_rects, &n_right, &fgeom->min_rect))
continue;
@ -519,6 +538,8 @@ meta_frame_layout_calc_geometry (MetaFrameLayout *layout,
if (x < 0) /* if we go negative, leave the buttons we don't get to as 0-width */
break;
x -= layout->button_margin.right * scale;
rect = right_func_rects[i];
rect->visible.x = x - button_width;
if (right_buttons_has_spacer[i])
@ -544,7 +565,7 @@ meta_frame_layout_calc_geometry (MetaFrameLayout *layout,
else
g_memmove (&(rect->clickable), &(rect->visible), sizeof(rect->clickable));
x = rect->visible.x;
x = rect->visible.x - layout->button_margin.left * scale;
if (i > 0)
x -= layout->titlebar_spacing;
@ -563,6 +584,8 @@ meta_frame_layout_calc_geometry (MetaFrameLayout *layout,
{
MetaButtonSpace *rect;
x += layout->button_margin.left * scale;
rect = left_func_rects[i];
rect->visible.x = x;
@ -589,7 +612,7 @@ meta_frame_layout_calc_geometry (MetaFrameLayout *layout,
else
g_memmove (&(rect->clickable), &(rect->visible), sizeof(rect->clickable));
x = rect->visible.x + rect->visible.width;
x = rect->visible.x + rect->visible.width + layout->button_margin.right * scale;
if (i < n_left - 1)
x += layout->titlebar_spacing * scale;
if (left_buttons_has_spacer[i])
@ -643,30 +666,6 @@ get_button_rect (MetaButtonType type,
*rect = fgeom->close_rect.visible;
break;
case META_BUTTON_TYPE_SHADE:
*rect = fgeom->shade_rect.visible;
break;
case META_BUTTON_TYPE_UNSHADE:
*rect = fgeom->unshade_rect.visible;
break;
case META_BUTTON_TYPE_ABOVE:
*rect = fgeom->above_rect.visible;
break;
case META_BUTTON_TYPE_UNABOVE:
*rect = fgeom->unabove_rect.visible;
break;
case META_BUTTON_TYPE_STICK:
*rect = fgeom->stick_rect.visible;
break;
case META_BUTTON_TYPE_UNSTICK:
*rect = fgeom->unstick_rect.visible;
break;
case META_BUTTON_TYPE_MAXIMIZE:
*rect = fgeom->max_rect.visible;
break;
@ -890,6 +889,7 @@ meta_frame_layout_draw_with_style (MetaFrameLayout *layout,
cairo_restore (cr);
if (button_class)
gtk_style_context_remove_class (style, button_class);
gtk_style_context_set_state (style, state);
}
}
@ -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:
@ -977,6 +975,7 @@ static GtkStyleContext *
create_style_context (GType widget_type,
GtkStyleContext *parent_style,
GtkCssProvider *provider,
const char *object_name,
const char *first_class,
...)
{
@ -996,6 +995,9 @@ create_style_context (GType widget_type,
gtk_widget_path_append_type (path, widget_type);
if (object_name)
gtk_widget_path_iter_set_object_name (path, -1, object_name);
va_start (ap, first_class);
for (name = first_class; name; name = va_arg (ap, const char *))
gtk_widget_path_iter_add_class (path, -1, name);
@ -1035,6 +1037,7 @@ meta_theme_create_style_info (GdkScreen *screen,
create_style_context (META_TYPE_FRAMES,
NULL,
provider,
"decoration",
GTK_STYLE_CLASS_BACKGROUND,
"window-frame",
"ssd",
@ -1043,28 +1046,30 @@ meta_theme_create_style_info (GdkScreen *screen,
create_style_context (GTK_TYPE_HEADER_BAR,
style_info->styles[META_STYLE_ELEMENT_FRAME],
provider,
"headerbar",
GTK_STYLE_CLASS_TITLEBAR,
GTK_STYLE_CLASS_HORIZONTAL,
"default-decoration",
"header-bar",
NULL);
style_info->styles[META_STYLE_ELEMENT_TITLE] =
create_style_context (GTK_TYPE_LABEL,
style_info->styles[META_STYLE_ELEMENT_TITLEBAR],
provider,
"label",
GTK_STYLE_CLASS_TITLE,
NULL);
style_info->styles[META_STYLE_ELEMENT_BUTTON] =
create_style_context (GTK_TYPE_BUTTON,
style_info->styles[META_STYLE_ELEMENT_TITLEBAR],
provider,
GTK_STYLE_CLASS_BUTTON,
"button",
"titlebutton",
NULL);
style_info->styles[META_STYLE_ELEMENT_IMAGE] =
create_style_context (GTK_TYPE_IMAGE,
style_info->styles[META_STYLE_ELEMENT_BUTTON],
provider,
"image",
NULL);
return style_info;
}
@ -1171,9 +1176,10 @@ meta_style_info_create_font_desc (MetaStyleInfo *style_info)
{
PangoFontDescription *font_desc;
const PangoFontDescription *override = meta_prefs_get_titlebar_font ();
GtkStyleContext *context = style_info->styles[META_STYLE_ELEMENT_TITLE];
gtk_style_context_get (style_info->styles[META_STYLE_ELEMENT_TITLE],
GTK_STATE_FLAG_NORMAL,
gtk_style_context_get (context,
gtk_style_context_get_state (context),
"font", &font_desc, NULL);
if (override)

View File

@ -37,17 +37,30 @@
#include "meta-wayland-private.h"
#include "meta-dnd-actor-private.h"
#define ALL_ACTIONS (WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | \
WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | \
WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
struct _MetaWaylandDataOffer
{
struct wl_resource *resource;
MetaWaylandDataSource *source;
struct wl_listener source_destroy_listener;
uint32_t dnd_actions;
enum wl_data_device_manager_dnd_action preferred_dnd_action;
};
typedef struct _MetaWaylandDataSourcePrivate
{
MetaWaylandDataOffer *offer;
struct wl_array mime_types;
gboolean has_target;
uint32_t dnd_actions;
enum wl_data_device_manager_dnd_action user_dnd_action;
enum wl_data_device_manager_dnd_action current_dnd_action;
MetaWaylandSeat *seat;
guint actions_set : 1;
guint in_ask : 1;
} MetaWaylandDataSourcePrivate;
typedef struct _MetaWaylandDataSourceWayland
@ -57,8 +70,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,
@ -76,6 +87,75 @@ unbind_resource (struct wl_resource *resource)
wl_list_remove (wl_resource_get_link (resource));
}
static gboolean
meta_wayland_source_get_in_ask (MetaWaylandDataSource *source)
{
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
return priv->in_ask;
}
static void
meta_wayland_source_update_in_ask (MetaWaylandDataSource *source)
{
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
priv->in_ask =
priv->current_dnd_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
}
static enum wl_data_device_manager_dnd_action
data_offer_choose_action (MetaWaylandDataOffer *offer)
{
MetaWaylandDataSource *source = offer->source;
uint32_t actions, user_action, available_actions;
actions = meta_wayland_data_source_get_actions (source);
user_action = meta_wayland_data_source_get_user_action (source);
available_actions = actions & offer->dnd_actions;
if (!available_actions)
return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
/* If the user is forcing an action, go for it */
if ((user_action & available_actions) != 0)
return user_action;
/* If the dest side has a preferred DnD action, use it */
if ((offer->preferred_dnd_action & available_actions) != 0)
return offer->preferred_dnd_action;
/* Use the first found action, in bit order */
return 1 << (ffs (available_actions) - 1);
}
static void
data_offer_update_action (MetaWaylandDataOffer *offer)
{
enum wl_data_device_manager_dnd_action current_action, action;
MetaWaylandDataSource *source;
if (!offer->source)
return;
source = offer->source;
current_action = meta_wayland_data_source_get_current_action (source);
action = data_offer_choose_action (offer);
if (current_action == action)
return;
meta_wayland_data_source_set_current_action (source, action);
if (!meta_wayland_source_get_in_ask (source) &&
wl_resource_get_version (offer->resource) >=
WL_DATA_OFFER_ACTION_SINCE_VERSION)
wl_data_offer_send_action (offer->resource, action);
}
static void
meta_wayland_data_source_target (MetaWaylandDataSource *source,
const char *mime_type)
@ -100,6 +180,25 @@ meta_wayland_data_source_has_target (MetaWaylandDataSource *source)
return priv->has_target;
}
static void
meta_wayland_data_source_set_seat (MetaWaylandDataSource *source,
MetaWaylandSeat *seat)
{
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
priv->seat = seat;
}
static MetaWaylandSeat *
meta_wayland_data_source_get_seat (MetaWaylandDataSource *source)
{
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
return priv->seat;
}
void
meta_wayland_data_source_set_has_target (MetaWaylandDataSource *source,
gboolean has_target)
@ -114,7 +213,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;
}
@ -125,6 +224,100 @@ meta_wayland_data_source_cancel (MetaWaylandDataSource *source)
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->cancel (source);
}
uint32_t
meta_wayland_data_source_get_actions (MetaWaylandDataSource *source)
{
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
return priv->dnd_actions;
}
enum wl_data_device_manager_dnd_action
meta_wayland_data_source_get_user_action (MetaWaylandDataSource *source)
{
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
if (!priv->seat)
return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
return priv->user_dnd_action;
}
enum wl_data_device_manager_dnd_action
meta_wayland_data_source_get_current_action (MetaWaylandDataSource *source)
{
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
return priv->current_dnd_action;
}
static void
meta_wayland_data_source_set_current_offer (MetaWaylandDataSource *source,
MetaWaylandDataOffer *offer)
{
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
priv->offer = offer;
}
static MetaWaylandDataOffer *
meta_wayland_data_source_get_current_offer (MetaWaylandDataSource *source)
{
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
return priv->offer;
}
void
meta_wayland_data_source_set_current_action (MetaWaylandDataSource *source,
enum wl_data_device_manager_dnd_action action)
{
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
if (priv->current_dnd_action == action)
return;
priv->current_dnd_action = action;
if (!meta_wayland_source_get_in_ask (source))
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->action (source, action);
}
void
meta_wayland_data_source_set_actions (MetaWaylandDataSource *source,
uint32_t dnd_actions)
{
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
priv->dnd_actions = dnd_actions;
priv->actions_set = TRUE;
}
static void
meta_wayland_data_source_set_user_action (MetaWaylandDataSource *source,
enum wl_data_device_manager_dnd_action action)
{
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
MetaWaylandDataOffer *offer;
if (priv->user_dnd_action == action)
return;
priv->user_dnd_action = action;
offer = meta_wayland_data_source_get_current_offer (source);
if (offer)
data_offer_update_action (offer);
}
static void
data_offer_accept (struct wl_client *client,
struct wl_resource *resource,
@ -163,21 +356,117 @@ data_offer_destroy (struct wl_client *client, struct wl_resource *resource)
wl_resource_destroy (resource);
}
static void
data_offer_finish (struct wl_client *client,
struct wl_resource *resource)
{
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
enum wl_data_device_manager_dnd_action current_action;
if (!offer->source ||
offer != meta_wayland_data_source_get_current_offer (offer->source))
return;
if (meta_wayland_data_source_get_seat (offer->source) ||
!meta_wayland_data_source_has_target (offer->source))
{
wl_resource_post_error (offer->resource,
WL_DATA_OFFER_ERROR_INVALID_FINISH,
"premature finish request");
return;
}
current_action = meta_wayland_data_source_get_current_action (offer->source);
if (current_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE ||
current_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
{
wl_resource_post_error (offer->resource,
WL_DATA_OFFER_ERROR_INVALID_OFFER,
"offer finished with an invalid action");
return;
}
meta_wayland_data_source_notify_finish (offer->source);
}
static void
data_offer_set_actions (struct wl_client *client,
struct wl_resource *resource,
uint32_t dnd_actions,
uint32_t preferred_action)
{
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
if (dnd_actions & ~(ALL_ACTIONS))
{
wl_resource_post_error (offer->resource,
WL_DATA_OFFER_ERROR_INVALID_ACTION_MASK,
"invalid actions mask %x", dnd_actions);
return;
}
if (preferred_action &&
(!(preferred_action & dnd_actions) ||
__builtin_popcount (preferred_action) > 1))
{
wl_resource_post_error (offer->resource,
WL_DATA_OFFER_ERROR_INVALID_ACTION,
"invalid action %x", preferred_action);
return;
}
offer->dnd_actions = dnd_actions;
offer->preferred_dnd_action = preferred_action;
data_offer_update_action (offer);
}
static const struct wl_data_offer_interface data_offer_interface = {
data_offer_accept,
data_offer_receive,
data_offer_destroy,
data_offer_finish,
data_offer_set_actions,
};
static void
meta_wayland_data_source_notify_drop_performed (MetaWaylandDataSource *source)
{
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->drop_performed (source);
}
void
meta_wayland_data_source_notify_finish (MetaWaylandDataSource *source)
{
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->drag_finished (source);
}
static void
destroy_data_offer (struct wl_resource *resource)
{
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
if (offer->source)
g_object_remove_weak_pointer (G_OBJECT (offer->source),
(gpointer *)&offer->source);
{
if (offer == meta_wayland_data_source_get_current_offer (offer->source))
{
if (wl_resource_get_version (offer->resource) <
WL_DATA_OFFER_ACTION_SINCE_VERSION)
meta_wayland_data_source_notify_finish (offer->source);
else
{
meta_wayland_data_source_cancel (offer->source);
meta_wayland_data_source_set_current_offer (offer->source, NULL);
}
}
g_object_remove_weak_pointer (G_OBJECT (offer->source),
(gpointer *)&offer->source);
offer->source = NULL;
}
meta_display_sync_wayland_input_focus (meta_get_display ());
g_slice_free (MetaWaylandDataOffer, offer);
}
@ -205,6 +494,9 @@ meta_wayland_data_source_send_offer (MetaWaylandDataSource *source,
wl_array_for_each (p, &priv->mime_types)
wl_data_offer_send_offer (offer->resource, *p);
data_offer_update_action (offer);
meta_wayland_data_source_set_current_offer (source, offer);
return offer->resource;
}
@ -224,14 +516,56 @@ data_source_destroy (struct wl_client *client, struct wl_resource *resource)
wl_resource_destroy (resource);
}
static void
data_source_set_actions (struct wl_client *client,
struct wl_resource *resource,
uint32_t dnd_actions)
{
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
MetaWaylandDataSourceWayland *source_wayland =
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
if (priv->actions_set)
{
wl_resource_post_error (source_wayland->resource,
WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK,
"cannot set actions more than once");
return;
}
if (dnd_actions & ~(ALL_ACTIONS))
{
wl_resource_post_error (source_wayland->resource,
WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK,
"invalid actions mask %x", dnd_actions);
return;
}
if (meta_wayland_data_source_get_seat (source))
{
wl_resource_post_error (source_wayland->resource,
WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK,
"invalid action change after "
"wl_data_device.start_drag");
return;
}
meta_wayland_data_source_set_actions (source, dnd_actions);
}
static struct wl_data_source_interface data_source_interface = {
data_source_offer,
data_source_destroy
data_source_destroy,
data_source_set_actions
};
struct _MetaWaylandDragGrab {
MetaWaylandPointerGrab generic;
MetaWaylandKeyboardGrab keyboard_grab;
MetaWaylandSeat *seat;
struct wl_client *drag_client;
@ -250,6 +584,7 @@ struct _MetaWaylandDragGrab {
struct wl_listener drag_origin_listener;
int drag_start_x, drag_start_y;
ClutterModifierType buttons;
};
static void
@ -258,6 +593,24 @@ destroy_drag_focus (struct wl_listener *listener, void *data)
MetaWaylandDragGrab *grab = wl_container_of (listener, grab, drag_focus_listener);
grab->drag_focus_data_device = NULL;
grab->drag_focus = NULL;
}
static void
meta_wayland_drag_grab_set_source (MetaWaylandDragGrab *drag_grab,
MetaWaylandDataSource *source)
{
if (drag_grab->drag_data_source)
g_object_weak_unref (G_OBJECT (drag_grab->drag_data_source),
drag_grab_data_source_destroyed,
drag_grab);
drag_grab->drag_data_source = source;
if (source)
g_object_weak_ref (G_OBJECT (source),
drag_grab_data_source_destroyed,
drag_grab);
}
void
@ -277,6 +630,9 @@ meta_wayland_drag_grab_set_focus (MetaWaylandDragGrab *drag_grab,
drag_grab->drag_focus = NULL;
}
if (drag_grab->drag_data_source)
meta_wayland_data_source_set_current_offer (drag_grab->drag_data_source, NULL);
if (!surface)
return;
@ -314,6 +670,22 @@ drag_grab_focus (MetaWaylandPointerGrab *grab,
meta_wayland_drag_grab_set_focus (drag_grab, surface);
}
static void
data_source_update_user_dnd_action (MetaWaylandDataSource *source,
ClutterModifierType modifiers)
{
enum wl_data_device_manager_dnd_action user_dnd_action = 0;
if (modifiers & CLUTTER_SHIFT_MASK)
user_dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
else if (modifiers & CLUTTER_CONTROL_MASK)
user_dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
else if (modifiers & (CLUTTER_MOD1_MASK | CLUTTER_BUTTON2_MASK))
user_dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
meta_wayland_data_source_set_user_action (source, user_dnd_action);
}
static void
drag_grab_motion (MetaWaylandPointerGrab *grab,
const ClutterEvent *event)
@ -345,10 +717,7 @@ data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
wl_list_remove (&drag_grab->drag_icon_listener.link);
}
if (drag_grab->drag_data_source)
g_object_weak_unref (G_OBJECT (drag_grab->drag_data_source),
drag_grab_data_source_destroyed,
drag_grab);
meta_wayland_drag_grab_set_source (drag_grab, NULL);
if (drag_grab->feedback_actor)
{
@ -358,7 +727,15 @@ data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
drag_grab->seat->data_device.current_grab = NULL;
meta_wayland_pointer_end_grab (drag_grab->generic.pointer);
/* There might be other grabs created in result to DnD actions like popups
* on "ask" actions, we must not reset those, only our own.
*/
if (drag_grab->generic.pointer->grab == (MetaWaylandPointerGrab *) drag_grab)
{
meta_wayland_pointer_end_grab (drag_grab->generic.pointer);
meta_wayland_keyboard_end_grab (drag_grab->keyboard_grab.keyboard);
}
g_slice_free (MetaWaylandDragGrab, drag_grab);
}
@ -373,17 +750,33 @@ drag_grab_button (MetaWaylandPointerGrab *grab,
if (drag_grab->generic.pointer->grab_button == clutter_event_get_button (event) &&
event_type == CLUTTER_BUTTON_RELEASE)
{
gboolean success = FALSE;
MetaWaylandDataSource *source = drag_grab->drag_data_source;
gboolean success;
if (meta_wayland_data_source_has_target (drag_grab->drag_data_source))
if (drag_grab->drag_focus && source &&
meta_wayland_data_source_has_target (source) &&
meta_wayland_data_source_get_current_action (source))
{
/* Detach the data source from the grab, it's meant to live longer */
meta_wayland_drag_grab_set_source (drag_grab, NULL);
meta_wayland_data_source_set_seat (source, NULL);
meta_wayland_surface_drag_dest_drop (drag_grab->drag_focus);
meta_wayland_data_source_notify_drop_performed (source);
meta_wayland_source_update_in_ask (source);
success = TRUE;
}
else
{
meta_wayland_data_source_cancel (source);
meta_wayland_data_source_set_current_offer (source, NULL);
meta_wayland_data_device_set_dnd_source (&seat->data_device, NULL);
success= FALSE;
}
/* Finish drag and let actor self-destruct */
meta_dnd_actor_drag_finish (META_DND_ACTOR (drag_grab->feedback_actor),
success);
meta_dnd_actor_drag_finish (META_DND_ACTOR (drag_grab->feedback_actor), success);
drag_grab->feedback_actor = NULL;
}
@ -398,6 +791,40 @@ static const MetaWaylandPointerGrabInterface drag_grab_interface = {
drag_grab_button,
};
static gboolean
keyboard_drag_grab_key (MetaWaylandKeyboardGrab *grab,
const ClutterEvent *event)
{
return FALSE;
}
static void
keyboard_drag_grab_modifiers (MetaWaylandKeyboardGrab *grab,
ClutterModifierType modifiers)
{
MetaWaylandDragGrab *drag_grab;
drag_grab = wl_container_of (grab, drag_grab, keyboard_grab);
/* The modifiers here just contain keyboard modifiers, mix it with the
* mouse button modifiers we got when starting the drag operation.
*/
modifiers |= drag_grab->buttons;
if (drag_grab->drag_data_source)
{
data_source_update_user_dnd_action (drag_grab->drag_data_source, modifiers);
if (drag_grab->drag_focus)
meta_wayland_surface_drag_dest_update (drag_grab->drag_focus);
}
}
static const MetaWaylandKeyboardGrabInterface keyboard_drag_grab_interface = {
keyboard_drag_grab_key,
keyboard_drag_grab_modifiers
};
static void
destroy_data_device_origin (struct wl_listener *listener, void *data)
{
@ -405,8 +832,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 +842,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
@ -442,12 +869,16 @@ meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
MetaWaylandDragGrab *drag_grab;
ClutterPoint pos, stage_pos;
ClutterModifierType modifiers;
data_device->current_grab = drag_grab = g_slice_new0 (MetaWaylandDragGrab);
drag_grab->generic.interface = funcs;
drag_grab->generic.pointer = &seat->pointer;
drag_grab->keyboard_grab.interface = &keyboard_drag_grab_interface;
drag_grab->keyboard_grab.keyboard = &seat->keyboard;
drag_grab->drag_client = client;
drag_grab->seat = seat;
@ -462,13 +893,15 @@ meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data
drag_grab->drag_start_x = stage_pos.x;
drag_grab->drag_start_y = stage_pos.y;
g_object_weak_ref (G_OBJECT (source),
drag_grab_data_source_destroyed,
drag_grab);
modifiers = clutter_input_device_get_modifier_state (seat->pointer.device);
drag_grab->buttons = modifiers &
(CLUTTER_BUTTON1_MASK | CLUTTER_BUTTON2_MASK | CLUTTER_BUTTON3_MASK |
CLUTTER_BUTTON4_MASK | CLUTTER_BUTTON5_MASK);
drag_grab->drag_data_source = source;
meta_wayland_drag_grab_set_source (drag_grab, source);
meta_wayland_data_device_set_dnd_source (data_device,
drag_grab->drag_data_source);
data_source_update_user_dnd_action (source, modifiers);
if (icon_surface)
{
@ -482,8 +915,7 @@ meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data
drag_grab->drag_start_x,
drag_grab->drag_start_y);
meta_feedback_actor_set_anchor (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
-drag_grab->drag_surface->offset_x,
-drag_grab->drag_surface->offset_y);
0, 0);
clutter_actor_add_child (drag_grab->feedback_actor,
CLUTTER_ACTOR (drag_grab->drag_surface->surface_actor));
@ -492,6 +924,7 @@ meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data
}
meta_wayland_pointer_start_grab (&seat->pointer, (MetaWaylandPointerGrab*) drag_grab);
meta_wayland_data_source_set_seat (source, seat);
}
void
@ -550,6 +983,10 @@ data_device_start_drag (struct wl_client *client,
meta_wayland_data_device_start_drag (data_device, client,
&drag_grab_interface,
surface, drag_source, icon_surface);
meta_wayland_keyboard_set_focus (&seat->keyboard, NULL);
meta_wayland_keyboard_start_grab (&seat->keyboard,
&seat->data_device.current_grab->keyboard_grab);
}
static void
@ -602,6 +1039,47 @@ meta_wayland_source_cancel (MetaWaylandDataSource *source)
wl_data_source_send_cancelled (source_wayland->resource);
}
static void
meta_wayland_source_action (MetaWaylandDataSource *source,
enum wl_data_device_manager_dnd_action action)
{
MetaWaylandDataSourceWayland *source_wayland =
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
if (wl_resource_get_version (source_wayland->resource) >=
WL_DATA_SOURCE_ACTION_SINCE_VERSION)
wl_data_source_send_action (source_wayland->resource, action);
}
static void
meta_wayland_source_drop_performed (MetaWaylandDataSource *source)
{
MetaWaylandDataSourceWayland *source_wayland =
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
if (wl_resource_get_version (source_wayland->resource) >=
WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION)
wl_data_source_send_dnd_drop_performed (source_wayland->resource);
}
static void
meta_wayland_source_drag_finished (MetaWaylandDataSource *source)
{
MetaWaylandDataSourceWayland *source_wayland =
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
enum wl_data_device_manager_dnd_action action;
if (meta_wayland_source_get_in_ask (source))
{
action = meta_wayland_data_source_get_current_action (source);
meta_wayland_source_action (source, action);
}
if (wl_resource_get_version (source_wayland->resource) >=
WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION)
wl_data_source_send_dnd_finished (source_wayland->resource);
}
static void
meta_wayland_source_finalize (GObject *object)
{
@ -625,6 +1103,9 @@ meta_wayland_data_source_wayland_class_init (MetaWaylandDataSourceWaylandClass *
data_source_class->send = meta_wayland_source_send;
data_source_class->target = meta_wayland_source_target;
data_source_class->cancel = meta_wayland_source_cancel;
data_source_class->action = meta_wayland_source_action;
data_source_class->drop_performed = meta_wayland_source_drop_performed;
data_source_class->drag_finished = meta_wayland_source_drag_finished;
}
static void
@ -649,6 +1130,7 @@ meta_wayland_data_source_init (MetaWaylandDataSource *source)
meta_wayland_data_source_get_instance_private (source);
wl_array_init (&priv->mime_types);
priv->current_dnd_action = -1;
}
static void
@ -667,6 +1149,7 @@ meta_wayland_drag_dest_focus_in (MetaWaylandDataDevice *data_device,
MetaWaylandDragGrab *grab = data_device->current_grab;
struct wl_display *display;
struct wl_client *client;
uint32_t source_actions;
wl_fixed_t sx, sy;
if (!grab->drag_focus_data_device)
@ -679,6 +1162,13 @@ meta_wayland_drag_dest_focus_in (MetaWaylandDataDevice *data_device,
wl_resource_add_destroy_listener (grab->drag_focus_data_device,
&grab->drag_focus_listener);
if (wl_resource_get_version (offer->resource) >=
WL_DATA_OFFER_SOURCE_ACTIONS_SINCE_VERSION)
{
source_actions = meta_wayland_data_source_get_actions (offer->source);
wl_data_offer_send_source_actions (offer->resource, source_actions);
}
meta_wayland_pointer_get_relative_coordinates (grab->generic.pointer,
surface, &sx, &sy);
wl_data_device_send_enter (grab->drag_focus_data_device,
@ -724,11 +1214,18 @@ meta_wayland_drag_dest_drop (MetaWaylandDataDevice *data_device,
wl_data_device_send_drop (grab->drag_focus_data_device);
}
static void
meta_wayland_drag_dest_update (MetaWaylandDataDevice *data_device,
MetaWaylandSurface *surface)
{
}
static const MetaWaylandDragDestFuncs meta_wayland_drag_dest_funcs = {
meta_wayland_drag_dest_focus_in,
meta_wayland_drag_dest_focus_out,
meta_wayland_drag_dest_motion,
meta_wayland_drag_dest_drop
meta_wayland_drag_dest_drop,
meta_wayland_drag_dest_update
};
const MetaWaylandDragDestFuncs *
@ -745,12 +1242,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);
}
@ -815,6 +1314,7 @@ data_device_set_selection (struct wl_client *client,
guint32 serial)
{
MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource);
MetaWaylandDataSourcePrivate *priv;
MetaWaylandDataSource *source;
if (source_resource)
@ -822,6 +1322,19 @@ data_device_set_selection (struct wl_client *client,
else
source = NULL;
if (source)
{
priv = meta_wayland_data_source_get_instance_private (source);
if (priv->actions_set)
{
wl_resource_post_error(source_resource,
WL_DATA_SOURCE_ERROR_INVALID_SOURCE,
"cannot set drag-and-drop source as selection");
return;
}
}
/* FIXME: Store serial and check against incoming serial here. */
meta_wayland_data_device_set_selection (data_device, source, serial);
}
@ -912,6 +1425,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;
@ -937,30 +1456,12 @@ meta_wayland_data_device_is_dnd_surface (MetaWaylandDataDevice *data_device,
data_device->current_grab->drag_surface == surface;
}
void
meta_wayland_data_device_update_dnd_surface (MetaWaylandDataDevice *data_device)
{
MetaWaylandDragGrab *drag_grab;
if (!data_device->current_grab)
return;
drag_grab = data_device->current_grab;
if (!drag_grab->feedback_actor || !drag_grab->drag_surface)
return;
meta_feedback_actor_set_anchor (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
-drag_grab->drag_surface->offset_x,
-drag_grab->drag_surface->offset_y);
}
gboolean
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

@ -45,6 +45,11 @@ struct _MetaWaylandDataSourceClass
void (* target) (MetaWaylandDataSource *source,
const gchar *mime_type);
void (* cancel) (MetaWaylandDataSource *source);
void (* action) (MetaWaylandDataSource *source,
uint32_t action);
void (* drop_performed) (MetaWaylandDataSource *source);
void (* drag_finished) (MetaWaylandDataSource *source);
};
struct _MetaWaylandDataDevice
@ -55,13 +60,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);
@ -70,7 +74,6 @@ void meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_de
gboolean meta_wayland_data_device_is_dnd_surface (MetaWaylandDataDevice *data_device,
MetaWaylandSurface *surface);
void meta_wayland_data_device_update_dnd_surface (MetaWaylandDataDevice *data_device);
void meta_wayland_data_device_set_dnd_source (MetaWaylandDataDevice *data_device,
MetaWaylandDataSource *source);
@ -96,6 +99,17 @@ void meta_wayland_data_source_send (MetaWaylandDataSource *source,
const gchar *mime_type,
gint fd);
void meta_wayland_data_source_notify_finish (MetaWaylandDataSource *source);
uint32_t meta_wayland_data_source_get_actions (MetaWaylandDataSource *source);
uint32_t meta_wayland_data_source_get_user_action (MetaWaylandDataSource *source);
uint32_t meta_wayland_data_source_get_current_action (MetaWaylandDataSource *source);
void meta_wayland_data_source_set_actions (MetaWaylandDataSource *source,
uint32_t dnd_actions);
void meta_wayland_data_source_set_current_action (MetaWaylandDataSource *source,
uint32_t action);
const MetaWaylandDragDestFuncs *
meta_wayland_data_device_get_drag_dest_funcs (void);

View File

@ -56,13 +56,19 @@
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <clutter/evdev/clutter-evdev.h>
#include "backends/meta-backend-private.h"
#include "meta-wayland-private.h"
#ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-backend-native.h"
#endif
static void meta_wayland_keyboard_update_xkb_state (MetaWaylandKeyboard *keyboard);
static void notify_modifiers (MetaWaylandKeyboard *keyboard);
static guint evdev_code (const ClutterKeyEvent *event);
static void
unbind_resource (struct wl_resource *resource)
@ -240,8 +246,10 @@ keyboard_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
}
static gboolean
notify_key (MetaWaylandKeyboard *keyboard,
uint32_t time, uint32_t key, uint32_t state)
meta_wayland_keyboard_broadcast_key (MetaWaylandKeyboard *keyboard,
uint32_t time,
uint32_t key,
uint32_t state)
{
struct wl_resource *resource;
struct wl_list *l;
@ -251,11 +259,12 @@ notify_key (MetaWaylandKeyboard *keyboard,
{
struct wl_client *client = wl_resource_get_client (keyboard->focus_surface->resource);
struct wl_display *display = wl_client_get_display (client);
uint32_t serial = wl_display_next_serial (display);
keyboard->key_serial = wl_display_next_serial (display);
wl_resource_for_each (resource, l)
{
wl_keyboard_send_key (resource, serial, time, key, state);
wl_keyboard_send_key (resource, keyboard->key_serial, time, key, state);
}
}
@ -263,8 +272,15 @@ notify_key (MetaWaylandKeyboard *keyboard,
return (keyboard->focus_surface != NULL);
}
static gboolean
notify_key (MetaWaylandKeyboard *keyboard,
const ClutterEvent *event)
{
return keyboard->grab->interface->key (keyboard->grab, event);
}
static void
notify_modifiers (MetaWaylandKeyboard *keyboard)
meta_wayland_keyboard_broadcast_modifiers (MetaWaylandKeyboard *keyboard)
{
struct xkb_state *state;
struct wl_resource *resource;
@ -289,6 +305,16 @@ notify_modifiers (MetaWaylandKeyboard *keyboard)
}
}
static void
notify_modifiers (MetaWaylandKeyboard *keyboard)
{
struct xkb_state *state;
state = keyboard->xkb_info.state;
keyboard->grab->interface->modifiers (keyboard->grab,
xkb_state_serialize_mods (state, XKB_STATE_MODS_EFFECTIVE));
}
static void
meta_wayland_keyboard_update_xkb_state (MetaWaylandKeyboard *keyboard)
{
@ -368,6 +394,45 @@ settings_changed (GSettings *settings,
notify_key_repeat (keyboard);
}
static gboolean
default_grab_key (MetaWaylandKeyboardGrab *grab,
const ClutterEvent *event)
{
MetaWaylandKeyboard *keyboard = grab->keyboard;
gboolean is_press = event->type == CLUTTER_KEY_PRESS;
guint32 code;
#ifdef HAVE_NATIVE_BACKEND
MetaBackend *backend = meta_get_backend ();
#endif
/* Synthetic key events are for autorepeat. Ignore those, as
* autorepeat in Wayland is done on the client side. */
if (event->key.flags & CLUTTER_EVENT_FLAG_SYNTHETIC)
return FALSE;
#ifdef HAVE_NATIVE_BACKEND
if (META_IS_BACKEND_NATIVE (backend))
code = clutter_evdev_event_get_event_code (event);
else
#endif
code = evdev_code (&event->key);
return meta_wayland_keyboard_broadcast_key (keyboard, event->key.time,
code, is_press);
}
static void
default_grab_modifiers (MetaWaylandKeyboardGrab *grab,
ClutterModifierType modifiers)
{
meta_wayland_keyboard_broadcast_modifiers (grab->keyboard);
}
static const MetaWaylandKeyboardGrabInterface default_keyboard_grab_interface = {
default_grab_key,
default_grab_modifiers
};
void
meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
struct wl_display *display)
@ -385,6 +450,10 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
keyboard->xkb_info.keymap_fd = -1;
keyboard->default_grab.interface = &default_keyboard_grab_interface;
keyboard->default_grab.keyboard = keyboard;
keyboard->grab = &keyboard->default_grab;
keyboard->settings = g_settings_new ("org.gnome.desktop.peripherals.keyboard");
g_signal_connect (keyboard->settings, "changed",
G_CALLBACK (settings_changed), keyboard);
@ -461,7 +530,7 @@ meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
is_press ? "press" : "release",
event->hardware_keycode);
handled = notify_key (keyboard, event->time, evdev_code (event), is_press);
handled = notify_key (keyboard, (const ClutterEvent *) event);
if (handled)
meta_verbose ("Sent event to wayland client\n");
@ -672,3 +741,25 @@ meta_wayland_keyboard_create_new_resource (MetaWaylandKeyboard *keyboard,
wl_list_insert (&keyboard->resource_list, wl_resource_get_link (cr));
}
}
gboolean
meta_wayland_keyboard_can_popup (MetaWaylandKeyboard *keyboard,
uint32_t serial)
{
return keyboard->key_serial == serial;
}
void
meta_wayland_keyboard_start_grab (MetaWaylandKeyboard *keyboard,
MetaWaylandKeyboardGrab *grab)
{
meta_wayland_keyboard_set_focus (keyboard, NULL);
keyboard->grab = grab;
grab->keyboard = keyboard;
}
void
meta_wayland_keyboard_end_grab (MetaWaylandKeyboard *keyboard)
{
keyboard->grab = &keyboard->default_grab;
}

View File

@ -49,6 +49,20 @@
#include <wayland-server.h>
#include <xkbcommon/xkbcommon.h>
struct _MetaWaylandKeyboardGrabInterface
{
gboolean (*key) (MetaWaylandKeyboardGrab *grab,
const ClutterEvent *event);
void (*modifiers) (MetaWaylandKeyboardGrab *grab,
ClutterModifierType modifiers);
};
struct _MetaWaylandKeyboardGrab
{
const MetaWaylandKeyboardGrabInterface *interface;
MetaWaylandKeyboard *keyboard;
};
typedef struct
{
struct xkb_keymap *keymap;
@ -68,10 +82,14 @@ struct _MetaWaylandKeyboard
MetaWaylandSurface *focus_surface;
struct wl_listener focus_surface_listener;
uint32_t focus_serial;
uint32_t key_serial;
MetaWaylandXkbInfo xkb_info;
enum xkb_state_component mods_changed;
MetaWaylandKeyboardGrab *grab;
MetaWaylandKeyboardGrab default_grab;
GSettings *settings;
};
@ -100,4 +118,11 @@ void meta_wayland_keyboard_create_new_resource (MetaWaylandKeyboard *keyboard,
struct wl_resource *seat_resource,
uint32_t id);
gboolean meta_wayland_keyboard_can_popup (MetaWaylandKeyboard *keyboard,
uint32_t serial);
void meta_wayland_keyboard_start_grab (MetaWaylandKeyboard *keyboard,
MetaWaylandKeyboardGrab *grab);
void meta_wayland_keyboard_end_grab (MetaWaylandKeyboard *keyboard);
#endif /* META_WAYLAND_KEYBOARD_H */

View File

@ -99,7 +99,7 @@ bind_output (struct wl_client *client,
mode_flags,
(int)monitor_info->rect.width,
(int)monitor_info->rect.height,
(int)monitor_info->refresh_rate);
(int)(monitor_info->refresh_rate * 1000));
if (version >= WL_OUTPUT_SCALE_SINCE_VERSION)
wl_output_send_scale (resource, output->scale);
@ -160,7 +160,7 @@ wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
mode_flags,
(int)monitor_info->rect.width,
(int)monitor_info->rect.height,
(int)monitor_info->refresh_rate);
(int)(monitor_info->refresh_rate * 1000));
}
/* It's very important that we change the output pointer here, as

View File

@ -30,7 +30,7 @@
#include "meta-wayland-pointer-gesture-pinch.h"
#include "meta-wayland-pointer.h"
#include "meta-wayland-surface.h"
#include "pointer-gestures-server-protocol.h"
#include "pointer-gestures-unstable-v1-server-protocol.h"
static void
handle_pinch_begin (MetaWaylandPointer *pointer,
@ -45,10 +45,10 @@ handle_pinch_begin (MetaWaylandPointer *pointer,
wl_resource_for_each (resource, &pointer_client->pinch_gesture_resources)
{
_wl_pointer_gesture_pinch_send_begin (resource, serial,
clutter_event_get_time (event),
pointer->focus_surface->resource,
2);
zwp_pointer_gesture_pinch_v1_send_begin (resource, serial,
clutter_event_get_time (event),
pointer->focus_surface->resource,
2);
}
}
@ -67,12 +67,12 @@ handle_pinch_update (MetaWaylandPointer *pointer,
wl_resource_for_each (resource, &pointer_client->pinch_gesture_resources)
{
_wl_pointer_gesture_pinch_send_update (resource,
clutter_event_get_time (event),
wl_fixed_from_double (dx),
wl_fixed_from_double (dy),
wl_fixed_from_double (scale),
wl_fixed_from_double (rotation));
zwp_pointer_gesture_pinch_v1_send_update (resource,
clutter_event_get_time (event),
wl_fixed_from_double (dx),
wl_fixed_from_double (dy),
wl_fixed_from_double (scale),
wl_fixed_from_double (rotation));
}
}
@ -93,9 +93,9 @@ handle_pinch_end (MetaWaylandPointer *pointer,
wl_resource_for_each (resource, &pointer_client->pinch_gesture_resources)
{
_wl_pointer_gesture_pinch_send_end (resource, serial,
clutter_event_get_time (event),
cancelled);
zwp_pointer_gesture_pinch_v1_send_end (resource, serial,
clutter_event_get_time (event),
cancelled);
}
}
@ -135,7 +135,7 @@ pointer_gesture_pinch_destroy (struct wl_client *client,
wl_resource_destroy (resource);
}
static const struct _wl_pointer_gesture_pinch_interface pointer_gesture_pinch_interface = {
static const struct zwp_pointer_gesture_pinch_v1_interface pointer_gesture_pinch_interface = {
pointer_gesture_pinch_destroy
};
@ -151,7 +151,7 @@ meta_wayland_pointer_gesture_pinch_create_new_resource (MetaWaylandPointer *poin
pointer_client = meta_wayland_pointer_get_pointer_client (pointer, client);
g_return_if_fail (pointer_client != NULL);
res = wl_resource_create (client, &_wl_pointer_gesture_pinch_interface,
res = wl_resource_create (client, &zwp_pointer_gesture_pinch_v1_interface,
wl_resource_get_version (gestures_resource), id);
wl_resource_set_implementation (res, &pointer_gesture_pinch_interface, pointer,
meta_wayland_pointer_unbind_pointer_client_resource);

View File

@ -30,7 +30,7 @@
#include "meta-wayland-pointer-gesture-swipe.h"
#include "meta-wayland-pointer.h"
#include "meta-wayland-surface.h"
#include "pointer-gestures-server-protocol.h"
#include "pointer-gestures-unstable-v1-server-protocol.h"
static void
handle_swipe_begin (MetaWaylandPointer *pointer,
@ -46,10 +46,10 @@ handle_swipe_begin (MetaWaylandPointer *pointer,
wl_resource_for_each (resource, &pointer_client->swipe_gesture_resources)
{
_wl_pointer_gesture_swipe_send_begin (resource, serial,
clutter_event_get_time (event),
pointer->focus_surface->resource,
fingers);
zwp_pointer_gesture_swipe_v1_send_begin (resource, serial,
clutter_event_get_time (event),
pointer->focus_surface->resource,
fingers);
}
}
@ -66,10 +66,10 @@ handle_swipe_update (MetaWaylandPointer *pointer,
wl_resource_for_each (resource, &pointer_client->swipe_gesture_resources)
{
_wl_pointer_gesture_swipe_send_update (resource,
clutter_event_get_time (event),
wl_fixed_from_double (dx),
wl_fixed_from_double (dy));
zwp_pointer_gesture_swipe_v1_send_update (resource,
clutter_event_get_time (event),
wl_fixed_from_double (dx),
wl_fixed_from_double (dy));
}
}
@ -90,9 +90,9 @@ handle_swipe_end (MetaWaylandPointer *pointer,
wl_resource_for_each (resource, &pointer_client->swipe_gesture_resources)
{
_wl_pointer_gesture_swipe_send_end (resource, serial,
clutter_event_get_time (event),
cancelled);
zwp_pointer_gesture_swipe_v1_send_end (resource, serial,
clutter_event_get_time (event),
cancelled);
}
}
@ -131,7 +131,7 @@ pointer_gesture_swipe_release (struct wl_client *client,
wl_resource_destroy (resource);
}
static const struct _wl_pointer_gesture_swipe_interface pointer_gesture_swipe_interface = {
static const struct zwp_pointer_gesture_swipe_v1_interface pointer_gesture_swipe_interface = {
pointer_gesture_swipe_release
};
@ -147,7 +147,7 @@ meta_wayland_pointer_gesture_swipe_create_new_resource (MetaWaylandPointer *poin
pointer_client = meta_wayland_pointer_get_pointer_client (pointer, client);
g_return_if_fail (pointer_client != NULL);
res = wl_resource_create (client, &_wl_pointer_gesture_swipe_interface,
res = wl_resource_create (client, &zwp_pointer_gesture_swipe_v1_interface,
wl_resource_get_version (pointer_resource), id);
wl_resource_set_implementation (res, &pointer_gesture_swipe_interface, pointer,
meta_wayland_pointer_unbind_pointer_client_resource);

View File

@ -27,7 +27,7 @@
#include <glib.h>
#include "meta-wayland-pointer-gestures.h"
#include "pointer-gestures-server-protocol.h"
#include "pointer-gestures-unstable-v1-server-protocol.h"
#include "meta-wayland-versions.h"
#include "meta-wayland-private.h"
@ -53,7 +53,7 @@ gestures_get_pinch (struct wl_client *client,
meta_wayland_pointer_gesture_pinch_create_new_resource (pointer, client, resource, id);
}
static const struct _wl_pointer_gestures_interface pointer_gestures_interface = {
static const struct zwp_pointer_gestures_v1_interface pointer_gestures_interface = {
gestures_get_swipe,
gestures_get_pinch
};
@ -66,16 +66,8 @@ 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;
}
resource = wl_resource_create (client, &zwp_pointer_gestures_v1_interface,
version, id);
wl_resource_set_implementation (resource, &pointer_gestures_interface,
NULL, NULL);
}
@ -84,7 +76,7 @@ void
meta_wayland_pointer_gestures_init (MetaWaylandCompositor *compositor)
{
wl_global_create (compositor->wayland_display,
&_wl_pointer_gestures_interface,
META__WL_POINTER_GESTURES_VERSION,
&zwp_pointer_gestures_v1_interface,
META_ZWP_POINTER_GESTURES_V1_VERSION,
NULL, bind_pointer_gestures);
}

View File

@ -44,6 +44,7 @@
#include "config.h"
#include <clutter/clutter.h>
#include <clutter/evdev/clutter-evdev.h>
#include <cogl/cogl.h>
#include <cogl/cogl-wayland-server.h>
#include <linux/input.h>
@ -53,6 +54,7 @@
#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"
@ -61,6 +63,10 @@
#include "backends/meta-cursor-tracker-private.h"
#include "backends/meta-cursor-renderer.h"
#ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-backend-native.h"
#endif
#include <string.h>
#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int (10)
@ -74,7 +80,6 @@ struct _MetaWaylandSurfaceRoleCursor
MetaCursorSprite *cursor_sprite;
};
GType meta_wayland_surface_role_cursor_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE (MetaWaylandSurfaceRoleCursor,
meta_wayland_surface_role_cursor,
META_TYPE_WAYLAND_SURFACE_ROLE);
@ -237,6 +242,28 @@ pointer_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
meta_wayland_pointer_set_focus (pointer, NULL);
}
static void
meta_wayland_pointer_send_frame (MetaWaylandPointer *pointer,
struct wl_resource *resource)
{
if (wl_resource_get_version (resource) >= WL_POINTER_AXIS_SOURCE_SINCE_VERSION)
wl_pointer_send_frame (resource);
}
static void
meta_wayland_pointer_broadcast_frame (MetaWaylandPointer *pointer)
{
struct wl_resource *resource;
if (!pointer->focus_client)
return;
wl_resource_for_each (resource, &pointer->focus_client->pointer_resources)
{
meta_wayland_pointer_send_frame (pointer, resource);
}
}
void
meta_wayland_pointer_send_motion (MetaWaylandPointer *pointer,
const ClutterEvent *event)
@ -257,6 +284,8 @@ meta_wayland_pointer_send_motion (MetaWaylandPointer *pointer,
{
wl_pointer_send_motion (resource, time, sx, sy);
}
meta_wayland_pointer_broadcast_frame (pointer);
}
void
@ -277,26 +306,37 @@ meta_wayland_pointer_send_button (MetaWaylandPointer *pointer,
uint32_t button;
uint32_t serial;
#ifdef HAVE_NATIVE_BACKEND
MetaBackend *backend = meta_get_backend ();
if (META_IS_BACKEND_NATIVE (backend))
button = clutter_evdev_event_get_event_code (event);
else
#endif
{
button = clutter_event_get_button (event);
switch (button)
{
case 1:
button = BTN_LEFT;
break;
/* The evdev input right and middle button numbers are swapped
relative to how Clutter numbers them */
case 2:
button = BTN_MIDDLE;
break;
case 3:
button = BTN_RIGHT;
break;
default:
button = button + (BTN_LEFT - 1) + 4;
break;
}
}
time = clutter_event_get_time (event);
button = clutter_event_get_button (event);
switch (button)
{
/* The evdev input right and middle button numbers are swapped
relative to how Clutter numbers them */
case 2:
button = BTN_MIDDLE;
break;
case 3:
button = BTN_RIGHT;
break;
default:
button = button + BTN_LEFT - 1;
break;
}
serial = wl_display_next_serial (display);
wl_resource_for_each (resource, &pointer->focus_client->pointer_resources)
@ -305,6 +345,8 @@ meta_wayland_pointer_send_button (MetaWaylandPointer *pointer,
time, button,
event_type == CLUTTER_BUTTON_PRESS ? 1 : 0);
}
meta_wayland_pointer_broadcast_frame (pointer);
}
if (pointer->button_count == 0 && event_type == CLUTTER_BUTTON_RELEASE)
@ -494,26 +536,48 @@ handle_scroll_event (MetaWaylandPointer *pointer,
{
struct wl_resource *resource;
wl_fixed_t x_value = 0, y_value = 0;
int x_discrete = 0, y_discrete = 0;
enum wl_pointer_axis_source source = -1;
if (clutter_event_is_pointer_emulated (event))
return;
switch (event->scroll.scroll_source)
{
case CLUTTER_SCROLL_SOURCE_WHEEL:
source = WL_POINTER_AXIS_SOURCE_WHEEL;
break;
case CLUTTER_SCROLL_SOURCE_FINGER:
source = WL_POINTER_AXIS_SOURCE_FINGER;
break;
case CLUTTER_SCROLL_SOURCE_CONTINUOUS:
source = WL_POINTER_AXIS_SOURCE_CONTINUOUS;
break;
default:
source = WL_POINTER_AXIS_SOURCE_WHEEL;
break;
}
switch (clutter_event_get_scroll_direction (event))
{
case CLUTTER_SCROLL_UP:
y_value = -DEFAULT_AXIS_STEP_DISTANCE;
y_discrete = -1;
break;
case CLUTTER_SCROLL_DOWN:
y_value = DEFAULT_AXIS_STEP_DISTANCE;
y_discrete = 1;
break;
case CLUTTER_SCROLL_LEFT:
x_value = -DEFAULT_AXIS_STEP_DISTANCE;
x_discrete = -1;
break;
case CLUTTER_SCROLL_RIGHT:
x_value = DEFAULT_AXIS_STEP_DISTANCE;
x_discrete = 1;
break;
case CLUTTER_SCROLL_SMOOTH:
@ -537,13 +601,44 @@ handle_scroll_event (MetaWaylandPointer *pointer,
{
wl_resource_for_each (resource, &pointer->focus_client->pointer_resources)
{
if (wl_resource_get_version (resource) >= WL_POINTER_AXIS_SOURCE_SINCE_VERSION)
wl_pointer_send_axis_source (resource, source);
/* X axis */
if (x_discrete != 0 &&
wl_resource_get_version (resource) >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION)
wl_pointer_send_axis_discrete (resource,
WL_POINTER_AXIS_HORIZONTAL_SCROLL,
x_discrete);
if (x_value)
wl_pointer_send_axis (resource, clutter_event_get_time (event),
WL_POINTER_AXIS_HORIZONTAL_SCROLL, x_value);
if ((event->scroll.finish_flags & CLUTTER_SCROLL_FINISHED_HORIZONTAL) &&
wl_resource_get_version (resource) >= WL_POINTER_AXIS_STOP_SINCE_VERSION)
wl_pointer_send_axis_stop (resource,
clutter_event_get_time (event),
WL_POINTER_AXIS_HORIZONTAL_SCROLL);
/* Y axis */
if (y_discrete != 0 &&
wl_resource_get_version (resource) >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION)
wl_pointer_send_axis_discrete (resource,
WL_POINTER_AXIS_VERTICAL_SCROLL,
y_discrete);
if (y_value)
wl_pointer_send_axis (resource, clutter_event_get_time (event),
WL_POINTER_AXIS_VERTICAL_SCROLL, y_value);
if ((event->scroll.finish_flags & CLUTTER_SCROLL_FINISHED_VERTICAL) &&
wl_resource_get_version (resource) >= WL_POINTER_AXIS_STOP_SINCE_VERSION)
wl_pointer_send_axis_stop (resource,
clutter_event_get_time (event),
WL_POINTER_AXIS_VERTICAL_SCROLL);
}
meta_wayland_pointer_broadcast_frame (pointer);
}
}
@ -582,13 +677,57 @@ meta_wayland_pointer_handle_event (MetaWaylandPointer *pointer,
}
static void
broadcast_focus (MetaWaylandPointer *pointer,
struct wl_resource *resource)
meta_wayland_pointer_send_enter (MetaWaylandPointer *pointer,
struct wl_resource *pointer_resource,
uint32_t serial,
MetaWaylandSurface *surface)
{
wl_fixed_t sx, sy;
meta_wayland_pointer_get_relative_coordinates (pointer, pointer->focus_surface, &sx, &sy);
wl_pointer_send_enter (resource, pointer->focus_serial, pointer->focus_surface->resource, sx, sy);
meta_wayland_pointer_get_relative_coordinates (pointer, surface, &sx, &sy);
wl_pointer_send_enter (pointer_resource,
serial,
surface->resource,
sx, sy);
}
static void
meta_wayland_pointer_send_leave (MetaWaylandPointer *pointer,
struct wl_resource *pointer_resource,
uint32_t serial,
MetaWaylandSurface *surface)
{
wl_pointer_send_leave (pointer_resource, serial, surface->resource);
}
static void
meta_wayland_pointer_broadcast_enter (MetaWaylandPointer *pointer,
uint32_t serial,
MetaWaylandSurface *surface)
{
struct wl_resource *pointer_resource;
wl_resource_for_each (pointer_resource,
&pointer->focus_client->pointer_resources)
meta_wayland_pointer_send_enter (pointer, pointer_resource,
serial, surface);
meta_wayland_pointer_broadcast_frame (pointer);
}
static void
meta_wayland_pointer_broadcast_leave (MetaWaylandPointer *pointer,
uint32_t serial,
MetaWaylandSurface *surface)
{
struct wl_resource *pointer_resource;
wl_resource_for_each (pointer_resource,
&pointer->focus_client->pointer_resources)
meta_wayland_pointer_send_leave (pointer, pointer_resource,
serial, surface);
meta_wayland_pointer_broadcast_frame (pointer);
}
void
@ -607,18 +746,14 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
wl_resource_get_client (pointer->focus_surface->resource);
struct wl_display *display = wl_client_get_display (client);
uint32_t serial;
struct wl_resource *resource;
serial = wl_display_next_serial (display);
if (pointer->focus_client)
{
wl_resource_for_each (resource,
&pointer->focus_client->pointer_resources)
{
wl_pointer_send_leave (resource, serial, pointer->focus_surface->resource);
}
meta_wayland_pointer_broadcast_leave (pointer,
serial,
pointer->focus_surface);
pointer->focus_client = NULL;
}
@ -630,7 +765,6 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
{
struct wl_client *client = wl_resource_get_client (surface->resource);
struct wl_display *display = wl_client_get_display (client);
struct wl_resource *resource;
ClutterPoint pos;
pointer->focus_surface = surface;
@ -649,12 +783,9 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
if (pointer->focus_client)
{
pointer->focus_serial = wl_display_next_serial (display);
wl_resource_for_each (resource,
&pointer->focus_client->pointer_resources)
{
broadcast_focus (pointer, resource);
}
meta_wayland_pointer_broadcast_enter (pointer,
pointer->focus_serial,
pointer->focus_surface);
}
}
@ -820,9 +951,12 @@ cursor_sprite_prepare_at (MetaCursorSprite *cursor_sprite,
MetaScreen *screen = display->screen;
const MetaMonitorInfo *monitor;
monitor = meta_screen_get_monitor_for_point (screen, x, y);
meta_cursor_sprite_set_texture_scale (cursor_sprite,
(float)monitor->scale / surface->scale);
if (!meta_xwayland_is_xwayland_surface (surface))
{
monitor = meta_screen_get_monitor_for_point (screen, x, y);
meta_cursor_sprite_set_texture_scale (cursor_sprite,
(float)monitor->scale / surface->scale);
}
meta_wayland_surface_update_outputs (surface);
}
@ -927,7 +1061,12 @@ meta_wayland_pointer_create_new_resource (MetaWaylandPointer *pointer,
wl_resource_get_link (cr));
if (pointer->focus_client == pointer_client)
broadcast_focus (pointer, cr);
{
meta_wayland_pointer_send_enter (pointer, cr,
pointer->focus_serial,
pointer->focus_surface);
meta_wayland_pointer_send_frame (pointer, cr);
}
}
gboolean

View File

@ -405,3 +405,12 @@ meta_wayland_seat_get_grab_info (MetaWaylandSeat *seat,
return sequence || can_grab_surface;
}
gboolean
meta_wayland_seat_can_popup (MetaWaylandSeat *seat,
uint32_t serial)
{
return (meta_wayland_pointer_can_popup (&seat->pointer, serial) ||
meta_wayland_keyboard_can_popup (&seat->keyboard, serial) ||
meta_wayland_touch_can_popup (&seat->touch, serial));
}

View File

@ -64,5 +64,7 @@ gboolean meta_wayland_seat_get_grab_info (MetaWaylandSeat *seat,
uint32_t serial,
gfloat *x,
gfloat *y);
gboolean meta_wayland_seat_can_popup (MetaWaylandSeat *seat,
uint32_t serial);
#endif /* META_WAYLAND_SEAT_H */

View File

@ -31,7 +31,7 @@
#include <wayland-server.h>
#include "gtk-shell-server-protocol.h"
#include "xdg-shell-server-protocol.h"
#include "xdg-shell-unstable-v5-server-protocol.h"
#include "meta-wayland-private.h"
#include "meta-xwayland-private.h"
@ -73,11 +73,8 @@ typedef struct
struct wl_listener sibling_destroy_listener;
} MetaWaylandSubsurfacePlacementOp;
GType meta_wayland_surface_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE (MetaWaylandSurface, meta_wayland_surface, G_TYPE_OBJECT);
GType meta_wayland_surface_role_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandSurfaceRole,
meta_wayland_surface_role,
G_TYPE_OBJECT);
@ -87,7 +84,6 @@ struct _MetaWaylandSurfaceRoleSubsurface
MetaWaylandSurfaceRole parent;
};
GType meta_wayland_surface_role_subsurface_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE (MetaWaylandSurfaceRoleSubsurface,
meta_wayland_surface_role_subsurface,
META_TYPE_WAYLAND_SURFACE_ROLE);
@ -97,7 +93,6 @@ struct _MetaWaylandSurfaceRoleXdgSurface
MetaWaylandSurfaceRole parent;
};
GType meta_wayland_surface_role_xdg_surface_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE (MetaWaylandSurfaceRoleXdgSurface,
meta_wayland_surface_role_xdg_surface,
META_TYPE_WAYLAND_SURFACE_ROLE);
@ -107,7 +102,6 @@ struct _MetaWaylandSurfaceRoleXdgPopup
MetaWaylandSurfaceRole parent;
};
GType meta_wayland_surface_role_xdg_popup_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE (MetaWaylandSurfaceRoleXdgPopup,
meta_wayland_surface_role_xdg_popup,
META_TYPE_WAYLAND_SURFACE_ROLE);
@ -117,7 +111,6 @@ struct _MetaWaylandSurfaceRoleWlShellSurface
MetaWaylandSurfaceRole parent;
};
GType meta_wayland_surface_role_wl_shell_surface_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE (MetaWaylandSurfaceRoleWlShellSurface,
meta_wayland_surface_role_wl_shell_surface,
META_TYPE_WAYLAND_SURFACE_ROLE);
@ -127,7 +120,6 @@ struct _MetaWaylandSurfaceRoleDND
MetaWaylandSurfaceRole parent;
};
GType meta_wayland_surface_role_dnd_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE (MetaWaylandSurfaceRoleDND,
meta_wayland_surface_role_dnd,
META_TYPE_WAYLAND_SURFACE_ROLE);
@ -265,8 +257,6 @@ dnd_surface_commit (MetaWaylandSurfaceRole *surface_role,
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);
}
static void
@ -359,12 +349,6 @@ toplevel_surface_commit (MetaWaylandSurfaceRole *surface_role,
return;
}
}
else if (META_IS_WAYLAND_SURFACE_ROLE_XDG_POPUP (surface->role))
{
/* Ignore commits if we couldn't grab the pointer */
if (!window)
return;
}
else
{
if (surface->buffer == NULL)
@ -377,10 +361,11 @@ toplevel_surface_commit (MetaWaylandSurfaceRole *surface_role,
}
}
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 };
@ -936,7 +921,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);
@ -947,22 +931,26 @@ set_surface_is_on_output (MetaWaylandSurface *surface,
MetaWaylandOutput *wayland_output,
gboolean is_on_output)
{
gboolean was_on_output = g_hash_table_contains (surface->outputs,
wayland_output);
gpointer orig_id;
gboolean was_on_output = g_hash_table_lookup_extended (surface->outputs_to_destroy_notify_id,
wayland_output,
NULL, &orig_id);
if (!was_on_output && is_on_output)
{
g_signal_connect (wayland_output, "output-destroyed",
G_CALLBACK (surface_handle_output_destroy),
surface);
g_hash_table_add (surface->outputs, wayland_output);
gulong id;
id = g_signal_connect (wayland_output, "output-destroyed",
G_CALLBACK (surface_handle_output_destroy),
surface);
g_hash_table_insert (surface->outputs_to_destroy_notify_id, wayland_output,
GSIZE_TO_POINTER ((gsize)id));
surface_entered_output (surface, wayland_output);
}
else if (was_on_output && !is_on_output)
{
g_hash_table_remove (surface->outputs, wayland_output);
g_signal_handlers_disconnect_by_func (
wayland_output, (gpointer)surface_handle_output_destroy, surface);
g_hash_table_remove (surface->outputs_to_destroy_notify_id, wayland_output);
g_signal_handler_disconnect (wayland_output, (gulong) GPOINTER_TO_SIZE (orig_id));
surface_left_output (surface, wayland_output);
}
}
@ -1000,6 +988,12 @@ update_surface_output_state (gpointer key, gpointer value, gpointer user_data)
set_surface_is_on_output (surface, wayland_output, is_on_output);
}
static void
surface_output_disconnect_signal (gpointer key, gpointer value, gpointer user_data)
{
g_signal_handler_disconnect (key, (gulong) GPOINTER_TO_SIZE (value));
}
void
meta_wayland_surface_update_outputs (MetaWaylandSurface *surface)
{
@ -1050,7 +1044,8 @@ wl_surface_destructor (struct wl_resource *resource)
meta_wayland_compositor_destroy_frame_callbacks (compositor, surface);
g_hash_table_unref (surface->outputs);
g_hash_table_foreach (surface->outputs_to_destroy_notify_id, surface_output_disconnect_signal, surface);
g_hash_table_unref (surface->outputs_to_destroy_notify_id);
wl_list_for_each_safe (cb, next, &surface->pending_frame_callback_list, link)
wl_resource_destroy (cb->resource);
@ -1095,7 +1090,7 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
sync_drag_dest_funcs (surface);
surface->outputs = g_hash_table_new (NULL, NULL);
surface->outputs_to_destroy_notify_id = g_hash_table_new (NULL, NULL);
pending_state_init (&surface->pending);
return surface;
@ -1436,8 +1431,8 @@ handle_popup_parent_destroyed (struct wl_listener *listener, void *data)
MetaWaylandSurface *surface =
wl_container_of (listener, surface, popup.parent_destroy_listener);
wl_resource_post_error (surface->xdg_popup,
XDG_POPUP_ERROR_NOT_THE_TOPMOST_POPUP,
wl_resource_post_error (surface->xdg_shell_resource,
XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP,
"destroyed popup not top most popup");
surface->popup.parent = NULL;
@ -1455,8 +1450,8 @@ handle_popup_destroyed (struct wl_listener *listener, void *data)
top_popup = meta_wayland_popup_get_top_popup (popup);
if (surface != top_popup)
{
wl_resource_post_error (surface->xdg_popup,
XDG_POPUP_ERROR_NOT_THE_TOPMOST_POPUP,
wl_resource_post_error (surface->xdg_shell_resource,
XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP,
"destroyed popup not top most popup");
}
@ -1507,7 +1502,7 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
(parent_surf->xdg_popup == NULL && parent_surf->xdg_surface == NULL))
{
wl_resource_post_error (resource,
XDG_POPUP_ERROR_INVALID_PARENT,
XDG_SHELL_ERROR_INVALID_POPUP_PARENT,
"invalid parent surface");
return;
}
@ -1517,7 +1512,7 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
(top_popup != NULL && parent_surf != top_popup))
{
wl_resource_post_error (resource,
XDG_POPUP_ERROR_NOT_THE_TOPMOST_POPUP,
XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP,
"parent not top most surface");
return;
}
@ -1529,15 +1524,15 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
surface,
xdg_popup_destructor);
if (!meta_wayland_pointer_can_popup (&seat->pointer, serial))
surface->xdg_popup = popup_resource;
surface->xdg_shell_resource = resource;
if (!meta_wayland_seat_can_popup (seat, 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,
@ -1753,7 +1748,7 @@ wl_shell_surface_set_popup (struct wl_client *client,
wl_shell_surface_set_state (surface, SURFACE_STATE_TOPLEVEL);
if (!meta_wayland_pointer_can_popup (&seat->pointer, serial))
if (!meta_wayland_seat_can_popup (seat, serial))
{
wl_shell_surface_send_popup_done (resource);
return;
@ -2390,6 +2385,15 @@ meta_wayland_surface_drag_dest_drop (MetaWaylandSurface *surface)
surface->dnd.funcs->drop (data_device, surface);
}
void
meta_wayland_surface_drag_dest_update (MetaWaylandSurface *surface)
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaWaylandDataDevice *data_device = &compositor->seat->data_device;
surface->dnd.funcs->update (data_device, surface);
}
MetaWindow *
meta_wayland_surface_get_toplevel_window (MetaWaylandSurface *surface)
{

View File

@ -128,6 +128,8 @@ struct _MetaWaylandDragDestFuncs
const ClutterEvent *event);
void (* drop) (MetaWaylandDataDevice *data_device,
MetaWaylandSurface *surface);
void (* update) (MetaWaylandDataDevice *data_device,
MetaWaylandSurface *surface);
};
struct _MetaWaylandSurface
@ -147,7 +149,7 @@ struct _MetaWaylandSurface
int scale;
int32_t offset_x, offset_y;
GList *subsurfaces;
GHashTable *outputs;
GHashTable *outputs_to_destroy_notify_id;
/* 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.
@ -240,6 +242,7 @@ void meta_wayland_surface_drag_dest_motion (MetaWaylandSurface
const ClutterEvent *event);
void meta_wayland_surface_drag_dest_focus_out (MetaWaylandSurface *surface);
void meta_wayland_surface_drag_dest_drop (MetaWaylandSurface *surface);
void meta_wayland_surface_drag_dest_update (MetaWaylandSurface *surface);
void meta_wayland_surface_update_outputs (MetaWaylandSurface *surface);

View File

@ -208,8 +208,8 @@ touch_get_relative_coordinates (MetaWaylandTouch *touch,
&event_x, &event_y);
}
*x = event_x;
*y = event_y;
*x = event_x / surface->scale;
*y = event_y / surface->scale;
}
@ -575,6 +575,26 @@ meta_wayland_touch_create_new_resource (MetaWaylandTouch *touch,
wl_list_insert (&touch->resource_list, wl_resource_get_link (cr));
}
gboolean
meta_wayland_touch_can_popup (MetaWaylandTouch *touch,
uint32_t serial)
{
MetaWaylandTouchInfo *touch_info;
GHashTableIter iter;
if (!touch->touches)
return FALSE;
g_hash_table_iter_init (&iter, touch->touches);
while (g_hash_table_iter_next (&iter, NULL, (gpointer*) &touch_info))
{
if (touch_info->slot_serial == serial)
return TRUE;
}
return FALSE;
}
ClutterEventSequence *
meta_wayland_touch_find_grab_sequence (MetaWaylandTouch *touch,
MetaWaylandSurface *surface,

View File

@ -70,4 +70,7 @@ gboolean meta_wayland_touch_get_press_coords (MetaWaylandTouch *touch,
gfloat *x,
gfloat *y);
gboolean meta_wayland_touch_can_popup (MetaWaylandTouch *touch,
uint32_t serial);
#endif /* META_WAYLAND_TOUCH_H */

View File

@ -29,6 +29,8 @@ typedef struct _MetaWaylandPointerGrabInterface MetaWaylandPointerGrabInterface;
typedef struct _MetaWaylandPopupGrab MetaWaylandPopupGrab;
typedef struct _MetaWaylandPopup MetaWaylandPopup;
typedef struct _MetaWaylandKeyboard MetaWaylandKeyboard;
typedef struct _MetaWaylandKeyboardGrab MetaWaylandKeyboardGrab;
typedef struct _MetaWaylandKeyboardGrabInterface MetaWaylandKeyboardGrabInterface;
typedef struct _MetaWaylandTouch MetaWaylandTouch;
typedef struct _MetaWaylandDragDestFuncs MetaWaylandDragDestFuncs;
typedef struct _MetaWaylandDataOffer MetaWaylandDataOffer;

View File

@ -36,14 +36,14 @@
/* Global/master objects (version exported by wl_registry and negotiated through bind) */
#define META_WL_COMPOSITOR_VERSION 3
#define META_WL_DATA_DEVICE_MANAGER_VERSION 2
#define META_WL_DATA_DEVICE_MANAGER_VERSION 3
#define META_XDG_SHELL_VERSION 1
#define META_WL_SHELL_VERSION 1
#define META_WL_SEAT_VERSION 4
#define META_WL_SEAT_VERSION 5
#define META_WL_OUTPUT_VERSION 2
#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_ZWP_POINTER_GESTURES_V1_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
};
@ -272,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)
@ -335,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

@ -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

@ -39,8 +39,6 @@
#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
@ -88,6 +86,7 @@ struct _MetaWaylandDataSourceXWayland
MetaWaylandDataSource parent;
MetaSelectionBridge *selection;
guint has_utf8_string_atom : 1;
};
struct _MetaXWaylandSelection {
@ -109,6 +108,7 @@ enum {
ATOM_DND_ACTION_MOVE,
ATOM_DND_ACTION_COPY,
ATOM_DND_ACTION_ASK,
ATOM_DND_ACTION_PRIVATE,
N_DND_ATOMS
};
@ -127,6 +127,7 @@ const gchar *atom_names[] = {
"XdndActionMove",
"XdndActionCopy",
"XdndActionAsk",
"XdndActionPrivate",
NULL
};
@ -136,6 +137,33 @@ G_DEFINE_TYPE (MetaWaylandDataSourceXWayland, meta_wayland_data_source_xwayland,
META_TYPE_WAYLAND_DATA_SOURCE);
/* XDND helpers */
static Atom
action_to_atom (uint32_t action)
{
if (action & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
return xdnd_atoms[ATOM_DND_ACTION_COPY];
else if (action & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
return xdnd_atoms[ATOM_DND_ACTION_MOVE];
else if (action & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
return xdnd_atoms[ATOM_DND_ACTION_ASK];
else
return None;
}
static enum wl_data_device_manager_dnd_action
atom_to_action (Atom atom)
{
if (atom == xdnd_atoms[ATOM_DND_ACTION_COPY] ||
atom == xdnd_atoms[ATOM_DND_ACTION_PRIVATE])
return WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
else if (atom == xdnd_atoms[ATOM_DND_ACTION_MOVE])
return WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
else if (atom == xdnd_atoms[ATOM_DND_ACTION_ASK])
return WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
else
return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
}
static void
xdnd_send_enter (MetaXWaylandSelection *selection_data,
Window dest)
@ -162,7 +190,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)
@ -219,10 +246,21 @@ xdnd_send_position (MetaXWaylandSelection *selection_data,
int x,
int y)
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaSelectionBridge *selection = &selection_data->dnd.selection;
MetaWaylandDataSource *source = compositor->seat->data_device.dnd_data_source;
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
uint32_t action = 0, user_action, actions;
XEvent xev = { 0 };
user_action = meta_wayland_data_source_get_user_action (source);
actions = meta_wayland_data_source_get_actions (source);
if (user_action & actions)
action = user_action;
if (!action)
action = actions;
xev.xclient.type = ClientMessage;
xev.xclient.message_type = xdnd_atoms[ATOM_DND_POSITION];
xev.xclient.format = 32;
@ -232,7 +270,7 @@ xdnd_send_position (MetaXWaylandSelection *selection_data,
xev.xclient.data.l[1] = 0;
xev.xclient.data.l[2] = (x << 16) | y;
xev.xclient.data.l[3] = time;
xev.xclient.data.l[4] = xdnd_atoms[ATOM_DND_ACTION_COPY];
xev.xclient.data.l[4] = action_to_atom (action);
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
}
@ -264,6 +302,8 @@ xdnd_send_finished (MetaXWaylandSelection *selection_data,
{
MetaDndBridge *selection = &selection_data->dnd;
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
MetaWaylandDataSource *source = selection_data->dnd.selection.source;
uint32_t action = 0;
XEvent xev = { 0 };
xev.xclient.type = ClientMessage;
@ -275,8 +315,9 @@ xdnd_send_finished (MetaXWaylandSelection *selection_data,
if (accepted)
{
action = meta_wayland_data_source_get_current_action (source);
xev.xclient.data.l[1] = 1; /* Drop successful */
xev.xclient.data.l[2] = xdnd_atoms[ATOM_DND_ACTION_COPY];
xev.xclient.data.l[2] = action_to_atom (action);
}
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
@ -285,7 +326,7 @@ xdnd_send_finished (MetaXWaylandSelection *selection_data,
static void
xdnd_send_status (MetaXWaylandSelection *selection_data,
Window dest,
gboolean accepted)
uint32_t action)
{
MetaDndBridge *selection = &selection_data->dnd;
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
@ -298,12 +339,10 @@ xdnd_send_status (MetaXWaylandSelection *selection_data,
xev.xclient.data.l[0] = selection->dnd_window;
xev.xclient.data.l[1] = 1 << 1; /* Bit 2: dest wants XdndPosition messages */
xev.xclient.data.l[4] = action_to_atom (action);
if (accepted)
{
xev.xclient.data.l[1] |= 1 << 0; /* Bit 1: dest accepts the drop */
xev.xclient.data.l[4] = xdnd_atoms[ATOM_DND_ACTION_COPY];
}
if (xev.xclient.data.l[4])
xev.xclient.data.l[1] |= 1 << 0; /* Bit 1: dest accepts the drop */
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
}
@ -389,6 +428,32 @@ x11_selection_data_free (X11SelectionData *data)
g_slice_free (X11SelectionData, data);
}
static void
x11_selection_data_send_finished (MetaSelectionBridge *selection,
gboolean success)
{
uint32_t action = meta_wayland_data_source_get_current_action (selection->source);
if (!selection->x11_selection)
return;
if (success && action == WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
{
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
/* Request data deletion on the drag source */
XConvertSelection (xdisplay,
selection->selection_atom,
gdk_x11_get_xatom_by_name ("DELETE"),
gdk_x11_get_xatom_by_name ("_META_SELECTION"),
selection->window,
CurrentTime);
}
xdnd_send_finished (selection->x11_selection->selection_data,
selection->owner, success);
}
static void
x11_selection_data_finish (MetaSelectionBridge *selection,
gboolean success)
@ -397,13 +462,18 @@ x11_selection_data_finish (MetaSelectionBridge *selection,
return;
if (selection == &selection->x11_selection->selection_data->dnd.selection)
xdnd_send_finished (selection->x11_selection->selection_data,
selection->owner, success);
x11_selection_data_send_finished (selection, success);
g_clear_pointer (&selection->x11_selection,
(GDestroyNotify) x11_selection_data_free);
}
static void
x11_selection_data_close (X11SelectionData *data)
{
g_output_stream_close (data->stream, data->cancellable, NULL);
}
static void
x11_data_write_cb (GObject *object,
GAsyncResult *res,
@ -412,27 +482,34 @@ 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_close (selection->x11_selection);
x11_selection_data_finish (selection, success);
}
if (!data->incr)
x11_selection_data_finish (selection, TRUE);
}
static void
@ -689,6 +766,7 @@ meta_xwayland_selection_get_incr_chunk (MetaWaylandCompositor *compositor,
else
{
/* Transfer has completed */
x11_selection_data_close (selection->x11_selection);
x11_selection_data_finish (selection, TRUE);
}
@ -707,7 +785,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);
@ -736,11 +815,15 @@ meta_x11_source_target (MetaWaylandDataSource *source,
MetaWaylandDataSourceXWayland *source_xwayland =
META_WAYLAND_DATA_SOURCE_XWAYLAND (source);
MetaSelectionBridge *selection = source_xwayland->selection;
uint32_t action = 0;
if (selection->selection_atom == xdnd_atoms[ATOM_DND_SELECTION])
{
if (mime_type)
action = meta_wayland_data_source_get_current_action (source);
xdnd_send_status (compositor->xwayland_manager.selection_data,
selection->owner, mime_type != NULL);
selection->owner, action);
}
}
@ -751,10 +834,46 @@ meta_x11_source_cancel (MetaWaylandDataSource *source)
META_WAYLAND_DATA_SOURCE_XWAYLAND (source);
MetaSelectionBridge *selection = source_xwayland->selection;
x11_selection_data_send_finished (selection, FALSE);
g_clear_pointer (&selection->x11_selection,
(GDestroyNotify) x11_selection_data_free);
}
static void
meta_x11_source_action (MetaWaylandDataSource *source,
uint32_t action)
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaWaylandDataSourceXWayland *source_xwayland =
META_WAYLAND_DATA_SOURCE_XWAYLAND (source);
MetaSelectionBridge *selection = source_xwayland->selection;
if (selection->selection_atom == xdnd_atoms[ATOM_DND_SELECTION])
{
if (!meta_wayland_data_source_has_target (source))
action = 0;
xdnd_send_status (compositor->xwayland_manager.selection_data,
selection->owner, action);
}
}
static void
meta_x11_source_drop_performed (MetaWaylandDataSource *source)
{
}
static void
meta_x11_source_drag_finished (MetaWaylandDataSource *source)
{
MetaWaylandDataSourceXWayland *source_xwayland =
META_WAYLAND_DATA_SOURCE_XWAYLAND (source);
MetaSelectionBridge *selection = source_xwayland->selection;
if (selection->x11_selection)
x11_selection_data_send_finished (selection, TRUE);
}
static void
meta_wayland_data_source_xwayland_init (MetaWaylandDataSourceXWayland *source_xwayland)
{
@ -769,6 +888,9 @@ meta_wayland_data_source_xwayland_class_init (MetaWaylandDataSourceXWaylandClass
data_source_class->send = meta_x11_source_send;
data_source_class->target = meta_x11_source_target;
data_source_class->cancel = meta_x11_source_cancel;
data_source_class->action = meta_x11_source_action;
data_source_class->drop_performed = meta_x11_source_drop_performed;
data_source_class->drag_finished = meta_x11_source_drag_finished;
}
static MetaWaylandDataSource *
@ -832,11 +954,27 @@ meta_x11_drag_dest_drop (MetaWaylandDataDevice *data_device,
meta_display_get_current_time_roundtrip (meta_get_display ()));
}
static void
meta_x11_drag_dest_update (MetaWaylandDataDevice *data_device,
MetaWaylandSurface *surface)
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaWaylandSeat *seat = compositor->seat;
ClutterPoint pos;
clutter_input_device_get_coords (seat->pointer.device, NULL, &pos);
xdnd_send_position (compositor->xwayland_manager.selection_data,
compositor->xwayland_manager.selection_data->dnd.dnd_dest,
clutter_get_current_event_time (),
pos.x, pos.y);
}
static const MetaWaylandDragDestFuncs meta_x11_drag_dest_funcs = {
meta_x11_drag_dest_focus_in,
meta_x11_drag_dest_focus_out,
meta_x11_drag_dest_motion,
meta_x11_drag_dest_drop
meta_x11_drag_dest_drop,
meta_x11_drag_dest_update
};
const MetaWaylandDragDestFuncs *
@ -850,6 +988,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;
@ -883,10 +1023,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);
}
@ -1125,6 +1268,10 @@ meta_xwayland_selection_handle_selection_request (MetaWaylandCompositor *composi
selection->timestamp);
reply_selection_request (event, TRUE);
}
else if (data_source && event->target == gdk_x11_get_xatom_by_name ("DELETE"))
{
reply_selection_request (event, TRUE);
}
else
{
if (data_source &&
@ -1247,6 +1394,7 @@ meta_xwayland_selection_handle_client_message (MetaWaylandCompositor *compositor
if (event->window == dnd->selection.window)
{
MetaWaylandDataSource *data_source;
uint32_t action = 0;
data_source = compositor->seat->data_device.dnd_data_source;
@ -1259,6 +1407,11 @@ meta_xwayland_selection_handle_client_message (MetaWaylandCompositor *compositor
meta_wayland_data_source_set_has_target (data_source,
(event->data.l[1] & 1) != 0);
/* data.l[4] contains the action atom */
if (event->data.l[4])
action = atom_to_action ((Atom) event->data.l[4]);
meta_wayland_data_source_set_current_action (data_source, action);
return TRUE;
}
else if (event->message_type == xdnd_atoms[ATOM_DND_FINISHED])
@ -1267,8 +1420,7 @@ meta_xwayland_selection_handle_client_message (MetaWaylandCompositor *compositor
if (compositor->seat->data_device.current_grab)
return FALSE;
meta_wayland_data_device_set_dnd_source (&compositor->seat->data_device,
NULL);
meta_wayland_data_source_notify_finish (data_source);
return TRUE;
}
}
@ -1280,6 +1432,10 @@ 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 &&
event->message_type != xdnd_atoms[ATOM_DND_ENTER])
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
@ -1325,6 +1481,7 @@ meta_xwayland_selection_handle_client_message (MetaWaylandCompositor *compositor
{
ClutterEvent *motion;
ClutterPoint pos;
uint32_t action = 0;
motion = clutter_event_new (CLUTTER_MOTION);
clutter_input_device_get_coords (seat->pointer.device, NULL, &pos);
@ -1333,11 +1490,13 @@ meta_xwayland_selection_handle_client_message (MetaWaylandCompositor *compositor
clutter_event_set_source_device (motion, seat->pointer.device);
clutter_event_set_time (motion, dnd->last_motion_time);
action = atom_to_action ((Atom) event->data.l[4]);
meta_wayland_data_source_set_actions (dnd->selection.source, action);
meta_wayland_surface_drag_dest_motion (drag_focus, motion);
xdnd_send_status (compositor->xwayland_manager.selection_data,
(Window) event->data.l[0],
meta_wayland_data_source_has_target (
dnd->selection.source));
meta_wayland_data_source_get_current_action (dnd->selection.source));
clutter_event_free (motion);
return TRUE;

View File

@ -45,7 +45,6 @@ struct _MetaWaylandSurfaceRoleXWayland
MetaWaylandSurfaceRole parent;
};
GType meta_wayland_surface_role_xwayland_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE (MetaWaylandSurfaceRoleXWayland,
meta_wayland_surface_role_xwayland,
META_TYPE_WAYLAND_SURFACE_ROLE);
@ -56,13 +55,6 @@ associate_window_with_surface (MetaWindow *window,
{
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))
{
@ -89,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)
{
@ -172,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,

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

@ -1,176 +0,0 @@
<protocol name="pointer_gestures">
<interface name="_wl_pointer_gestures" version="1">
<description summary="touchpad gestures">
A global interface to provide semantic touchpad gestures for a given
pointer.
Two gestures are currently supported: swipe and zoom/rotate.
All gestures follow a three-stage cycle: begin, update, end and
are identified by a unique id.
Warning! The protocol described in this file is experimental. Each
version of this protocol should be considered incompatible with any
other version, and a client binding to a version different to the one
advertised will be terminated. Once the protocol is declared stable,
compatibility is guaranteed, the '_' prefix will be removed from the
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
wl_pointer_gesture_swipe interface for details.
</description>
<arg name="id" type="new_id" interface="_wl_pointer_gesture_swipe"/>
<arg name="pointer" type="object" interface="wl_pointer"/>
</request>
<request name="get_pinch_gesture">
<description summary="get pinch gesture">
Create a pinch gesture object. See the
wl_pointer_gesture_pinch interface for details.
</description>
<arg name="id" type="new_id" interface="_wl_pointer_gesture_pinch"/>
<arg name="pointer" type="object" interface="wl_pointer"/>
</request>
</interface>
<interface name="_wl_pointer_gesture_swipe" version="1">
<description summary="a swipe gesture object">
A swipe gesture object notifies a client about a multi-finger swipe
gesture detected on an indirect input device such as a touchpad.
The gesture is usually initiated by multiple fingers moving in the
same direction but once initiated the direction may change.
The precise conditions of when such a gesture is detected are
implementation-dependent.
A gesture consists of three stages: begin, update (optional) and end.
There cannot be multiple simultaneous pinch or swipe gestures on a
same pointer/seat, how compositors prevent these situations is
implementation-dependent.
A gesture may be cancelled by the compositor or the hardware.
Clients should not consider performing permanent or irreversible
actions until the end of a gesture has been received.
</description>
<request name="destroy" type="destructor">
<description summary="destroy the pointer swipe gesture object"/>
</request>
<event name="begin">
<description summary="multi-finger swipe begin">
This event is sent when a multi-finger swipe gesture is detected
on the device.
</description>
<arg name="serial" type="uint"/>
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="fingers" type="uint" summary="number of fingers"/>
</event>
<event name="update">
<description summary="multi-finger swipe motion">
This event is sent when a multi-finger swipe gesture changes the
position of the logical center.
The dx and dy coordinates are relative coordinates of the logical
center of the gesture compared to the previous event.
</description>
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
<arg name="dx" type="fixed" summary="delta x coordinate in surface coordinate space"/>
<arg name="dy" type="fixed" summary="delta y coordinate in surface coordinate space"/>
</event>
<event name="end">
<description summary="multi-finger swipe end">
This event is sent when a multi-finger swipe gesture ceases to
be valid. This may happen when one or more finger is lifted or
the gesture is cancelled.
When a gesture is cancelled, the client should undo state changes
caused by this gesture. What causes a gesture to be cancelled is
implementation-dependent.
</description>
<arg name="serial" type="uint"/>
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
<arg name="cancelled" type="int" summary="1 if the gesture was cancelled, 0 otherwise"/>
</event>
</interface>
<interface name="_wl_pointer_gesture_pinch" version="1">
<description summary="a pinch gesture object">
A pinch gesture object notifies a client about a multi-finger pinch
gesture detected on an indirect input device such as a touchpad.
The gesture is usually initiated by multiple fingers moving towards
each other or away from each other, or by two or more fingers rotating
around a logical center of gravity. The precise conditions of when
such a gesture is detected are implementation-dependent.
A gesture consists of three stages: begin, update (optional) and end.
There cannot be multiple simultaneous pinch or swipe gestures on a
same pointer/seat, how compositors prevent these situations is
implementation-dependent.
A gesture may be cancelled by the compositor or the hardware.
Clients should not consider performing permanent or irreversible
actions until the end of a gesture has been received.
</description>
<request name="destroy" type="destructor">
<description summary="destroy the pinch gesture object"/>
</request>
<event name="begin">
<description summary="multi-finger pinch begin">
This event is sent when a multi-finger pinch gesture is detected
on the device.
</description>
<arg name="serial" type="uint"/>
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="fingers" type="uint" summary="number of fingers"/>
</event>
<event name="update">
<description summary="multi-finger pinch motion">
This event is sent when a multi-finger pinch gesture changes the
position of the logical center, the rotation or the relative scale.
The dx and dy coordinates are relative coordinates in the
surface coordinate space of the logical center of the gesture.
The scale factor is an absolute scale compared to the
pointer_gesture_pinch.begin event, e.g. a scale of 2 means the fingers
are now twice as far apart as on pointer_gesture_pinch.begin.
The rotation is the relative angle in degrees clockwise compared to the previous
pointer_gesture_pinch.begin or pointer_gesture_pinch.update event.
</description>
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
<arg name="dx" type="fixed" summary="delta x coordinate in surface coordinate space"/>
<arg name="dy" type="fixed" summary="delta y coordinate in surface coordinate space"/>
<arg name="scale" type="fixed" summary="scale relative to the initial finger position"/>
<arg name="rotation" type="fixed" summary="angle in degrees cw relative to the previous event"/>
</event>
<event name="end">
<description summary="multi-finger pinch end">
This event is sent when a multi-finger pinch gesture ceases to
be valid. This may happen when one or more finger is lifted or
the gesture is cancelled.
When a gesture is cancelled, the client should undo state changes
caused by this gesture. What causes a gesture to be cancelled is
implementation-dependent.
</description>
<arg name="serial" type="uint"/>
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
<arg name="cancelled" type="int" summary="1 if the gesture was cancelled, 0 otherwise"/>
</event>
</interface>
</protocol>

View File

@ -1,485 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="xdg_shell">
<copyright>
Copyright © 2008-2013 Kristian Høgsberg
Copyright © 2013 Rafael Antognolli
Copyright © 2013 Jasper St. Pierre
Copyright © 2010-2013 Intel Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that copyright notice and this permission
notice appear in supporting documentation, and that the name of
the copyright holders not be used in advertising or publicity
pertaining to distribution of the software without specific,
written prior permission. The copyright holders make no
representations about the suitability of this software for any
purpose. It is provided "as is" without express or implied
warranty.
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
</copyright>
<interface name="xdg_shell" version="1">
<description summary="create desktop-style surfaces">
xdg_shell allows clients to turn a wl_surface into a "real window"
which can be dragged, resized, stacked, and moved around by the
user. Everything about this interface is suited towards traditional
desktop environments.
</description>
<enum name="version">
<description summary="latest protocol version">
The 'current' member of this enum gives the version of the
protocol. Implementations can compare this to the version
they implement using static_assert to ensure the protocol and
implementation versions match.
</description>
<entry name="current" value="5" summary="Always the latest version"/>
</enum>
<enum name="error">
<entry name="role" value="0" summary="given wl_surface has another role"/>
</enum>
<request name="destroy" type="destructor">
<description summary="destroy xdg_shell">
Destroy this xdg_shell object.
Destroying a bound xdg_shell object while there are surfaces
still alive with roles from this interface is illegal and will
result in a protocol error. Make sure to destroy all surfaces
before destroying this object.
</description>
</request>
<request name="use_unstable_version">
<description summary="enable use of this unstable version">
Negotiate the unstable version of the interface. This
mechanism is in place to ensure client and server agree on the
unstable versions of the protocol that they speak or exit
cleanly if they don't agree. This request will go away once
the xdg-shell protocol is stable.
</description>
<arg name="version" type="int"/>
</request>
<request name="get_xdg_surface">
<description summary="create a shell surface from a surface">
This creates an xdg_surface for the given surface and gives it the
xdg_surface role. See the documentation of xdg_surface for more details.
</description>
<arg name="id" type="new_id" interface="xdg_surface"/>
<arg name="surface" type="object" interface="wl_surface"/>
</request>
<request name="get_xdg_popup">
<description summary="create a popup for a surface">
This creates an xdg_popup for the given surface and gives it the
xdg_popup role. See the documentation of xdg_popup for more details.
This request must be used in response to some sort of user action
like a button press, key press, or touch down event.
</description>
<arg name="id" type="new_id" interface="xdg_popup"/>
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="parent" type="object" interface="wl_surface"/>
<arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
<arg name="serial" type="uint" summary="the serial of the user event"/>
<arg name="x" type="int"/>
<arg name="y" type="int"/>
</request>
<event name="ping">
<description summary="check if the client is alive">
The ping event asks the client if it's still alive. Pass the
serial specified in the event back to the compositor by sending
a "pong" request back with the specified serial.
Compositors can use this to determine if the client is still
alive. It's unspecified what will happen if the client doesn't
respond to the ping request, or in what timeframe. Clients should
try to respond in a reasonable amount of time.
</description>
<arg name="serial" type="uint" summary="pass this to the pong request"/>
</event>
<request name="pong">
<description summary="respond to a ping event">
A client must respond to a ping event with a pong request or
the client may be deemed unresponsive.
</description>
<arg name="serial" type="uint" summary="serial of the ping event"/>
</request>
</interface>
<interface name="xdg_surface" version="1">
<description summary="A desktop window">
An interface that may be implemented by a wl_surface, for
implementations that provide a desktop-style user interface.
It provides requests to treat surfaces like windows, allowing to set
properties like maximized, fullscreen, minimized, and to move and resize
them, and associate metadata like title and app id.
</description>
<request name="destroy" type="destructor">
<description summary="Destroy the xdg_surface">
Unmap and destroy the window. The window will be effectively
hidden from the user's point of view, and all state like
maximization, fullscreen, and so on, will be lost.
</description>
</request>
<request name="set_parent">
<description summary="set the parent of this surface">
Set the "parent" of this surface. This window should be stacked
above a parent. The parent surface must be mapped as long as this
surface is mapped.
Parent windows should be set on dialogs, toolboxes, or other
"auxilliary" surfaces, so that the parent is raised when the dialog
is raised.
</description>
<arg name="parent" type="object" interface="xdg_surface" allow-null="true"/>
</request>
<request name="set_title">
<description summary="set surface title">
Set a short title for the surface.
This string may be used to identify the surface in a task bar,
window list, or other user interface elements provided by the
compositor.
The string must be encoded in UTF-8.
</description>
<arg name="title" type="string"/>
</request>
<request name="set_app_id">
<description summary="set application ID">
Set an application identifier for the surface.
The app ID identifies the general class of applications to which
the surface belongs. The compositor can use this to group multiple
applications together, or to determine how to launch a new
application.
See the desktop-entry specification [0] for more details on
application identifiers and how they relate to well-known DBus
names and .desktop files.
[0] http://standards.freedesktop.org/desktop-entry-spec/
</description>
<arg name="app_id" type="string"/>
</request>
<request name="show_window_menu">
<description summary="show the window menu">
Clients implementing client-side decorations might want to show
a context menu when right-clicking on the decorations, giving the
user a menu that they can use to maximize or minimize the window.
This request asks the compositor to pop up such a window menu at
the given position, relative to the local surface coordinates of
the parent surface. There are no guarantees as to what menu items
the window menu contains.
This request must be used in response to some sort of user action
like a button press, key press, or touch down event.
</description>
<arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
<arg name="serial" type="uint" summary="the serial of the user event"/>
<arg name="x" type="int" summary="the x position to pop up the window menu at"/>
<arg name="y" type="int" summary="the y position to pop up the window menu at"/>
</request>
<request name="move">
<description summary="start an interactive move">
Start an interactive, user-driven move of the surface.
This request must be used in response to some sort of user action
like a button press, key press, or touch down event.
The server may ignore move requests depending on the state of
the surface (e.g. fullscreen or maximized).
</description>
<arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
<arg name="serial" type="uint" summary="the serial of the user event"/>
</request>
<enum name="resize_edge">
<description summary="edge values for resizing">
These values are used to indicate which edge of a surface
is being dragged in a resize operation. The server may
use this information to adapt its behavior, e.g. choose
an appropriate cursor image.
</description>
<entry name="none" value="0"/>
<entry name="top" value="1"/>
<entry name="bottom" value="2"/>
<entry name="left" value="4"/>
<entry name="top_left" value="5"/>
<entry name="bottom_left" value="6"/>
<entry name="right" value="8"/>
<entry name="top_right" value="9"/>
<entry name="bottom_right" value="10"/>
</enum>
<request name="resize">
<description summary="start an interactive resize">
Start a user-driven, interactive resize of the surface.
This request must be used in response to some sort of user action
like a button press, key press, or touch down event.
The server may ignore resize requests depending on the state of
the surface (e.g. fullscreen or maximized).
</description>
<arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
<arg name="serial" type="uint" summary="the serial of the user event"/>
<arg name="edges" type="uint" summary="which edge or corner is being dragged"/>
</request>
<enum name="state">
<description summary="types of state on the surface">
The different state values used on the surface. This is designed for
state values like maximized, fullscreen. It is paired with the
configure event to ensure that both the client and the compositor
setting the state can be synchronized.
States set in this way are double-buffered. They will get applied on
the next commit.
Desktop environments may extend this enum by taking up a range of
values and documenting the range they chose in this description.
They are not required to document the values for the range that they
chose. Ideally, any good extensions from a desktop environment should
make its way into standardization into this enum.
The current reserved ranges are:
0x0000 - 0x0FFF: xdg-shell core values, documented below.
0x1000 - 0x1FFF: GNOME
</description>
<entry name="maximized" value="1" summary="the surface is maximized">
The surface is maximized. The window geometry specified in the configure
event must be obeyed by the client.
</entry>
<entry name="fullscreen" value="2" summary="the surface is fullscreen">
The surface is fullscreen. The window geometry specified in the configure
event must be obeyed by the client.
</entry>
<entry name="resizing" value="3">
The surface is being resized. The window geometry specified in the
configure event is a maximum; the client cannot resize beyond it.
Clients that have aspect ratio or cell sizing configuration can use
a smaller size, however.
</entry>
<entry name="activated" value="4">
Client window decorations should be painted as if the window is
active. Do not assume this means that the window actually has
keyboard or pointer focus.
</entry>
</enum>
<event name="configure">
<description summary="suggest a surface change">
The configure event asks the client to resize its surface or to
change its state.
The width and height arguments specify a hint to the window
about how its surface should be resized in window geometry
coordinates.
The states listed in the event specify how the width/height
arguments should be interpreted, and possibly how it should be
drawn.
Clients should arrange their surface for the new size and
states, and then send a ack_configure request with the serial
sent in this configure event at some point before committing
the new surface.
If the client receives multiple configure events before it
can respond to one, it is free to discard all but the last
event it received.
</description>
<arg name="width" type="int"/>
<arg name="height" type="int"/>
<arg name="states" type="array"/>
<arg name="serial" type="uint"/>
</event>
<request name="ack_configure">
<description summary="ack a configure event">
When a configure event is received, if a client commits the
surface in response to the configure event, then the client
must make a ack_configure request before the commit request,
passing along the serial of the configure event.
The compositor might use this information to move a surface
to the top left only when the client has drawn itself for
the maximized or fullscreen state.
If the client receives multiple configure events before it
can respond to one, it only has to ack the last configure event.
</description>
<arg name="serial" type="uint" summary="the serial from the configure event"/>
</request>
<request name="set_window_geometry">
<description summary="set the new window geometry">
The window geometry of a window is its "visible bounds" from the
user's perspective. Client-side decorations often have invisible
portions like drop-shadows which should be ignored for the
purposes of aligning, placing and constraining windows.
Once the window geometry of the surface is set once, it is not
possible to unset it, and it will remain the same until
set_window_geometry is called again, even if a new subsurface or
buffer is attached.
If never set, the value is the full bounds of the surface,
including any subsurfaces. This updates dynamically on every
commit. This unset mode is meant for extremely simple clients.
If responding to a configure event, the window geometry in here
must respect the sizing negotiations specified by the states in
the configure event.
The width and height must be greater than zero.
</description>
<arg name="x" type="int"/>
<arg name="y" type="int"/>
<arg name="width" type="int"/>
<arg name="height" type="int"/>
</request>
<request name="set_maximized" />
<request name="unset_maximized" />
<request name="set_fullscreen">
<description summary="set the window as fullscreen on a monitor">
Make the surface fullscreen.
You can specify an output that you would prefer to be fullscreen.
If this value is NULL, it's up to the compositor to choose which
display will be used to map this surface.
</description>
<arg name="output" type="object" interface="wl_output" allow-null="true"/>
</request>
<request name="unset_fullscreen" />
<request name="set_minimized">
<description summary="set the window as minimized">
Request that the compositor minimize your surface. There is no
way to know if the surface is currently minimized, nor is there
any way to unset minimization on this surface.
If you are looking to throttle redrawing when minimized, please
instead use the wl_surface.frame event for this, as this will
also work with live previews on windows in Alt-Tab, Expose or
similar compositor features.
</description>
</request>
<event name="close">
<description summary="surface wants to be closed">
The close event is sent by the compositor when the user
wants the surface to be closed. This should be equivalent to
the user clicking the close button in client-side decorations,
if your application has any...
This is only a request that the user intends to close your
window. The client may choose to ignore this request, or show
a dialog to ask the user to save their data...
</description>
</event>
</interface>
<interface name="xdg_popup" version="1">
<description summary="short-lived, popup surfaces for menus">
A popup surface is a short-lived, temporary surface that can be
used to implement menus. It takes an explicit grab on the surface
that will be dismissed when the user dismisses the popup. This can
be done by the user clicking outside the surface, using the keyboard,
or even locking the screen through closing the lid or a timeout.
When the popup is dismissed, a popup_done event will be sent out,
and at the same time the surface will be unmapped. The xdg_popup
object is now inert and cannot be reactivated, so clients should
destroy it. Explicitly destroying the xdg_popup object will also
dismiss the popup and unmap the surface.
Clients will receive events for all their surfaces during this
grab (which is an "owner-events" grab in X11 parlance). This is
done so that users can navigate through submenus and other
"nested" popup windows without having to dismiss the topmost
popup.
Clients that want to dismiss the popup when another surface of
their own is clicked should dismiss the popup using the destroy
request.
The parent surface must have either an xdg_surface or xdg_popup
role.
Specifying an xdg_popup for the parent means that the popups are
nested, with this popup now being the topmost popup. Nested
popups must be destroyed in the reverse order they were created
in, e.g. the only popup you are allowed to destroy at all times
is the topmost one.
If there is an existing popup when creating a new popup, the
parent must be the current topmost popup.
A parent surface must be mapped before the new popup is mapped.
When compositors choose to dismiss a popup, they will likely
dismiss every nested popup as well.
The x and y arguments specify where the top left of the popup
should be placed, relative to the local surface coordinates of the
parent surface.
</description>
<enum name="error">
<description summary="xdg_popup error values">
These errors can be emitted in response to xdg_popup requests.
</description>
<entry name="not_the_topmost_popup" value="0" summary="The client tried to map or destroy a non-toplevel popup"/>
<entry name="invalid_parent" value="1" summary="The client specified an invalid parent surface"/>
</enum>
<request name="destroy" type="destructor">
<description summary="remove xdg_popup interface">
This destroys the popup. Explicitly destroying the xdg_popup
object will also dismiss the popup, and unmap the surface.
If this xdg_popup is not the "topmost" popup, a protocol error
will be sent.
</description>
</request>
<event name="popup_done">
<description summary="popup interaction is done">
The popup_done event is sent out when a popup is dismissed
by the compositor.
</description>
</event>
</interface>
</protocol>

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

@ -389,7 +389,7 @@ meta_window_apply_session_info (MetaWindow *window,
"Restoring minimized state %d for window %s\n",
info->minimized, window->desc);
if (window->has_minimize_func && info->minimized)
if (info->minimized)
meta_window_minimize (window);
}
@ -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;
@ -863,7 +860,7 @@ meta_window_x11_grab_op_began (MetaWindow *window,
if (window->sync_request_counter != None)
meta_window_x11_create_sync_request_alarm (window);
if (window->size_hints.width_inc > 1 || window->size_hints.height_inc > 1)
if (window->size_hints.width_inc > 2 || window->size_hints.height_inc > 2)
{
priv->showing_resize_popup = TRUE;
meta_window_refresh_resize_popup (window);
@ -1850,6 +1847,12 @@ meta_window_x11_update_shape_region (MetaWindow *window)
* this is simply the client area.
*/
cairo_region_intersect_rectangle (region, &client_area);
/* Some applications might explicitly set their bounding region
* to the client area. Detect these cases, and throw out the
* bounding region in this case. */
if (cairo_region_contains_rectangle (region, &client_area) == CAIRO_REGION_OVERLAP_IN)
g_clear_pointer (&region, cairo_region_destroy);
}
meta_window_set_shape_region (window, region);
@ -2441,8 +2444,7 @@ meta_window_x11_client_message (MetaWindow *window,
{
meta_verbose ("WM_CHANGE_STATE client message, state: %ld\n",
event->xclient.data.l[0]);
if (event->xclient.data.l[0] == IconicState &&
window->has_minimize_func)
if (event->xclient.data.l[0] == IconicState)
meta_window_minimize (window);
return TRUE;

View File

@ -194,6 +194,7 @@ async_get_property_finish (xcb_connection_t *xcb_conn,
{
xcb_get_property_reply_t *reply;
xcb_generic_error_t *error;
int length;
reply = xcb_get_property_reply (xcb_conn, cookie, &error);
if (error)
@ -209,8 +210,15 @@ async_get_property_finish (xcb_connection_t *xcb_conn,
results->prop = NULL;
if (results->type != None)
results->prop = g_memdup (xcb_get_property_value (reply),
xcb_get_property_value_length (reply));
{
length = xcb_get_property_value_length (reply);
/* Leave room for a trailing '\0' since xcb doesn't return null-terminated
* strings
*/
results->prop = g_malloc (length + 1);
memcpy (results->prop, xcb_get_property_value (reply), length);
results->prop[length] = '\0';
}
free (reply);
return (results->prop != NULL);
@ -507,7 +515,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 +531,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;