Compare commits

..

62 Commits

Author SHA1 Message Date
3e511b9591 Bump version to 3.14.1
Update NEWS.
2014-10-14 20:26:31 +02:00
5664c703b7 screen: Always consider monitors with fullscreen windows "in-fullscreen"
Fullscreen windows look weird when they are overlapped by system chrome,
which currently happens when another window is stacked above. We used to
auto-minimize fullscreen windows in that case, which proved to be both
unreliable and unpopular. So instead, keep the system chrome hidden even
when the fullscreen window is not stacked at the top.

https://bugzilla.gnome.org/show_bug.cgi?id=693991
2014-10-14 18:42:38 +02:00
5c80c4b006 window-x11: Update the input region after setting the client rect
We clip the input region to the client rect, so the client rect should
be up to date before we fetch the input region.

This fixes popup windows not working in GTK+2 under Wayland.

We should also update the shape / input regions when the window is
reconfigured for a complete fix, so that making an O-R window bigger
doesn't confuse mutter, but let's leave that to a future commit.
2014-10-12 16:14:17 -07:00
22f91eba8d backend: Fix minor comment 2014-10-12 13:41:03 -07:00
d07e2f4090 workspace: fix crash when creating a new workspace with sticky windows that have struts
The constructor would collect windows that are sticky before initializing its state
which would lead to a crash in the case of windows with struts which trigger a work
area recalculation where mutter would assume, due to uninitialized state, that an
existing work area has to be freed.

https://bugzilla.gnome.org/show_bug.cgi?id=738384
2014-10-12 22:27:02 +02:00
cd32e4a68a meta-surface-actor-x11: Fix unredirect heuristic
Damage coordinates are relative to the drawable not to the screen. So we
have to check whether x and y are 0 and not window_rect.x/y otherwise the
herustic will never trigger for windows on monitors whos x and y are not 0.

https://bugzilla.gnome.org/show_bug.cgi?id=738271
2014-10-12 00:35:47 +02:00
4040a70781 wayland-keyboard: Send modifiers after the key event
The key event should be interpreted by clients with the modifier state
as it was before the event itself just as in X11 input events.
Achieving this in wayland is a matter of sending the key event first
and the modifiers after (if needed).

This isn't really specified in the wayland protocol but it matches
weston's behavior and should avoid corner cases in clients.

https://bugzilla.gnome.org/show_bug.cgi?id=738238
2014-10-10 18:12:23 +02:00
cb084cc841 build: Require clutter-egl-1.0 for native backend only
https://bugzilla.gnome.org/show_bug.cgi?id=738225
2014-10-09 20:03:31 +02:00
2deea6e0a3 events: Fix build without wayland
https://bugzilla.gnome.org/show_bug.cgi?id=738225
2014-10-09 20:03:30 +02:00
a116509301 meta-surface-actor-x11: Detatch the pixmap in window_decorated_notify
The window can change its decoration without changing its size.

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

Found by Jasper St. Pierre <jstpierre@mecheye.net>
2014-10-08 23:11:47 +02:00
ead79f834c Revert "wayland-pointer: Just use the pointer actor instead of doing a full repick"
This reverts commit 33acb5fea0.

The issue here is that the pointer actor does not actually get reset
when the actor's reactivity changes, so we end up with stale picks after
actors are destroyed.

I have a local patch to Clutter for this, but I don't have time to
submit it upstream, so let's just use the ugly code for now.
2014-10-08 13:43:57 -07:00
7e431bd6bc Revert "pointer: Repick after the focused surface is destroyed"
This reverts commit e496ed50d6.

This was incorrect. wl_surface_destructor actually does the full repick
-- doing it here is dangerous, because the destroy listeners actually
run *before* the destructor, not after, so the surface is still alive.
2014-10-08 12:38:56 -07:00
272e1fb296 MetaBackgroundActor: queue a redraw when the background changes
When the MetaBackground changes, queue the actor for redraw.
2014-10-08 15:03:02 -04:00
c39f18c2d4 wayland-keyboard: Don't send pressed keys on enter
We never want to send pressed keys to wayland clients on enter. The
protocol says that we should send them, presumably so that clients can
trigger their own key repeat routine in case they are given focus and
a key is physically pressed.

Unfortunately this causes some clients, in particular Xwayland, to
register key events that they really shouldn't handle, e.g. on an
Alt+Tab keybinding, where Alt is released before Tab, clients would
see Tab being pressed on enter followed by a key release event for
Tab, meaning that Tab would be processed by the client when it really
shouldn't.

Since the use case for the pressed keys array on enter seems weak to
us, we'll just fake that there are no pressed keys instead which
should be spec compliant even if it might not be true.

https://bugzilla.gnome.org/show_bug.cgi?id=727178
2014-10-08 15:26:28 +02:00
33acb5fea0 wayland-pointer: Just use the pointer actor instead of doing a full repick
The full repick is unnecessary -- Clutter already does it for us.
2014-10-07 21:30:15 -07:00
591718dc02 wayland: Clump the globals code together 2014-10-07 20:54:28 -07:00
b6127eeda4 wayland: Remove old comments 2014-10-07 20:52:57 -07:00
eeff1b8b02 wayland: Remove unused variable 2014-10-07 20:51:18 -07:00
354cc466af wayland: Make WaylandEventSource private 2014-10-07 20:50:57 -07:00
9f5c38d121 wayland: Make the MetaWaylandRegion type opaque 2014-10-07 20:44:19 -07:00
ead0e902ed wayland: Move MetaWaylandRegion into a new file as well 2014-10-07 20:44:18 -07:00
5d16194b03 wayland: Clean up a bit more 2014-10-07 20:42:27 -07:00
a74acf0ec2 wayland: Clean up more includes 2014-10-07 20:42:27 -07:00
3044cfb7bf wayland-surface: Clean up includes 2014-10-07 20:42:27 -07:00
f658740043 wayland: Move some buffer manipulation functions to meta-wayland-buffer 2014-10-07 20:42:27 -07:00
c1613a16c0 wayland: Put the MetaWaylandBuffer implementation in a new file 2014-10-07 20:42:27 -07:00
8e85015f91 default: Adjust the default background
Getting a bit tired of green...
2014-10-07 20:42:26 -07:00
f127ee3bde wayland-surface: Fix a build coming from a bad rebase 2014-10-07 12:09:52 -07:00
acd928044f wayland-surface: Remove MetaWaylandSurfaceExtension
It only contained a pointer to a wl_resource, which isn't much of
value. Just replace it with the wl_resource instead. Any future private
data should be handled by our future role system.
2014-10-07 11:23:45 -07:00
4ef2f2ce09 wayland-surface: Remove create_surface_extension and friends
This function has a lot of parameters, and doesn't do much in the way of
boilerplate. It's a lot simpler to hand-code.
2014-10-07 11:23:45 -07:00
bc81736e6b wayland-surface: Rename the subsurface extension to wl_subsurface
To match the interface name.
2014-10-07 11:23:45 -07:00
49092397f2 wayland-surface: Group MetaWaylandSurface members logically
And add comments so that we know what's what. This cleans up the struct.
2014-10-07 11:23:45 -07:00
97705d3cfe wayland-surface: Move wl_surface.frame above role-specific stuff
The role-specific stuff will soon be part of a set_role callback set on
the surface itself.
2014-10-07 11:23:44 -07:00
0364ea9140 wayland-surface: Apply the surface scale only if needed
There's no need to call scale_texture on every commit.
2014-10-07 11:23:31 -07:00
c0bdb3018b display: Do not include unmanaging windows in list_windows()
There's a small window before a window that is being unmanaged is
unregistered with the display. The MetaScreen::window-left-monitor
and MetaWorkspace::window-removed emissions fall right into that
window, so code that runs in that time may well be out of our
control; we can make sure that the method it can use to get an
updated list of windows no longer contains the destroyed window
though, which is a much better option than expecting everyone to
filter the list themselves.
2014-10-07 20:09:09 +02:00
924eaac358 Updated Latvian translation 2014-10-07 20:42:42 +03:00
a9f5a5661f Updated Latvian translation 2014-10-07 20:40:14 +03:00
9c589b6798 wayland: Ensure drag surface offset changes update the DnD actor 2014-10-06 19:39:43 -07:00
113be01ce8 wayland: Use a MetaDnDActor for the DnD icon surface
The actor is updated on DnD grab motion events, properly notified
when dragging finishes, and destroyed if the client/surface disappear
below its feet.
2014-10-06 19:39:43 -07:00
28e59c5a8f compositor: Add MetaDnDActor
This actor is a subclass of MetaFeedbackActor that additionally
implements the "drag failed" animation, snapping back to the drag
origin position in a surface.
2014-10-06 19:39:43 -07:00
b588baf9f5 compositor: Add MetaFeedbackActor
This actor is a non-reactive container that autoembeds itself into
the feedback window group in the compositor. The API is meant to
help on creating things attached to pointer/touchpoints, with an
X/Y attachment offset, and following the position of certain events.
2014-10-06 19:39:43 -07:00
9a825d9bee compositor: Add a "feedback" window group
Although not strictly a window group... This ClutterActor is
meant to stay always on top, and only show non-reactive actors
created by Mutter itself. Two possible usecases for this layer
are DnD surfaces, and touch spots.

We might also want to move cursors out of an overlay in MetaStage
into here at some point.
2014-10-06 19:39:43 -07:00
f211b3ec90 wayland: Store whether the wl_data_source has a target selected
It will be useful to check whether DnD is going to fail or not.
2014-10-06 19:39:43 -07:00
0510c3a621 wayland: Keep track of the origin surface and drag point on DnD
Keeping track of the surface will be necessary in case it is destroyed
during DnD, and the coordinates will be useful when figuring out the
snap back coordinates.
2014-10-06 19:39:43 -07:00
18db5d0799 data-device: Store the current drag grab
And bail out if any further start_drag() is attempted.
2014-10-06 19:39:42 -07:00
c061e26da5 wayland: Record the offset position
This is needed for DND surfaces. We should probably test to see if it's
used for cursor surfaces at all.
2014-10-06 19:39:42 -07:00
166668adc4 window: Remove duplicate case value 2014-10-06 19:39:38 -07:00
ec797b055d window: Mark all override-redirect window types as appears-focused 2014-10-06 19:30:12 -07:00
082cc9c83a wayland: Immediately give keyboard focus to Wayland popups 2014-10-06 17:05:23 -07:00
993bec37d7 window: Ensure that popup window types propagate their focus appearance
In Wayland, popup window types are not override-redirect, and thus can
steal window focus away from their parent window when clicked on.

This means that we need to make sure their appearance is properly
propagated to the parent windows so the parent windows don't lose their
focus while they're propagated.
2014-10-06 17:01:08 -07:00
e496ed50d6 pointer: Repick after the focused surface is destroyed
Having a null focus is incorrect -- we want to pick the surface that's
under the new pointer position.
2014-10-06 16:30:09 -07:00
a127d05790 pointer: Make sure to update the focus after ending a grab
Otherwise, we might not reset it after the grab has ended.
2014-10-06 16:19:30 -07:00
607730e96c pointer: Fix the behavior of the pointer under DND
When grabbing with DND, we need to leave the pointer alone and
under the client's control. The code here was a bit messy before about
when it unset the window cursor -- it did it whenever there was no
current surface after repicking, which is a bit wrong, since it will
fire during a drag grab.

Move the check for this to update_cursor_surface, which is our standard
"sync" API for this, and then call update_cursor_surface after we set
the focus.
2014-10-06 15:48:42 -07:00
9203db0655 pointer: Don't fizzle out surface changes too soon
During a DND grab, pointer->focus_surface is NULL, since the wl_pointer
doesn't have any focused surface (it's in drag mode). In this case, the
drag interface has control of the focus, and when dragging into a NULL
surface, drag_grab_focus won't get called, properly detaching it from
the previous surface.

Let the interface->focus implementation do the fizzling out.

In the future, we should split out wl_pointer's implementation
(pointer->focus_surface) from the Wayland side of the generic pointer
wrapper (pointer->current) and use our event routing system to determine
or similar whether it should go to wl_pointer or wl_data_device.
2014-10-06 14:31:16 -07:00
64d40792c4 Updated Italian translation 2014-10-05 13:41:57 +00:00
e7356917b0 meta-monitor-manager-xrandr: Simplify handle_xevent
The code here was a bit messy with the addition of
hotplug_mode_update, and the comments were a bit confusing and
inaccurate. Clean it up and comment it a bit better to make the flow and
intention more clear.
2014-10-03 15:12:00 -06:00
fa58752276 backend-native: Handle keyboard repeat settings
We need to tell clutter's evdev backend about the desktop's key repeat
settings so that our own key bindings event processing and
gnome-shell's chrome widgets get their fake key events for continuous
key press as they expect.

Note that the wayland frontend filters out these events and thus
wayland clients do not see them as specced.

https://bugzilla.gnome.org/show_bug.cgi?id=728055
2014-10-03 18:31:44 +02:00
478b75e803 backend-x11: Re-upload keymap when new keyboard devices are added
The X server applies a default keymap to hotplugged keyboard
devices. To enforce our current settings we must re-upload the keymap
when a new keyboard shows up.

Note that setting the VCK keymap causes the server to propagate it
to all slave keyboard devices.

https://bugzilla.gnome.org/show_bug.cgi?id=737673
2014-10-02 19:14:03 +02:00
492a1b244f Revert "display: Don't put minimized windows at the back of alt-tab"
This reverts commit 7e61ef0936.

https://bugzilla.gnome.org/show_bug.cgi?id=705177
2014-10-01 17:29:15 -06:00
5d8ff2e34d screen: Remove auto-minimization "feature"
https://bugzilla.gnome.org/show_bug.cgi?id=705177
2014-10-01 17:29:02 -06:00
310083aeb2 keybindings: Remove special-case code for reversing automatically
Since we now directly expose the reverses bindings directly, we
don't have to have this special-case in do_choose_window.

More importantly, if the backwards binding is pressed and has the Shift
key included, this will actually revert it

This doesn't matter for Alt-Tab in gnome-shell, which already replaces
it with a better Alt-Tab replacement, but it does matter for Alt-Esc,
which switches between windows directly.
2014-10-01 16:51:45 -06:00
0faa900207 frames: Make sure to initialize button_state
Otherwise, we're comparing with uninitialized memory. Spotted by
valgrind.
2014-09-30 15:16:07 -06:00
47 changed files with 2723 additions and 2354 deletions

26
NEWS
View File

@ -1,3 +1,29 @@
3.14.1
======
* Fix move-titlebar-onscreen function [Florian; #736915]
* Fix stacking of the guard window [Owen; #737233]
* Fix keycode lookup for non-default layouts [Rui; #737134]
* Fix workspaces-only-on-primary handling [Florian; #737178]
* Don't unstick sticky windows on workspace removal [Florian; #737625]
* Do not auto-minimize fullscreen windows [Jasper; #705177]
* Upload keymap to newly added keyboard devices [Rui; #737673]
* Apply keyboard repeat settings [Rui; #728055]
* Don't send pressed keys on enter [Rui; #727178]
* Fix build without wayland/native [Rico; #738225]
* Send modifiers after the key event [Rui; #738238]
* Fix unredirect heuristic [Adel; #738271]
* Do not show system chrome over fullscreen windows [Florian; #693991]
* Misc. bug fixes [Florian, Adel, Tom; #737135, #737581, #738146, #738384]
Contributors:
Tom Beckmann, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner,
Jasper St. Pierre, Rico Tzschichholz, Owen W. Taylor
Translations:
Krishnababu Krothapalli [te], Мирослав Николић [sr, sr@latin],
Alexander Shopov [bg], Saibal Ray [bn_IN], Milo Casagrande [it],
Rūdolfs Mazurs [lv]
3.14.0
======
* Fix placement of popup windows on wayland [Jasper; #736812]

View File

@ -2,7 +2,7 @@ AC_PREREQ(2.62)
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [14])
m4_define([mutter_micro_version], [0])
m4_define([mutter_micro_version], [1])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@ -77,7 +77,6 @@ MUTTER_PC_MODULES="
cairo >= 1.10.0
gsettings-desktop-schemas >= 3.7.3
$CLUTTER_PACKAGE >= 1.19.5
clutter-egl-1.0
cogl-1.0 >= 1.17.1
gbm >= 10.3
upower-glib >= 0.99.0
@ -202,7 +201,7 @@ AC_SUBST(XWAYLAND_PATH)
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [libdrm libsystemd libinput], [have_native_backend=yes], [have_native_backend=no])
PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [clutter-egl-1.0 libdrm libsystemd libinput], [have_native_backend=yes], [have_native_backend=no])
if test $have_native_backend = yes; then
AC_DEFINE([HAVE_NATIVE_BACKEND],[1],[Define if you want to enable the native (KMS) backend based on systemd])
fi

1346
po/it.po

File diff suppressed because it is too large Load Diff

1301
po/lv.po

File diff suppressed because it is too large Load Diff

View File

@ -109,6 +109,10 @@ libmutter_la_SOURCES = \
compositor/meta-background-group.c \
compositor/meta-cullable.c \
compositor/meta-cullable.h \
compositor/meta-dnd-actor.c \
compositor/meta-dnd-actor-private.h \
compositor/meta-feedback-actor.c \
compositor/meta-feedback-actor-private.h \
compositor/meta-module.c \
compositor/meta-module.h \
compositor/meta-plugin.c \
@ -230,6 +234,10 @@ libmutter_la_SOURCES += \
wayland/meta-xwayland.c \
wayland/meta-xwayland.h \
wayland/meta-xwayland-private.h \
wayland/meta-wayland-buffer.c \
wayland/meta-wayland-buffer.h \
wayland/meta-wayland-region.c \
wayland/meta-wayland-region.h \
wayland/meta-wayland-data-device.c \
wayland/meta-wayland-data-device.h \
wayland/meta-wayland-keyboard.c \

View File

@ -35,21 +35,13 @@
#include "meta-stage.h"
typedef struct
{
CoglTexture *texture;
MetaRectangle current_rect;
int current_x, current_y;
} MetaCursorLayer;
struct _MetaCursorRendererPrivate
{
MetaCursorLayer core_layer;
MetaCursorLayer dnd_layer;
int current_x, current_y;
MetaRectangle current_rect;
MetaCursorReference *displayed_cursor;
int dnd_surface_offset_x, dnd_surface_offset_y;
gboolean cursor_handled_by_backend;
gboolean handled_by_backend;
};
typedef struct _MetaCursorRendererPrivate MetaCursorRendererPrivate;
@ -67,19 +59,12 @@ queue_redraw (MetaCursorRenderer *renderer)
if (!stage)
return;
/* Pointer cursor */
if (!priv->cursor_handled_by_backend)
texture = priv->core_layer.texture;
if (priv->displayed_cursor && !priv->handled_by_backend)
texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, NULL, NULL);
else
texture = NULL;
meta_stage_set_cursor (META_STAGE (stage), texture,
&priv->core_layer.current_rect);
/* DnD surface */
meta_stage_set_dnd_surface (META_STAGE (stage),
priv->dnd_layer.texture,
&priv->dnd_layer.current_rect);
meta_stage_set_cursor (META_STAGE (stage), texture, &priv->current_rect);
}
static gboolean
@ -100,76 +85,46 @@ meta_cursor_renderer_init (MetaCursorRenderer *renderer)
}
static void
update_layer (MetaCursorRenderer *renderer,
MetaCursorLayer *layer,
CoglTexture *texture,
int offset_x,
int offset_y)
update_cursor (MetaCursorRenderer *renderer)
{
layer->texture = texture;
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
gboolean handled_by_backend;
gboolean should_redraw = FALSE;
if (layer->texture)
if (priv->displayed_cursor)
{
layer->current_rect.x = layer->current_x + offset_x;
layer->current_rect.y = layer->current_y + offset_y;
layer->current_rect.width = cogl_texture_get_width (layer->texture);
layer->current_rect.height = cogl_texture_get_height (layer->texture);
CoglTexture *texture;
int hot_x, hot_y;
texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, &hot_x, &hot_y);
priv->current_rect.x = priv->current_x - hot_x;
priv->current_rect.y = priv->current_y - hot_y;
priv->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (texture));
priv->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (texture));
}
else
{
layer->current_rect.x = 0;
layer->current_rect.y = 0;
layer->current_rect.width = 0;
layer->current_rect.height = 0;
priv->current_rect.x = 0;
priv->current_rect.y = 0;
priv->current_rect.width = 0;
priv->current_rect.height = 0;
}
}
static void
emit_update_cursor (MetaCursorRenderer *renderer,
gboolean force)
{
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
gboolean handled_by_backend, should_redraw = FALSE;
handled_by_backend = META_CURSOR_RENDERER_GET_CLASS (renderer)->update_cursor (renderer);
if (handled_by_backend != priv->cursor_handled_by_backend)
if (handled_by_backend != priv->handled_by_backend)
{
priv->cursor_handled_by_backend = handled_by_backend;
priv->handled_by_backend = handled_by_backend;
should_redraw = TRUE;
}
if (force || !handled_by_backend || priv->dnd_layer.texture)
if (!handled_by_backend)
should_redraw = TRUE;
if (should_redraw)
queue_redraw (renderer);
}
static void
update_cursor (MetaCursorRenderer *renderer)
{
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
CoglTexture *texture;
int hot_x, hot_y;
/* Cursor layer */
if (priv->displayed_cursor)
{
texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor,
&hot_x, &hot_y);
}
else
{
texture = NULL;
hot_x = 0;
hot_y = 0;
}
update_layer (renderer, &priv->core_layer, texture, -hot_x, -hot_y);
emit_update_cursor (renderer, FALSE);
}
MetaCursorRenderer *
meta_cursor_renderer_new (void)
{
@ -189,23 +144,6 @@ meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer,
update_cursor (renderer);
}
void
meta_cursor_renderer_set_dnd_surface (MetaCursorRenderer *renderer,
CoglTexture *texture,
int offset_x,
int offset_y)
{
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
g_assert (meta_is_wayland_compositor ());
priv->dnd_surface_offset_x = offset_x;
priv->dnd_surface_offset_y = offset_y;
update_layer (renderer, &priv->dnd_layer, texture, offset_x, offset_y);
emit_update_cursor (renderer, TRUE);
}
void
meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
int x, int y)
@ -214,46 +152,12 @@ meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
g_assert (meta_is_wayland_compositor ());
priv->core_layer.current_x = x;
priv->core_layer.current_y = y;
priv->current_x = x;
priv->current_y = y;
update_cursor (renderer);
}
void
meta_cursor_renderer_set_dnd_surface_position (MetaCursorRenderer *renderer,
int x,
int y)
{
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
g_assert (meta_is_wayland_compositor ());
priv->dnd_layer.current_x = x;
priv->dnd_layer.current_y = y;
update_layer (renderer, &priv->dnd_layer, priv->dnd_layer.texture,
priv->dnd_surface_offset_x, priv->dnd_surface_offset_y);
emit_update_cursor (renderer, FALSE);
}
void
meta_cursor_renderer_dnd_failed (MetaCursorRenderer *renderer,
int dest_x,
int dest_y)
{
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
MetaBackend *backend = meta_get_backend ();
ClutterActor *stage = meta_backend_get_stage (backend);
g_assert (meta_is_wayland_compositor ());
if (priv->dnd_layer.texture)
meta_stage_dnd_failed (META_STAGE (stage),
dest_x + priv->dnd_surface_offset_x,
dest_y + priv->dnd_surface_offset_y);
}
MetaCursorReference *
meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer)
{
@ -267,5 +171,5 @@ meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer)
{
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
return &priv->core_layer.current_rect;
return &priv->current_rect;
}

View File

@ -67,14 +67,4 @@ void meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
MetaCursorReference * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer);
const MetaRectangle * meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer);
void meta_cursor_renderer_set_dnd_surface (MetaCursorRenderer *renderer,
CoglTexture *texture,
int offset_x,
int offset_y);
void meta_cursor_renderer_set_dnd_surface_position (MetaCursorRenderer *renderer,
int x, int y);
void meta_cursor_renderer_dnd_failed (MetaCursorRenderer *renderer,
int dest_x, int dest_y);
#endif /* META_CURSOR_RENDERER_H */

View File

@ -62,20 +62,10 @@ void meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
void meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker);
void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor);
void meta_cursor_tracker_set_dnd_surface (MetaCursorTracker *tracker,
CoglTexture *texture,
int offset_x,
int offset_y);
void meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
int new_x,
int new_y);
void meta_cursor_tracker_update_dnd_surface_position (MetaCursorTracker *tracker,
int new_x,
int new_y);
void meta_cursor_tracker_dnd_failed (MetaCursorTracker *tracker,
int dest_x,
int dest_y);
MetaCursorReference * meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker);

View File

@ -358,28 +358,6 @@ meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
sync_cursor (tracker);
}
void
meta_cursor_tracker_set_dnd_surface (MetaCursorTracker *tracker,
CoglTexture *texture,
int offset_x,
int offset_y)
{
g_assert (meta_is_wayland_compositor ());
meta_cursor_renderer_set_dnd_surface (tracker->renderer, texture,
offset_x, offset_y);
}
void
meta_cursor_tracker_dnd_failed (MetaCursorTracker *tracker,
int dest_x,
int dest_y)
{
g_assert (meta_is_wayland_compositor ());
meta_cursor_renderer_dnd_failed (tracker->renderer, dest_x, dest_y);
}
void
meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
int new_x,
@ -390,17 +368,6 @@ meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
meta_cursor_renderer_set_position (tracker->renderer, new_x, new_y);
}
void
meta_cursor_tracker_update_dnd_surface_position (MetaCursorTracker *tracker,
int new_x,
int new_y)
{
g_assert (meta_is_wayland_compositor ());
meta_cursor_renderer_set_dnd_surface_position (tracker->renderer,
new_x, new_y);
}
static void
get_pointer_position_gdk (int *x,
int *y,

View File

@ -28,8 +28,6 @@
#include <meta/meta-backend.h>
#include <meta/util.h>
#define DRAG_FAILED_MSECS 500
typedef struct {
gboolean enabled;
@ -41,20 +39,8 @@ typedef struct {
gboolean previous_is_valid;
} MetaOverlay;
typedef struct {
MetaStage *stage;
MetaOverlay overlay;
ClutterTimeline *timeline;
int orig_x;
int orig_y;
int dest_x;
int dest_y;
} MetaDragFailedAnimation;
struct _MetaStagePrivate {
MetaOverlay dnd_overlay;
MetaOverlay cursor_overlay;
GList *drag_failed_animations;
};
typedef struct _MetaStagePrivate MetaStagePrivate;
@ -68,15 +54,6 @@ meta_overlay_init (MetaOverlay *overlay)
overlay->pipeline = cogl_pipeline_new (ctx);
}
static void
meta_overlay_copy (MetaOverlay *src,
MetaOverlay *dst)
{
*dst = *src;
dst->pipeline = cogl_pipeline_copy (src->pipeline);
dst->texture = src->texture;
}
static void
meta_overlay_free (MetaOverlay *overlay)
{
@ -135,7 +112,6 @@ meta_stage_finalize (GObject *object)
MetaStage *stage = META_STAGE (object);
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
meta_overlay_free (&priv->dnd_overlay);
meta_overlay_free (&priv->cursor_overlay);
}
@ -144,18 +120,9 @@ meta_stage_paint (ClutterActor *actor)
{
MetaStage *stage = META_STAGE (actor);
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
MetaDragFailedAnimation *animation;
GList *l;
CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor);
for (l = priv->drag_failed_animations; l; l = l->next)
{
animation = l->data;
meta_overlay_paint (&animation->overlay);
}
meta_overlay_paint (&priv->dnd_overlay);
meta_overlay_paint (&priv->cursor_overlay);
}
@ -175,7 +142,6 @@ meta_stage_init (MetaStage *stage)
{
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
meta_overlay_init (&priv->dnd_overlay);
meta_overlay_init (&priv->cursor_overlay);
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), FALSE);
@ -217,19 +183,6 @@ queue_redraw_for_overlay (MetaStage *stage,
}
}
void
meta_stage_set_dnd_surface (MetaStage *stage,
CoglTexture *texture,
MetaRectangle *rect)
{
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
g_assert (meta_is_wayland_compositor ());
meta_overlay_set (&priv->dnd_overlay, texture, rect);
queue_redraw_for_overlay (stage, &priv->dnd_overlay);
}
void
meta_stage_set_cursor (MetaStage *stage,
CoglTexture *texture,
@ -242,84 +195,3 @@ meta_stage_set_cursor (MetaStage *stage,
meta_overlay_set (&priv->cursor_overlay, texture, rect);
queue_redraw_for_overlay (stage, &priv->cursor_overlay);
}
static void
drag_failed_animation_frame_cb (ClutterTimeline *timeline,
guint pos,
gpointer user_data)
{
MetaDragFailedAnimation *data = user_data;
gdouble progress = clutter_timeline_get_progress (timeline);
CoglColor color;
cogl_color_init_from_4f (&color, 0, 0, 0, 1 - progress);
cogl_pipeline_set_layer_combine_constant (data->overlay.pipeline, 0, &color);
data->overlay.current_rect.x = data->orig_x + ((data->dest_x - data->orig_x) * progress);
data->overlay.current_rect.y = data->orig_y + ((data->dest_y - data->orig_y) * progress);
queue_redraw_for_overlay (data->stage, &data->overlay);
}
static void
meta_drag_failed_animation_free (MetaDragFailedAnimation *data)
{
MetaStage *stage = data->stage;
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
priv->drag_failed_animations =
g_list_remove (priv->drag_failed_animations, data);
g_object_unref (data->timeline);
meta_overlay_free (&data->overlay);
g_slice_free (MetaDragFailedAnimation, data);
}
static MetaDragFailedAnimation *
meta_drag_failed_animation_new (MetaStage *stage,
int dest_x,
int dest_y)
{
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
MetaDragFailedAnimation *data;
data = g_slice_new0 (MetaDragFailedAnimation);
data->stage = stage;
data->orig_x = priv->dnd_overlay.current_rect.x;
data->orig_y = priv->dnd_overlay.current_rect.y;
data->dest_x = dest_x;
data->dest_y = dest_y;
meta_overlay_copy (&priv->dnd_overlay, &data->overlay);
data->timeline = clutter_timeline_new (DRAG_FAILED_MSECS);
clutter_timeline_set_progress_mode (data->timeline, CLUTTER_EASE_OUT_CUBIC);
g_signal_connect (data->timeline, "new-frame",
G_CALLBACK (drag_failed_animation_frame_cb), data);
g_signal_connect_swapped (data->timeline, "completed",
G_CALLBACK (meta_drag_failed_animation_free), data);
priv->drag_failed_animations =
g_list_prepend (priv->drag_failed_animations, data);
cogl_pipeline_set_layer_combine (data->overlay.pipeline, 0,
"RGBA = MODULATE (TEXTURE, CONSTANT[A])",
NULL);
return data;
}
void
meta_stage_dnd_failed (MetaStage *stage,
int dest_x,
int dest_y)
{
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
MetaDragFailedAnimation *data;
g_assert (meta_is_wayland_compositor ());
if (!priv->dnd_overlay.enabled)
return;
data = meta_drag_failed_animation_new (stage, dest_x, dest_y);
clutter_timeline_start (data->timeline);
}

View File

@ -51,18 +51,9 @@ GType meta_stage_get_type (void) G_GNUC_CONST;
ClutterActor *meta_stage_new (void);
void meta_stage_set_dnd_surface (MetaStage *stage,
CoglTexture *texture,
MetaRectangle *rect);
void meta_stage_set_cursor (MetaStage *stage,
CoglTexture *texture,
MetaRectangle *rect);
void meta_stage_dnd_failed (MetaStage *stage,
int dest_x,
int dest_y);
G_END_DECLS
#endif /* META_STAGE_H */

View File

@ -36,11 +36,24 @@
struct _MetaBackendNativePrivate
{
MetaLauncher *launcher;
GSettings *keyboard_settings;
};
typedef struct _MetaBackendNativePrivate MetaBackendNativePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendNative, meta_backend_native, META_TYPE_BACKEND);
static void
meta_backend_native_finalize (GObject *object)
{
MetaBackendNative *native = META_BACKEND_NATIVE (object);
MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native);
g_clear_object (&priv->keyboard_settings);
G_OBJECT_CLASS (meta_backend_native_parent_class)->finalize (object);
}
/*
* The pointer constrain code is mostly a rip-off of the XRandR code from Xorg.
* (from xserver/randr/rrcrtc.c, RRConstrainCursorHarder)
@ -142,15 +155,46 @@ pointer_constrain_callback (ClutterInputDevice *device,
constrain_all_screen_monitors(device, monitors, n_monitors, new_x, new_y);
}
static void
set_keyboard_repeat (MetaBackendNative *native)
{
MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native);
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
gboolean repeat;
unsigned int delay, interval;
repeat = g_settings_get_boolean (priv->keyboard_settings, "repeat");
delay = g_settings_get_uint (priv->keyboard_settings, "delay");
interval = g_settings_get_uint (priv->keyboard_settings, "repeat-interval");
clutter_evdev_set_keyboard_repeat (manager, repeat, delay, interval);
}
static void
keyboard_settings_changed (GSettings *settings,
const char *key,
gpointer data)
{
MetaBackendNative *native = data;
set_keyboard_repeat (native);
}
static void
meta_backend_native_post_init (MetaBackend *backend)
{
MetaBackendNative *native = META_BACKEND_NATIVE (backend);
MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native);
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
META_BACKEND_CLASS (meta_backend_native_parent_class)->post_init (backend);
clutter_evdev_set_pointer_constrain_callback (manager, pointer_constrain_callback,
NULL, NULL);
priv->keyboard_settings = g_settings_new ("org.gnome.settings-daemon.peripherals.keyboard");
g_signal_connect (priv->keyboard_settings, "changed",
G_CALLBACK (keyboard_settings_changed), native);
set_keyboard_repeat (native);
}
static MetaIdleMonitor *
@ -236,6 +280,9 @@ static void
meta_backend_native_class_init (MetaBackendNativeClass *klass)
{
MetaBackendClass *backend_class = META_BACKEND_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_backend_native_finalize;
backend_class->post_init = meta_backend_native_post_init;
backend_class->create_idle_monitor = meta_backend_native_create_idle_monitor;
@ -271,7 +318,7 @@ meta_activate_vt (int vt, GError **error)
* meta_activate_session:
*
* Tells mutter to activate the session. When mutter is a
* Wayland compositor, this tells logind to switch over to
* display server, this tells logind to switch over to
* the new session.
*/
gboolean

View File

@ -65,9 +65,14 @@ struct _MetaBackendX11Private
uint8_t xkb_error_base;
struct xkb_keymap *keymap;
gchar *keymap_layouts;
gchar *keymap_variants;
gchar *keymap_options;
};
typedef struct _MetaBackendX11Private MetaBackendX11Private;
static void apply_keymap (MetaBackendX11 *x11);
G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendX11, meta_backend_x11, META_TYPE_BACKEND);
static void
@ -326,6 +331,17 @@ take_touch_grab (MetaBackend *backend)
False, &mask, 1, &mods);
}
static void
on_device_added (ClutterDeviceManager *device_manager,
ClutterInputDevice *device,
gpointer user_data)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (user_data);
if (clutter_input_device_get_device_type (device) == CLUTTER_KEYBOARD_DEVICE)
apply_keymap (x11);
}
static void
meta_backend_x11_post_init (MetaBackend *backend)
{
@ -376,6 +392,9 @@ meta_backend_x11_post_init (MetaBackend *backend)
meta_fatal ("X server doesn't have the XKB extension, version %d.%d or newer\n",
XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION);
g_signal_connect_object (clutter_device_manager_get_default (), "device-added",
G_CALLBACK (on_device_added), backend, 0);
META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend);
}
@ -560,21 +579,22 @@ upload_xkb_description (Display *xdisplay,
}
static void
meta_backend_x11_set_keymap (MetaBackend *backend,
const char *layouts,
const char *variants,
const char *options)
apply_keymap (MetaBackendX11 *x11)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
XkbRF_RulesRec *xkb_rules;
XkbRF_VarDefsRec xkb_var_defs = { 0 };
gchar *rules_file_path;
if (!priv->keymap_layouts ||
!priv->keymap_variants ||
!priv->keymap_options)
return;
get_xkbrf_var_defs (priv->xdisplay,
layouts,
variants,
options,
priv->keymap_layouts,
priv->keymap_variants,
priv->keymap_options,
&rules_file_path,
&xkb_var_defs);
@ -598,6 +618,25 @@ meta_backend_x11_set_keymap (MetaBackend *backend,
g_free (rules_file_path);
}
static void
meta_backend_x11_set_keymap (MetaBackend *backend,
const char *layouts,
const char *variants,
const char *options)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
g_free (priv->keymap_layouts);
priv->keymap_layouts = g_strdup (layouts);
g_free (priv->keymap_variants);
priv->keymap_variants = g_strdup (variants);
g_free (priv->keymap_options);
priv->keymap_options = g_strdup (options);
apply_keymap (x11);
}
static struct xkb_keymap *
meta_backend_x11_get_keymap (MetaBackend *backend)
{

View File

@ -1075,6 +1075,7 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
MetaMonitorMode *old_modes;
unsigned int n_old_outputs, n_old_modes;
gboolean new_config;
gboolean applied_config = FALSE;
if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
return FALSE;
@ -1091,39 +1092,32 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
manager->serial++;
meta_monitor_manager_xrandr_read_current (manager);
new_config = manager_xrandr->resources->timestamp >=
manager_xrandr->resources->configTimestamp;
if (meta_monitor_manager_has_hotplug_mode_update (manager))
new_config = manager_xrandr->resources->timestamp >= manager_xrandr->resources->configTimestamp;
/* If this is the X server telling us we set a new configuration,
* we can simply short-cut to rebuilding our logical configuration.
*/
if (new_config || meta_monitor_config_match_current (manager->config, manager))
{
/* Check if the current intended configuration is a result of an
XRandR call. Otherwise, hotplug_mode_update tells us to get
a new preferred mode on hotplug events to handle dynamic
guest resizing. */
if (new_config)
meta_monitor_manager_xrandr_rebuild_derived (manager);
else
meta_monitor_config_make_default (manager->config, manager);
}
else
{
/* Check if the current intended configuration has the same outputs
as the new real one, or if the event is a result of an XRandR call.
If so, we can go straight to rebuild the logical config and tell
the outside world.
Otherwise, this event was caused by hotplug, so give a chance to
MetaMonitorConfig.
Note that we need to check both the timestamps and the list of
outputs, because the X server might emit spurious events with new
configTimestamps (bug 702804), and the driver may have changed
the EDID for some other reason (old qxl and vbox drivers). */
if (new_config || meta_monitor_config_match_current (manager->config, manager))
meta_monitor_manager_xrandr_rebuild_derived (manager);
else if (!meta_monitor_config_apply_stored (manager->config, manager))
meta_monitor_config_make_default (manager->config, manager);
meta_monitor_manager_xrandr_rebuild_derived (manager);
goto out;
}
/* If the monitor has hotplug_mode_update (which is used by VMs), don't bother
* applying our stored configuration, because it's likely the user just resizing
* the window.
*/
if (!meta_monitor_manager_has_hotplug_mode_update (manager))
{
if (meta_monitor_config_apply_stored (manager->config, manager))
applied_config = TRUE;
}
/* If we haven't applied any configuration, apply the default configuration. */
if (!applied_config)
meta_monitor_config_make_default (manager->config, manager);
out:
meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
g_free (old_crtcs);

View File

@ -23,7 +23,7 @@ struct _MetaCompositor
guint server_time_is_monotonic_time : 1;
guint no_mipmaps : 1;
ClutterActor *stage, *window_group, *top_window_group;
ClutterActor *stage, *window_group, *top_window_group, *feedback_group;
ClutterActor *background_actor;
GList *windows;
Window output;

View File

@ -185,6 +185,19 @@ meta_get_top_window_group_for_screen (MetaScreen *screen)
return compositor->top_window_group;
}
/**
* meta_get_feedback_group_for_screen:
* @screen: a #MetaScreen
*
* Returns: (transfer none): The feedback group corresponding to @screen
*/
ClutterActor *
meta_get_feedback_group_for_screen (MetaScreen *screen)
{
MetaCompositor *compositor = get_compositor_for_screen (screen);
return compositor->feedback_group;
}
/**
* meta_get_window_actors:
* @screen: a #MetaScreen
@ -478,9 +491,11 @@ meta_compositor_manage (MetaCompositor *compositor)
compositor->window_group = meta_window_group_new (screen);
compositor->top_window_group = meta_window_group_new (screen);
compositor->feedback_group = meta_window_group_new (screen);
clutter_actor_add_child (compositor->stage, compositor->window_group);
clutter_actor_add_child (compositor->stage, compositor->top_window_group);
clutter_actor_add_child (compositor->stage, compositor->feedback_group);
if (meta_is_wayland_compositor ())
{

View File

@ -708,6 +708,7 @@ on_background_changed (MetaBackground *background,
MetaBackgroundActor *self)
{
invalidate_pipeline (self, CHANGED_BACKGROUND);
clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
}
void

View File

@ -0,0 +1,64 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* meta-dnd-actor-private.h: Actor for painting the DnD surface
*
* Copyright 2014 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#ifndef META_DND_ACTOR_PRIVATE_H
#define META_DND_ACTOR_PRIVATE_H
#include "meta-feedback-actor-private.h"
/**
* MetaDnDActor:
*
* This class handles the rendering of the DnD surface
*/
#define META_TYPE_DND_ACTOR (meta_dnd_actor_get_type ())
#define META_DND_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DND_ACTOR, MetaDnDActor))
#define META_DND_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DND_ACTOR, MetaDnDActorClass))
#define META_IS_DND_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DND_ACTOR))
#define META_IS_DND_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DND_ACTOR))
#define META_DND_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DND_ACTOR, MetaDnDActorClass))
typedef struct _MetaDnDActor MetaDnDActor;
typedef struct _MetaDnDActorClass MetaDnDActorClass;
struct _MetaDnDActorClass
{
/*< private >*/
MetaFeedbackActorClass parent_class;
};
struct _MetaDnDActor
{
MetaFeedbackActor parent;
};
GType meta_dnd_actor_get_type (void);
ClutterActor *meta_dnd_actor_new (ClutterActor *drag_origin,
int start_x,
int start_y);
void meta_dnd_actor_drag_finish (MetaDnDActor *self,
gboolean success);
#endif /* META_DND_ACTOR_PRIVATE_H */

View File

@ -0,0 +1,231 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2014 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
/**
* SECTION:meta-dnd-actor
* @title: MetaDnDActor
* @short_description: Actor for painting the drag and drop surface
*
*/
#include <config.h>
#include <clutter/clutter.h>
#include "meta-dnd-actor-private.h"
#define DRAG_FAILED_DURATION 500
enum {
PROP_DRAG_ORIGIN = 1,
PROP_DRAG_START_X,
PROP_DRAG_START_Y
};
typedef struct _MetaDnDActorPrivate MetaDnDActorPrivate;
struct _MetaDnDActorPrivate
{
ClutterActor *drag_origin;
int drag_start_x;
int drag_start_y;
};
G_DEFINE_TYPE_WITH_PRIVATE (MetaDnDActor, meta_dnd_actor, META_TYPE_FEEDBACK_ACTOR)
static void
meta_dnd_actor_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaDnDActor *self = META_DND_ACTOR (object);
MetaDnDActorPrivate *priv = meta_dnd_actor_get_instance_private (self);
switch (prop_id)
{
case PROP_DRAG_ORIGIN:
priv->drag_origin = g_value_get_object (value);
break;
case PROP_DRAG_START_X:
priv->drag_start_x = g_value_get_int (value);
break;
case PROP_DRAG_START_Y:
priv->drag_start_y = g_value_get_int (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_dnd_actor_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaDnDActor *self = META_DND_ACTOR (object);
MetaDnDActorPrivate *priv = meta_dnd_actor_get_instance_private (self);
switch (prop_id)
{
case PROP_DRAG_ORIGIN:
g_value_set_object (value, priv->drag_origin);
break;
case PROP_DRAG_START_X:
g_value_set_int (value, priv->drag_start_x);
break;
case PROP_DRAG_START_Y:
g_value_set_int (value, priv->drag_start_y);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_dnd_actor_class_init (MetaDnDActorClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
object_class->set_property = meta_dnd_actor_set_property;
object_class->get_property = meta_dnd_actor_get_property;
pspec = g_param_spec_object ("drag-origin",
"Drag origin",
"The origin of the DnD operation",
CLUTTER_TYPE_ACTOR,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property (object_class,
PROP_DRAG_ORIGIN,
pspec);
pspec = g_param_spec_int ("drag-start-x",
"Drag start X",
"The X axis of the drag start point",
0, G_MAXINT, 0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property (object_class,
PROP_DRAG_START_X,
pspec);
pspec = g_param_spec_int ("drag-start-y",
"Drag start Y",
"The Y axis of the drag start point",
0, G_MAXINT, 0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property (object_class,
PROP_DRAG_START_Y,
pspec);
}
static void
meta_dnd_actor_init (MetaDnDActor *self)
{
}
/**
* meta_dnd_actor_new:
*
* Creates a new actor to draw the current drag and drop surface.
*
* Return value: the newly created background actor
*/
ClutterActor *
meta_dnd_actor_new (ClutterActor *drag_origin,
int drag_start_x,
int drag_start_y)
{
MetaDnDActor *self;
self = g_object_new (META_TYPE_DND_ACTOR,
"drag-origin", drag_origin,
"drag-start-x", drag_start_x,
"drag-start-y", drag_start_y,
NULL);
return CLUTTER_ACTOR (self);
}
static void
drag_failed_complete (ClutterTimeline *timeline,
gboolean is_finished,
gpointer user_data)
{
ClutterActor *self = user_data;
clutter_actor_remove_all_children (self);
clutter_actor_destroy (self);
}
void
meta_dnd_actor_drag_finish (MetaDnDActor *self,
gboolean success)
{
MetaDnDActorPrivate *priv;
ClutterActor *actor;
g_return_if_fail (META_IS_DND_ACTOR (self));
actor = CLUTTER_ACTOR (self);
priv = meta_dnd_actor_get_instance_private (self);
if (success)
{
clutter_actor_remove_all_children (CLUTTER_ACTOR (self));
clutter_actor_destroy (CLUTTER_ACTOR (self));
}
else
{
ClutterTransition *transition;
clutter_actor_save_easing_state (actor);
clutter_actor_set_easing_mode (actor, CLUTTER_EASE_OUT_CUBIC);
clutter_actor_set_easing_duration (actor, DRAG_FAILED_DURATION);
clutter_actor_set_opacity (actor, 0);
if (CLUTTER_ACTOR_IS_VISIBLE (priv->drag_origin))
{
int anchor_x, anchor_y;
ClutterPoint dest;
clutter_actor_get_transformed_position (priv->drag_origin,
&dest.x, &dest.y);
meta_feedback_actor_get_anchor (META_FEEDBACK_ACTOR (self),
&anchor_x, &anchor_y);
dest.x += priv->drag_start_x - anchor_x;
dest.y += priv->drag_start_y - anchor_y;
clutter_actor_set_position (actor, dest.x, dest.y);
}
transition = clutter_actor_get_transition (actor, "opacity");
g_signal_connect (transition, "stopped",
G_CALLBACK (drag_failed_complete), self);
clutter_actor_restore_easing_state (actor);
}
}

View File

@ -0,0 +1,74 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* meta-feedback-actor-private.h: Actor for painting user interaction feedback
*
* Copyright 2014 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#ifndef META_FEEDBACK_ACTOR_PRIVATE_H
#define META_FEEDBACK_ACTOR_PRIVATE_H
#include <clutter/clutter.h>
/**
* MetaFeedbackActor:
*
* This class handles the rendering of user interaction feedback
*/
#define META_TYPE_FEEDBACK_ACTOR (meta_feedback_actor_get_type ())
#define META_FEEDBACK_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_FEEDBACK_ACTOR, MetaFeedbackActor))
#define META_FEEDBACK_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_FEEDBACK_ACTOR, MetaFeedbackActorClass))
#define META_IS_FEEDBACK_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_FEEDBACK_ACTOR))
#define META_IS_FEEDBACK_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_FEEDBACK_ACTOR))
#define META_FEEDBACK_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_FEEDBACK_ACTOR, MetaFeedbackActorClass))
typedef struct _MetaFeedbackActor MetaFeedbackActor;
typedef struct _MetaFeedbackActorClass MetaFeedbackActorClass;
struct _MetaFeedbackActorClass
{
/*< private >*/
ClutterActorClass parent_class;
};
struct _MetaFeedbackActor
{
ClutterActor parent;
};
GType meta_feedback_actor_get_type (void);
ClutterActor *meta_feedback_actor_new (int anchor_x,
int anchor_y);
void meta_feedback_actor_set_anchor (MetaFeedbackActor *actor,
int anchor_x,
int anchor_y);
void meta_feedback_actor_get_anchor (MetaFeedbackActor *actor,
int *anchor_x,
int *anchor_y);
void meta_feedback_actor_set_position (MetaFeedbackActor *self,
int x,
int y);
void meta_feedback_actor_update (MetaFeedbackActor *self,
const ClutterEvent *event);
#endif /* META_FEEDBACK_ACTOR_PRIVATE_H */

View File

@ -0,0 +1,249 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2014 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
/**
* SECTION:meta-feedback-actor
* @title: MetaFeedbackActor
* @short_description: Actor for painting user interaction feedback
*/
#include <config.h>
#include "display-private.h"
#include "compositor-private.h"
#include "meta-feedback-actor-private.h"
enum {
PROP_ANCHOR_X = 1,
PROP_ANCHOR_Y
};
typedef struct _MetaFeedbackActorPrivate MetaFeedbackActorPrivate;
struct _MetaFeedbackActorPrivate
{
int anchor_x;
int anchor_y;
int pos_x;
int pos_y;
};
G_DEFINE_TYPE_WITH_PRIVATE (MetaFeedbackActor, meta_feedback_actor, CLUTTER_TYPE_ACTOR)
static void
meta_feedback_actor_constructed (GObject *object)
{
MetaDisplay *display;
display = meta_get_display ();
clutter_actor_add_child (display->compositor->feedback_group,
CLUTTER_ACTOR (object));
}
static void
meta_feedback_actor_update_position (MetaFeedbackActor *self)
{
MetaFeedbackActorPrivate *priv = meta_feedback_actor_get_instance_private (self);
clutter_actor_set_position (CLUTTER_ACTOR (self),
priv->pos_x - priv->anchor_x,
priv->pos_y - priv->anchor_y);
}
static void
meta_feedback_actor_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaFeedbackActor *self = META_FEEDBACK_ACTOR (object);
MetaFeedbackActorPrivate *priv = meta_feedback_actor_get_instance_private (self);
switch (prop_id)
{
case PROP_ANCHOR_X:
priv->anchor_x = g_value_get_int (value);
meta_feedback_actor_update_position (self);
break;
case PROP_ANCHOR_Y:
priv->anchor_y = g_value_get_int (value);
meta_feedback_actor_update_position (self);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_feedback_actor_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaFeedbackActor *self = META_FEEDBACK_ACTOR (object);
MetaFeedbackActorPrivate *priv = meta_feedback_actor_get_instance_private (self);
switch (prop_id)
{
case PROP_ANCHOR_X:
g_value_set_int (value, priv->anchor_x);
break;
case PROP_ANCHOR_Y:
g_value_set_int (value, priv->anchor_y);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_feedback_actor_class_init (MetaFeedbackActorClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
object_class->constructed = meta_feedback_actor_constructed;
object_class->set_property = meta_feedback_actor_set_property;
object_class->get_property = meta_feedback_actor_get_property;
pspec = g_param_spec_int ("anchor-x",
"Anchor X",
"The X axis of the anchor point",
0, G_MAXINT, 0,
G_PARAM_READWRITE);
g_object_class_install_property (object_class,
PROP_ANCHOR_X,
pspec);
pspec = g_param_spec_int ("anchor-y",
"Anchor Y",
"The Y axis of the anchor point",
0, G_MAXINT, 0,
G_PARAM_READWRITE);
g_object_class_install_property (object_class,
PROP_ANCHOR_Y,
pspec);
}
static void
meta_feedback_actor_init (MetaFeedbackActor *self)
{
clutter_actor_set_reactive (CLUTTER_ACTOR (self), FALSE);
}
/**
* meta_feedback_actor_new:
*
* Creates a new actor to draw the current drag and drop surface.
*
* Return value: the newly created background actor
*/
ClutterActor *
meta_feedback_actor_new (int anchor_x,
int anchor_y)
{
MetaFeedbackActor *self;
self = g_object_new (META_TYPE_FEEDBACK_ACTOR,
"anchor-x", anchor_x,
"anchor-y", anchor_y,
NULL);
return CLUTTER_ACTOR (self);
}
void
meta_feedback_actor_set_anchor (MetaFeedbackActor *self,
int anchor_x,
int anchor_y)
{
MetaFeedbackActorPrivate *priv;
g_return_if_fail (META_IS_FEEDBACK_ACTOR (self));
priv = meta_feedback_actor_get_instance_private (self);
if (priv->anchor_x == anchor_x && priv->anchor_y == anchor_y)
return;
if (priv->anchor_x != anchor_y)
{
priv->anchor_x = anchor_x;
g_object_notify (G_OBJECT (self), "anchor-x");
}
if (priv->anchor_y != anchor_y)
{
priv->anchor_y = anchor_y;
g_object_notify (G_OBJECT (self), "anchor-y");
}
meta_feedback_actor_update_position (self);
}
void
meta_feedback_actor_get_anchor (MetaFeedbackActor *self,
int *anchor_x,
int *anchor_y)
{
MetaFeedbackActorPrivate *priv;
g_return_if_fail (META_IS_FEEDBACK_ACTOR (self));
priv = meta_feedback_actor_get_instance_private (self);
if (anchor_x)
*anchor_x = priv->anchor_x;
if (anchor_y)
*anchor_y = priv->anchor_y;
}
void
meta_feedback_actor_set_position (MetaFeedbackActor *self,
int x,
int y)
{
MetaFeedbackActorPrivate *priv;
g_return_if_fail (META_IS_FEEDBACK_ACTOR (self));
priv = meta_feedback_actor_get_instance_private (self);
priv->pos_x = x;
priv->pos_y = y;
meta_feedback_actor_update_position (self);
}
void
meta_feedback_actor_update (MetaFeedbackActor *self,
const ClutterEvent *event)
{
ClutterPoint point;
g_return_if_fail (META_IS_FEEDBACK_ACTOR (self));
g_return_if_fail (event != NULL);
clutter_event_get_position (event, &point);
meta_feedback_actor_set_position (self, point.x, point.y);
}

View File

@ -193,8 +193,8 @@ meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor,
MetaRectangle window_rect;
meta_window_get_frame_rect (priv->window, &window_rect);
if (window_rect.x == x &&
window_rect.y == y &&
if (x == 0 &&
y == 0 &&
window_rect.width == width &&
window_rect.height == height)
priv->full_damage_frames_count++;
@ -383,6 +383,7 @@ window_decorated_notify (MetaWindow *window,
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (user_data);
detach_pixmap (self);
free_damage (self);
create_damage (self);
}

View File

@ -295,7 +295,7 @@ on_monitors_changed (MetaScreen *screen,
{
MetaDefaultPlugin *self = META_DEFAULT_PLUGIN (plugin);
int i, n;
GRand *rand = g_rand_new_with_seed (12345);
GRand *rand = g_rand_new_with_seed (123456);
clutter_actor_destroy_all_children (self->priv->background_group);

View File

@ -1007,7 +1007,7 @@ meta_display_list_windows (MetaDisplay *display,
{
MetaWindow *window = value;
if (!META_IS_WINDOW (window))
if (!META_IS_WINDOW (window) || window->unmanaging)
continue;
if (!window->override_redirect ||
@ -1020,7 +1020,7 @@ meta_display_list_windows (MetaDisplay *display,
{
MetaWindow *window = value;
if (!META_IS_WINDOW (window))
if (!META_IS_WINDOW (window) || window->unmanaging)
continue;
if (!window->override_redirect ||
@ -2440,13 +2440,22 @@ meta_display_get_tab_list (MetaDisplay *display,
mru_list = workspace ? workspace->mru_list : global_mru_list;
/* Windows sellout mode - MRU order.
/* Windows sellout mode - MRU order. Collect unminimized windows
* then minimized so minimized windows aren't in the way so much.
*/
for (tmp = mru_list; tmp; tmp = tmp->next)
{
MetaWindow *window = tmp->data;
if (IN_TAB_CHAIN (window, type))
if (!window->minimized && IN_TAB_CHAIN (window, type))
tab_list = g_list_prepend (tab_list, window);
}
for (tmp = mru_list; tmp; tmp = tmp->next)
{
MetaWindow *window = tmp->data;
if (window->minimized && IN_TAB_CHAIN (window, type))
tab_list = g_list_prepend (tab_list, window);
}

View File

@ -28,6 +28,7 @@
#include "display-private.h"
#include "window-private.h"
#include "backends/x11/meta-backend-x11.h"
#include "backends/meta-cursor-tracker-private.h"
#ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-backend-native.h"
@ -35,7 +36,6 @@
#endif
#ifdef HAVE_WAYLAND
#include "backends/meta-cursor-tracker-private.h"
#include "wayland/meta-wayland-private.h"
#endif
#include "meta-surface-actor.h"

View File

@ -2955,10 +2955,6 @@ do_choose_window (MetaDisplay *display,
meta_topic (META_DEBUG_KEYBINDINGS,
"Tab list = %u\n", type);
/* reverse direction if shift is down */
if (event->modifier_state & CLUTTER_SHIFT_MASK)
backward = !backward;
window = meta_display_get_tab_next (display,
type,
screen->active_workspace,

View File

@ -3021,38 +3021,33 @@ static gboolean
check_fullscreen_func (gpointer data)
{
MetaScreen *screen = data;
GSList *windows;
MetaWindow *window;
GSList *tmp;
GSList *fullscreen_monitors = NULL;
GSList *obscured_monitors = NULL;
gboolean in_fullscreen_changed = FALSE;
int i;
screen->check_fullscreen_later = 0;
windows = meta_display_list_windows (screen->display,
META_LIST_INCLUDE_OVERRIDE_REDIRECT);
for (tmp = windows; tmp != NULL; tmp = tmp->next)
/* We consider a monitor in fullscreen if it contains a fullscreen window;
* however we make an exception for maximized windows above the fullscreen
* one, as in that case window+chrome fully obscure the fullscreen window.
*/
for (window = meta_stack_get_top (screen->stack);
window;
window = meta_stack_get_below (screen->stack, window, FALSE))
{
MetaWindow *window = tmp->data;
gboolean covers_monitors = FALSE;
if (window->screen != screen || window->hidden)
continue;
if (window->fullscreen)
/* The checks for determining a fullscreen window's layer are quite
* elaborate, and we do a poor job at keeping it dynamically up-to-date.
* (It depends, for example, on whether the focus window is on the
* same monitor as the fullscreen window.) But because we minimize
* fullscreen windows not in LAYER_FULLSCREEN (see below), if the
* layer is stale here, it's really bad, so just force recomputation for
* here. This is expensive, but hopefully this function won't be
* called too often.
*/
meta_window_update_layer (window);
if (window->override_redirect)
{
covers_monitors = TRUE;
}
else if (window->override_redirect)
{
/* We want to handle the case where an application is creating an
* override-redirect window the size of the screen (monitor) and treat
@ -3062,10 +3057,14 @@ check_fullscreen_func (gpointer data)
if (meta_window_is_monitor_sized (window))
covers_monitors = TRUE;
}
else
else if (window->maximized_horizontally &&
window->maximized_vertically)
{
if (window->layer == META_LAYER_FULLSCREEN)
covers_monitors = TRUE;
int monitor_index = meta_window_get_monitor (window);
/* + 1 to avoid NULL */
gpointer monitor_p = GINT_TO_POINTER(monitor_index + 1);
if (!g_slist_find (obscured_monitors, monitor_p))
obscured_monitors = g_slist_prepend (obscured_monitors, monitor_p);
}
if (covers_monitors)
@ -3079,30 +3078,16 @@ check_fullscreen_func (gpointer data)
{
/* + 1 to avoid NULL */
gpointer monitor_p = GINT_TO_POINTER(monitors[j] + 1);
if (!g_slist_find (fullscreen_monitors, monitor_p))
if (!g_slist_find (fullscreen_monitors, monitor_p) &&
!g_slist_find (obscured_monitors, monitor_p))
fullscreen_monitors = g_slist_prepend (fullscreen_monitors, monitor_p);
}
g_free (monitors);
}
/* If we find a window that is fullscreen but not in the FULLSCREEN
* layer, it means that we've kicked it out of the layer because
* we've focused another window on the same monitor. In this case
* it would be confusing to keep the window fullscreen and visible,
* so minimize it. We can't do the same thing for override-redirect
* windows, so we just hope the application does the right thing.
*/
if (!covers_monitors && window->fullscreen)
{
meta_window_minimize (window);
meta_topic (META_DEBUG_WINDOW_OPS,
"Minimizing %s: was fullscreen but in a lower layer\n",
window->desc);
}
}
g_slist_free (windows);
g_slist_free (obscured_monitors);
for (i = 0; i < screen->n_monitor_infos; i++)
{

View File

@ -2622,6 +2622,9 @@ meta_window_maximize_internal (MetaWindow *window,
meta_window_recalc_features (window);
set_net_wm_state (window);
if (window->monitor->in_fullscreen)
meta_screen_queue_check_fullscreen (window->screen);
g_object_freeze_notify (G_OBJECT (window));
g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_MAXIMIZED_HORIZONTALLY]);
g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_MAXIMIZED_VERTICALLY]);
@ -3066,6 +3069,8 @@ meta_window_unmaximize_internal (MetaWindow *window,
meta_window_recalc_features (window);
set_net_wm_state (window);
if (!window->monitor->in_fullscreen)
meta_screen_queue_check_fullscreen (window->screen);
}
g_object_freeze_notify (G_OBJECT (window));
@ -4652,6 +4657,32 @@ meta_window_appears_focused_changed (MetaWindow *window)
meta_frame_queue_draw (window->frame);
}
static gboolean
should_propagate_focus_appearance (MetaWindow *window)
{
/* Parents of attached modal dialogs should appear focused. */
if (meta_window_is_attached_dialog (window))
return TRUE;
/* Parents of these sorts of override-redirect windows should
* appear focused. */
switch (window->type)
{
case META_WINDOW_DROPDOWN_MENU:
case META_WINDOW_POPUP_MENU:
case META_WINDOW_COMBO:
case META_WINDOW_TOOLTIP:
case META_WINDOW_NOTIFICATION:
case META_WINDOW_DND:
case META_WINDOW_OVERRIDE_OTHER:
return TRUE;
default:
break;
}
return FALSE;
}
/**
* meta_window_propagate_focus_appearance:
* @window: the window to start propagating from
@ -4675,7 +4706,7 @@ meta_window_propagate_focus_appearance (MetaWindow *window,
child = window;
parent = meta_window_get_transient_for (child);
while (parent && (!focused || meta_window_is_attached_dialog (child)))
while (parent && (!focused || should_propagate_focus_appearance (child)))
{
gboolean child_focus_state_changed;

View File

@ -180,13 +180,6 @@ meta_workspace_new (MetaScreen *screen)
workspace->windows = NULL;
workspace->mru_list = NULL;
/* make sure sticky windows are in our mru_list */
windows = meta_display_list_windows (screen->display, META_LIST_SORTED);
for (l = windows; l; l = l->next)
if (meta_window_located_on_workspace (l->data, workspace))
meta_workspace_add_window (workspace, l->data);
g_slist_free (windows);
workspace->work_areas_invalid = TRUE;
workspace->work_area_monitor = NULL;
workspace->work_area_screen.x = 0;
@ -205,6 +198,13 @@ meta_workspace_new (MetaScreen *screen)
workspace->showing_desktop = FALSE;
/* make sure sticky windows are in our mru_list */
windows = meta_display_list_windows (screen->display, META_LIST_SORTED);
for (l = windows; l; l = l->next)
if (meta_window_located_on_workspace (l->data, workspace))
meta_workspace_add_window (workspace, l->data);
g_slist_free (windows);
return workspace;
}

View File

@ -37,6 +37,7 @@ Window meta_get_overlay_window (MetaScreen *screen);
GList *meta_get_window_actors (MetaScreen *screen);
ClutterActor *meta_get_window_group_for_screen (MetaScreen *screen);
ClutterActor *meta_get_top_window_group_for_screen (MetaScreen *screen);
ClutterActor *meta_get_feedback_group_for_screen (MetaScreen *screen);
void meta_disable_unredirect_for_screen (MetaScreen *screen);
void meta_enable_unredirect_for_screen (MetaScreen *screen);

View File

@ -573,6 +573,7 @@ meta_frames_manage_window (MetaFrames *frames,
frame->title = NULL;
frame->shape_applied = FALSE;
frame->prelit_control = META_FRAME_CONTROL_NONE;
frame->button_state = META_BUTTON_STATE_NORMAL;
meta_core_grab_buttons (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow);

View File

@ -0,0 +1,137 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Endless Mobile
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include "config.h"
#include "meta-wayland-buffer.h"
#include <clutter/clutter.h>
#include <cogl/cogl-wayland-server.h>
#include <meta/util.h>
static void
meta_wayland_buffer_destroy_handler (struct wl_listener *listener,
void *data)
{
MetaWaylandBuffer *buffer =
wl_container_of (listener, buffer, destroy_listener);
wl_signal_emit (&buffer->destroy_signal, buffer);
g_slice_free (MetaWaylandBuffer, buffer);
}
void
meta_wayland_buffer_ref (MetaWaylandBuffer *buffer)
{
buffer->ref_count++;
}
void
meta_wayland_buffer_unref (MetaWaylandBuffer *buffer)
{
buffer->ref_count--;
if (buffer->ref_count == 0)
{
g_clear_pointer (&buffer->texture, cogl_object_unref);
wl_resource_queue_event (buffer->resource, WL_BUFFER_RELEASE);
}
}
MetaWaylandBuffer *
meta_wayland_buffer_from_resource (struct wl_resource *resource)
{
MetaWaylandBuffer *buffer;
struct wl_listener *listener;
listener =
wl_resource_get_destroy_listener (resource,
meta_wayland_buffer_destroy_handler);
if (listener)
{
buffer = wl_container_of (listener, buffer, destroy_listener);
}
else
{
buffer = g_slice_new0 (MetaWaylandBuffer);
buffer->resource = resource;
wl_signal_init (&buffer->destroy_signal);
buffer->destroy_listener.notify = meta_wayland_buffer_destroy_handler;
wl_resource_add_destroy_listener (resource, &buffer->destroy_listener);
}
return buffer;
}
CoglTexture *
meta_wayland_buffer_ensure_texture (MetaWaylandBuffer *buffer)
{
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
CoglError *catch_error = NULL;
CoglTexture *texture;
if (buffer->texture)
goto out;
texture = COGL_TEXTURE (cogl_wayland_texture_2d_new_from_buffer (ctx,
buffer->resource,
&catch_error));
if (!texture)
{
cogl_error_free (catch_error);
meta_fatal ("Could not import pending buffer, ignoring commit\n");
}
buffer->texture = texture;
out:
return buffer->texture;
}
void
meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
cairo_region_t *region)
{
struct wl_shm_buffer *shm_buffer;
shm_buffer = wl_shm_buffer_get (buffer->resource);
if (shm_buffer)
{
int i, n_rectangles;
n_rectangles = cairo_region_num_rectangles (region);
for (i = 0; i < n_rectangles; i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (region, i, &rect);
cogl_wayland_texture_set_region_from_shm_buffer (buffer->texture,
rect.x, rect.y, rect.width, rect.height,
shm_buffer,
rect.x, rect.y, 0, NULL);
}
}
}

View File

@ -0,0 +1,51 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Endless Mobile
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef META_WAYLAND_BUFFER_H
#define META_WAYLAND_BUFFER_H
#include <cogl/cogl.h>
#include <cairo.h>
#include <wayland-server.h>
#include "meta-wayland-types.h"
struct _MetaWaylandBuffer
{
struct wl_resource *resource;
struct wl_signal destroy_signal;
struct wl_listener destroy_listener;
CoglTexture *texture;
uint32_t ref_count;
};
MetaWaylandBuffer * meta_wayland_buffer_from_resource (struct wl_resource *resource);
void meta_wayland_buffer_ref (MetaWaylandBuffer *buffer);
void meta_wayland_buffer_unref (MetaWaylandBuffer *buffer);
CoglTexture * meta_wayland_buffer_ensure_texture (MetaWaylandBuffer *buffer);
void meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
cairo_region_t *region);
#endif /* META_WAYLAND_BUFFER_H */

View File

@ -34,7 +34,7 @@
#include "meta-wayland-seat.h"
#include "meta-wayland-pointer.h"
#include "meta-wayland-private.h"
#include "meta-cursor-tracker-private.h"
#include "meta-dnd-actor-private.h"
typedef struct
{
@ -183,6 +183,8 @@ struct _MetaWaylandDragGrab {
MetaWaylandDataSource *drag_data_source;
struct wl_listener drag_data_source_listener;
ClutterActor *feedback_actor;
MetaWaylandSurface *drag_origin;
struct wl_listener drag_origin_listener;
@ -212,8 +214,6 @@ drag_grab_focus (MetaWaylandPointerGrab *grab,
if (drag_grab->drag_focus == surface)
return;
meta_wayland_pointer_set_focus (&seat->pointer, surface, FALSE);
if (drag_grab->drag_focus_data_device)
{
wl_data_device_send_leave (drag_grab->drag_focus_data_device);
@ -253,40 +253,6 @@ drag_grab_focus (MetaWaylandPointerGrab *grab,
wl_resource_add_destroy_listener (data_device_resource, &drag_grab->drag_focus_listener);
}
static void
drag_grab_update_dnd_surface_position (MetaWaylandDragGrab *drag_grab)
{
MetaWaylandSeat *seat = drag_grab->seat;
ClutterPoint pos;
clutter_input_device_get_coords (seat->pointer.device, NULL, &pos);
meta_cursor_tracker_update_dnd_surface_position (seat->pointer.cursor_tracker,
(int) pos.x, (int) pos.y);
}
static void
drag_grab_update_dnd_surface (MetaWaylandDragGrab *drag_grab)
{
MetaWaylandSurface *surface = drag_grab->drag_surface;
MetaWaylandSeat *seat = drag_grab->seat;
CoglTexture *texture = NULL;
int offset_x, offset_y;
if (surface)
{
if (surface->buffer)
texture = surface->buffer->texture;
offset_x = surface->offset_x;
offset_y = surface->offset_y;
}
else
offset_x = offset_y = 0;
meta_cursor_tracker_set_dnd_surface (seat->pointer.cursor_tracker,
texture, offset_x, offset_y);
}
static void
drag_grab_motion (MetaWaylandPointerGrab *grab,
const ClutterEvent *event)
@ -294,8 +260,6 @@ drag_grab_motion (MetaWaylandPointerGrab *grab,
MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
wl_fixed_t sx, sy;
drag_grab_update_dnd_surface_position (drag_grab);
if (drag_grab->drag_focus_data_device)
{
meta_wayland_pointer_get_relative_coordinates (grab->pointer,
@ -305,29 +269,10 @@ drag_grab_motion (MetaWaylandPointerGrab *grab,
clutter_event_get_time (event),
sx, sy);
}
}
static void
data_device_dnd_failed (MetaWaylandDragGrab *drag_grab)
{
MetaWaylandSurface *surface = drag_grab->drag_origin;
MetaWaylandSeat *seat = drag_grab->seat;
ClutterPoint dest;
if (drag_grab->drag_origin &&
!meta_window_is_hidden (surface->window))
{
/* Find out the snap back position */
clutter_actor_get_transformed_position (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface->surface_actor)),
&dest.x, &dest.y);
dest.x += drag_grab->drag_start_x;
dest.y += drag_grab->drag_start_y;
}
else
clutter_input_device_get_coords (seat->pointer.device, NULL, &dest);
meta_cursor_tracker_dnd_failed (seat->pointer.cursor_tracker,
dest.x, dest.y);
if (drag_grab->drag_surface)
meta_feedback_actor_update (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
event);
}
static void
@ -351,10 +296,15 @@ data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
wl_list_remove (&drag_grab->drag_data_source_listener.link);
}
if (drag_grab->feedback_actor)
{
clutter_actor_remove_all_children (drag_grab->feedback_actor);
clutter_actor_destroy (drag_grab->feedback_actor);
}
drag_grab->seat->data_device.current_grab = NULL;
drag_grab_focus (&drag_grab->generic, NULL);
drag_grab_update_dnd_surface (drag_grab);
meta_wayland_pointer_end_grab (drag_grab->generic.pointer);
g_slice_free (MetaWaylandDragGrab, drag_grab);
@ -371,11 +321,19 @@ 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;
if (drag_grab->drag_focus_data_device &&
drag_grab->drag_data_source->has_target)
wl_data_device_send_drop (drag_grab->drag_focus_data_device);
else
data_device_dnd_failed (drag_grab);
{
wl_data_device_send_drop (drag_grab->drag_focus_data_device);
success = TRUE;
}
/* Finish drag and let actor self-destruct */
meta_dnd_actor_drag_finish (META_DND_ACTOR (drag_grab->feedback_actor),
success);
drag_grab->feedback_actor = NULL;
}
if (seat->pointer.button_count == 0 &&
@ -416,7 +374,9 @@ destroy_data_device_icon (struct wl_listener *listener, void *data)
wl_container_of (listener, drag_grab, drag_data_source_listener);
drag_grab->drag_surface = NULL;
drag_grab_update_dnd_surface (drag_grab);
if (drag_grab->feedback_actor)
clutter_actor_remove_all_children (drag_grab->feedback_actor);
}
static void
@ -483,12 +443,23 @@ data_device_start_drag (struct wl_client *client,
drag_grab->drag_icon_listener.notify = destroy_data_device_icon;
wl_resource_add_destroy_listener (icon_resource,
&drag_grab->drag_icon_listener);
drag_grab->feedback_actor = meta_dnd_actor_new (CLUTTER_ACTOR (drag_grab->drag_origin->surface_actor),
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);
clutter_actor_add_child (drag_grab->feedback_actor,
CLUTTER_ACTOR (drag_grab->drag_surface->surface_actor));
clutter_input_device_get_coords (seat->pointer.device, NULL, &pos);
meta_feedback_actor_set_position (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
pos.x, pos.y);
}
meta_wayland_pointer_set_focus (&seat->pointer, NULL, TRUE);
meta_wayland_pointer_set_focus (&seat->pointer, NULL);
meta_wayland_pointer_start_grab (&seat->pointer, (MetaWaylandPointerGrab*)drag_grab);
drag_grab_update_dnd_surface_position (drag_grab);
drag_grab_update_dnd_surface (drag_grab);
}
static void
@ -684,6 +655,17 @@ meta_wayland_data_device_is_dnd_surface (MetaWaylandDataDevice *data_device,
void
meta_wayland_data_device_update_dnd_surface (MetaWaylandDataDevice *data_device)
{
if (data_device->current_grab)
drag_grab_update_dnd_surface (data_device->current_grab);
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);
}

View File

@ -383,8 +383,6 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
keyboard->focus_surface_listener.notify = keyboard_handle_focus_surface_destroy;
wl_array_init (&keyboard->pressed_keys);
keyboard->xkb_info.keymap_fd = -1;
keyboard->settings = g_settings_new ("org.gnome.settings-daemon.peripherals.keyboard");
@ -417,47 +415,12 @@ meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard)
meta_wayland_xkb_info_destroy (&keyboard->xkb_info);
/* XXX: What about keyboard->resource_list? */
wl_array_release (&keyboard->pressed_keys);
g_object_unref (keyboard->settings);
keyboard->display = NULL;
}
static void
update_pressed_keys (struct wl_array *keys,
uint32_t evdev_code,
gboolean is_press)
{
uint32_t *end = (void *) ((char *) keys->data + keys->size);
uint32_t *k;
if (is_press)
{
/* Make sure we don't already have this key. */
for (k = keys->data; k < end; k++)
if (*k == evdev_code)
return;
/* Otherwise add the key to the list of pressed keys */
k = wl_array_add (keys, sizeof (*k));
*k = evdev_code;
}
else
{
/* Remove the key from the array */
for (k = keys->data; k < end; k++)
if (*k == evdev_code)
{
*k = *(end - 1);
keys->size -= sizeof (*k);
return;
}
g_warning ("unexpected key release event for key 0x%x", evdev_code);
}
}
static guint
evdev_code (const ClutterKeyEvent *event)
{
@ -471,18 +434,10 @@ meta_wayland_keyboard_update (MetaWaylandKeyboard *keyboard,
const ClutterKeyEvent *event)
{
gboolean is_press = event->type == CLUTTER_KEY_PRESS;
struct xkb_state *state = keyboard->xkb_info.state;
enum xkb_state_component changed_state;
update_pressed_keys (&keyboard->pressed_keys, evdev_code (event), is_press);
changed_state = xkb_state_update_key (state,
event->hardware_keycode,
is_press ? XKB_KEY_DOWN : XKB_KEY_UP);
if (changed_state == 0)
return;
notify_modifiers (keyboard);
keyboard->mods_changed = xkb_state_update_key (keyboard->xkb_info.state,
event->hardware_keycode,
is_press ? XKB_KEY_DOWN : XKB_KEY_UP);
}
gboolean
@ -508,6 +463,12 @@ meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
else
meta_verbose ("No wayland surface is focused, continuing normal operation\n");
if (keyboard->mods_changed != 0)
{
notify_modifiers (keyboard);
keyboard->mods_changed = 0;
}
return handled;
}
@ -538,8 +499,27 @@ static void
broadcast_focus (MetaWaylandKeyboard *keyboard,
struct wl_resource *resource)
{
struct wl_array fake_keys;
struct xkb_state *state = keyboard->xkb_info.state;
/* We never want to send pressed keys to wayland clients on
* enter. The protocol says that we should send them, presumably so
* that clients can trigger their own key repeat routine in case
* they are given focus and a key is physically pressed.
*
* Unfortunately this causes some clients, in particular Xwayland,
* to register key events that they really shouldn't handle,
* e.g. on an Alt+Tab keybinding, where Alt is released before Tab,
* clients would see Tab being pressed on enter followed by a key
* release event for Tab, meaning that Tab would be processed by
* the client when it really shouldn't.
*
* Since the use case for the pressed keys array on enter seems weak
* to us, we'll just fake that there are no pressed keys instead
* which should be spec compliant even if it might not be true.
*/
wl_array_init (&fake_keys);
wl_keyboard_send_modifiers (resource, keyboard->focus_serial,
xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED),
xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED),
@ -547,7 +527,7 @@ broadcast_focus (MetaWaylandKeyboard *keyboard,
xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE));
wl_keyboard_send_enter (resource, keyboard->focus_serial,
keyboard->focus_surface->resource,
&keyboard->pressed_keys);
&fake_keys);
}
void

View File

@ -69,9 +69,8 @@ struct _MetaWaylandKeyboard
struct wl_listener focus_surface_listener;
uint32_t focus_serial;
struct wl_array pressed_keys;
MetaWaylandXkbInfo xkb_info;
enum xkb_state_component mods_changed;
GSettings *settings;
};

View File

@ -48,6 +48,7 @@
#include "meta-wayland-pointer.h"
#include "meta-wayland-private.h"
#include "meta-wayland-buffer.h"
#include "meta-cursor.h"
#include "meta-cursor-tracker-private.h"
#include "meta-surface-actor-wayland.h"
@ -95,7 +96,7 @@ pointer_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
{
MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_surface_listener);
meta_wayland_pointer_set_focus (pointer, NULL, TRUE);
meta_wayland_pointer_set_focus (pointer, NULL);
}
static void
@ -107,7 +108,7 @@ default_grab_focus (MetaWaylandPointerGrab *grab,
if (pointer->button_count > 0)
return;
meta_wayland_pointer_set_focus (pointer, surface, TRUE);
meta_wayland_pointer_set_focus (pointer, surface);
}
static void
@ -178,7 +179,7 @@ default_grab_button (MetaWaylandPointerGrab *grab,
}
if (pointer->button_count == 0 && event_type == CLUTTER_BUTTON_RELEASE)
meta_wayland_pointer_set_focus (pointer, pointer->current, TRUE);
meta_wayland_pointer_set_focus (pointer, pointer->current);
}
static const MetaWaylandPointerGrabInterface default_pointer_grab_interface = {
@ -218,7 +219,7 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer,
void
meta_wayland_pointer_release (MetaWaylandPointer *pointer)
{
meta_wayland_pointer_set_focus (pointer, NULL, TRUE);
meta_wayland_pointer_set_focus (pointer, NULL);
set_cursor_surface (pointer, NULL);
pointer->display = NULL;
@ -272,11 +273,8 @@ sync_focus_surface (MetaWaylandPointer *pointer)
g_assert_not_reached ();
}
if (focus_surface != pointer->focus_surface)
{
const MetaWaylandPointerGrabInterface *interface = pointer->grab->interface;
interface->focus (pointer->grab, focus_surface);
}
const MetaWaylandPointerGrabInterface *interface = pointer->grab->interface;
interface->focus (pointer->grab, focus_surface);
}
static void
@ -308,9 +306,6 @@ repick_for_event (MetaWaylandPointer *pointer,
else
pointer->current = NULL;
if (pointer->cursor_tracker && pointer->current == NULL)
meta_cursor_tracker_unset_window_cursor (pointer->cursor_tracker);
sync_focus_surface (pointer);
}
@ -480,8 +475,7 @@ broadcast_focus (MetaWaylandPointer *pointer,
void
meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
MetaWaylandSurface *surface,
gboolean emit_crossing)
MetaWaylandSurface *surface)
{
if (pointer->display == NULL)
return;
@ -501,12 +495,9 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
struct wl_display *display = wl_client_get_display (client);
uint32_t serial = wl_display_next_serial (display);
if (emit_crossing)
wl_resource_for_each (resource, l)
{
wl_resource_for_each (resource, l)
{
wl_pointer_send_leave (resource, serial, pointer->focus_surface->resource);
}
wl_pointer_send_leave (resource, serial, pointer->focus_surface->resource);
}
move_resources (&pointer->resource_list, &pointer->focus_resource_list);
@ -537,7 +528,7 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
wl_resource_get_client (pointer->focus_surface->resource));
l = &pointer->focus_resource_list;
if (emit_crossing && !wl_list_empty (l))
if (!wl_list_empty (l))
{
struct wl_client *client = wl_resource_get_client (pointer->focus_surface->resource);
struct wl_display *display = wl_client_get_display (client);
@ -549,6 +540,8 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
}
}
}
meta_wayland_pointer_update_cursor_surface (pointer);
}
void
@ -573,6 +566,8 @@ meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer)
pointer->grab = &pointer->default_grab;
interface = pointer->grab->interface;
interface->focus (pointer->grab, pointer->current);
meta_wayland_pointer_update_cursor_surface (pointer);
}
typedef struct {
@ -599,9 +594,9 @@ popup_grab_focus (MetaWaylandPointerGrab *grab,
/* Popup grabs are in owner-events mode (ie, events for the same client
are reported as normal) */
if (surface && wl_resource_get_client (surface->resource) == popup_grab->grab_client)
meta_wayland_pointer_set_focus (grab->pointer, surface, TRUE);
meta_wayland_pointer_set_focus (grab->pointer, surface);
else
meta_wayland_pointer_set_focus (grab->pointer, NULL, TRUE);
meta_wayland_pointer_set_focus (grab->pointer, NULL);
}
static void
@ -722,10 +717,10 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
popup->grab = grab;
popup->surface = surface;
popup->surface_destroy_listener.notify = on_popup_surface_destroy;
if (surface->xdg_popup.resource)
wl_resource_add_destroy_listener (surface->xdg_popup.resource, &popup->surface_destroy_listener);
else if (surface->wl_shell_surface.resource)
wl_resource_add_destroy_listener (surface->wl_shell_surface.resource, &popup->surface_destroy_listener);
if (surface->xdg_popup)
wl_resource_add_destroy_listener (surface->xdg_popup, &popup->surface_destroy_listener);
else if (surface->wl_shell_surface)
wl_resource_add_destroy_listener (surface->wl_shell_surface, &popup->surface_destroy_listener);
wl_list_insert (&grab->all_popups, &popup->link);
return TRUE;
@ -757,25 +752,32 @@ meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer,
void
meta_wayland_pointer_update_cursor_surface (MetaWaylandPointer *pointer)
{
MetaCursorReference *cursor;
if (pointer->cursor_tracker == NULL)
return;
if (pointer->cursor_surface && pointer->cursor_surface->buffer)
if (pointer->current)
{
struct wl_resource *buffer = pointer->cursor_surface->buffer->resource;
cursor = meta_cursor_reference_from_buffer (buffer,
pointer->hotspot_x,
pointer->hotspot_y);
MetaCursorReference *cursor;
if (pointer->cursor_surface && pointer->cursor_surface->buffer)
{
struct wl_resource *buffer = pointer->cursor_surface->buffer->resource;
cursor = meta_cursor_reference_from_buffer (buffer,
pointer->hotspot_x,
pointer->hotspot_y);
}
else
cursor = NULL;
meta_cursor_tracker_set_window_cursor (pointer->cursor_tracker, cursor);
if (cursor)
meta_cursor_reference_unref (cursor);
}
else
cursor = NULL;
meta_cursor_tracker_set_window_cursor (pointer->cursor_tracker, cursor);
if (cursor)
meta_cursor_reference_unref (cursor);
{
meta_cursor_tracker_unset_window_cursor (pointer->cursor_tracker);
}
}
static void

View File

@ -86,8 +86,7 @@ gboolean meta_wayland_pointer_handle_event (MetaWaylandPointer *pointer,
const ClutterEvent *event);
void meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
MetaWaylandSurface *surface,
gboolean emit_crossing);
MetaWaylandSurface *surface);
void meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer,
MetaWaylandPointerGrab *grab);

View File

@ -24,7 +24,6 @@
#include <clutter/clutter.h>
#include <glib.h>
#include <cairo.h>
#include "window-private.h"
#include <meta/meta-cursor-tracker.h>
@ -34,19 +33,6 @@
#include "meta-wayland-surface.h"
#include "meta-wayland-seat.h"
typedef struct
{
struct wl_resource *resource;
cairo_region_t *region;
} MetaWaylandRegion;
typedef struct
{
GSource source;
GPollFD pfd;
struct wl_display *display;
} WaylandEventSource;
typedef struct
{
struct wl_list link;
@ -71,7 +57,6 @@ struct _MetaWaylandCompositor
{
struct wl_display *wayland_display;
const char *display_name;
ClutterActor *stage;
GHashTable *outputs;
struct wl_list frame_callbacks;
@ -80,8 +65,4 @@ struct _MetaWaylandCompositor
MetaWaylandSeat *seat;
};
MetaWaylandBuffer * meta_wayland_buffer_from_resource (struct wl_resource *resource);
void meta_wayland_buffer_ref (MetaWaylandBuffer *buffer);
void meta_wayland_buffer_unref (MetaWaylandBuffer *buffer);
#endif /* META_WAYLAND_PRIVATE_H */

View File

@ -0,0 +1,105 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Endless Mobile
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include "config.h"
#include "meta-wayland-region.h"
struct _MetaWaylandRegion
{
struct wl_resource *resource;
cairo_region_t *region;
};
static void
wl_region_destroy (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static void
wl_region_add (struct wl_client *client,
struct wl_resource *resource,
gint32 x,
gint32 y,
gint32 width,
gint32 height)
{
MetaWaylandRegion *region = wl_resource_get_user_data (resource);
cairo_rectangle_int_t rectangle = { x, y, width, height };
cairo_region_union_rectangle (region->region, &rectangle);
}
static void
wl_region_subtract (struct wl_client *client,
struct wl_resource *resource,
gint32 x,
gint32 y,
gint32 width,
gint32 height)
{
MetaWaylandRegion *region = wl_resource_get_user_data (resource);
cairo_rectangle_int_t rectangle = { x, y, width, height };
cairo_region_subtract_rectangle (region->region, &rectangle);
}
static const struct wl_region_interface meta_wayland_wl_region_interface = {
wl_region_destroy,
wl_region_add,
wl_region_subtract
};
static void
wl_region_destructor (struct wl_resource *resource)
{
MetaWaylandRegion *region = wl_resource_get_user_data (resource);
cairo_region_destroy (region->region);
g_slice_free (MetaWaylandRegion, region);
}
MetaWaylandRegion *
meta_wayland_region_create (MetaWaylandCompositor *compositor,
struct wl_client *client,
struct wl_resource *compositor_resource,
guint32 id)
{
MetaWaylandRegion *region = g_slice_new0 (MetaWaylandRegion);
region->resource = wl_resource_create (client, &wl_region_interface, wl_resource_get_version (compositor_resource), id);
wl_resource_set_implementation (region->resource, &meta_wayland_wl_region_interface, region, wl_region_destructor);
region->region = cairo_region_create ();
return region;
}
cairo_region_t *
meta_wayland_region_peek_cairo_region (MetaWaylandRegion *region)
{
return region->region;
}

View File

@ -0,0 +1,40 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Endless Mobile
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef META_WAYLAND_REGION_H
#define META_WAYLAND_REGION_H
#include <glib.h>
#include <cairo.h>
#include <wayland-server.h>
#include "meta-wayland-types.h"
MetaWaylandRegion * meta_wayland_region_create (MetaWaylandCompositor *compositor,
struct wl_client *client,
struct wl_resource *compositor_resource,
guint32 id);
cairo_region_t * meta_wayland_region_peek_cairo_region (MetaWaylandRegion *region);
#endif /* META_WAYLAND_REGION_H */

View File

@ -20,29 +20,23 @@
* 02111-1307, USA.
*/
#include <config.h>
#include "config.h"
#include "meta-wayland-surface.h"
#include <clutter/clutter.h>
#include <clutter/wayland/clutter-wayland-compositor.h>
#include <clutter/wayland/clutter-wayland-surface.h>
#include <cogl/cogl-wayland-server.h>
#include <glib.h>
#include <sys/time.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <wayland-server.h>
#include "gtk-shell-server-protocol.h"
#include "xdg-shell-server-protocol.h"
#include "meta-wayland-private.h"
#include "meta-xwayland-private.h"
#include "meta-wayland-buffer.h"
#include "meta-wayland-region.h"
#include "meta-wayland-seat.h"
#include "meta-wayland-keyboard.h"
#include "meta-wayland-pointer.h"
@ -52,9 +46,6 @@
#include "display-private.h"
#include "window-private.h"
#include "window-wayland.h"
#include <meta/types.h>
#include <meta/main.h>
#include "frame.h"
#include "meta-surface-actor.h"
#include "meta-surface-actor-wayland.h"
@ -106,67 +97,38 @@ static void
surface_process_damage (MetaWaylandSurface *surface,
cairo_region_t *region)
{
int i, n_rectangles;
cairo_rectangle_int_t buffer_rect;
int scale = surface->scale;
CoglTexture *texture;
struct wl_shm_buffer *shm_buffer;
int i, n_rectangles;
/* Damage without a buffer makes no sense so ignore that, otherwise we would crash */
if (!surface->buffer)
return;
texture = surface->buffer->texture;
buffer_rect.x = 0;
buffer_rect.y = 0;
buffer_rect.width = cogl_texture_get_width (surface->buffer->texture);
buffer_rect.height = cogl_texture_get_height (surface->buffer->texture);
/* The region will get destroyed after this call anyway so we can
just modify it here to avoid a copy */
* just modify it here to avoid a copy. */
cairo_region_intersect_rectangle (region, &buffer_rect);
/* First update the buffer. */
meta_wayland_buffer_process_damage (surface->buffer, region);
/* Now damage the actor. */
/* XXX: Should this be a signal / callback on MetaWaylandBuffer instead? */
n_rectangles = cairo_region_num_rectangles (region);
shm_buffer = wl_shm_buffer_get (surface->buffer->resource);
for (i = 0; i < n_rectangles; i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (region, i, &rect);
if (shm_buffer)
cogl_wayland_texture_set_region_from_shm_buffer (texture, rect.x, rect.y, rect.width, rect.height, shm_buffer, rect.x, rect.y, 0, NULL);
meta_surface_actor_process_damage (surface->surface_actor,
rect.x * scale, rect.y * scale, rect.width * scale, rect.height * scale);
}
}
static void
ensure_buffer_texture (MetaWaylandBuffer *buffer)
{
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
CoglError *catch_error = NULL;
CoglTexture *texture;
if (buffer->texture)
return;
texture = COGL_TEXTURE (cogl_wayland_texture_2d_new_from_buffer (ctx,
buffer->resource,
&catch_error));
if (!texture)
{
cogl_error_free (catch_error);
meta_warning ("Could not import pending buffer, ignoring commit\n");
return;
}
buffer->texture = texture;
}
static void
cursor_surface_commit (MetaWaylandSurface *surface,
MetaWaylandPendingState *pending)
@ -425,13 +387,16 @@ commit_pending_state (MetaWaylandSurface *surface,
if (pending->buffer)
{
ensure_buffer_texture (pending->buffer);
meta_surface_actor_wayland_set_texture (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor), pending->buffer->texture);
CoglTexture *texture = meta_wayland_buffer_ensure_texture (pending->buffer);
meta_surface_actor_wayland_set_texture (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor), texture);
}
}
if (pending->scale > 0)
surface->scale = pending->scale;
{
surface->scale = pending->scale;
meta_surface_actor_wayland_scale_texture (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor));
}
if (!cairo_region_is_empty (pending->damage))
surface_process_damage (surface, pending->damage);
@ -450,24 +415,21 @@ commit_pending_state (MetaWaylandSurface *surface,
meta_surface_actor_set_input_region (surface->surface_actor, pending->input_region);
}
/* wl_surface.frame */
wl_list_insert_list (&compositor->frame_callbacks, &pending->frame_callback_list);
wl_list_init (&pending->frame_callback_list);
if (surface == compositor->seat->pointer.cursor_surface)
cursor_surface_commit (surface, pending);
else if (meta_wayland_data_device_is_dnd_surface (&compositor->seat->data_device, surface))
dnd_surface_commit (surface, pending);
else if (surface->window)
toplevel_surface_commit (surface, pending);
else if (surface->subsurface.resource)
else if (surface->wl_subsurface)
subsurface_surface_commit (surface, pending);
g_list_foreach (surface->subsurfaces, parent_surface_committed, NULL);
/* scale surface texture */
meta_surface_actor_wayland_scale_texture (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor));
/* wl_surface.frame */
wl_list_insert_list (&compositor->frame_callbacks, &pending->frame_callback_list);
wl_list_init (&pending->frame_callback_list);
pending_state_reset (pending);
}
@ -578,7 +540,8 @@ wl_surface_set_opaque_region (struct wl_client *client,
if (region_resource)
{
MetaWaylandRegion *region = wl_resource_get_user_data (region_resource);
surface->pending.opaque_region = cairo_region_copy (region->region);
cairo_region_t *cr_region = meta_wayland_region_peek_cairo_region (region);
surface->pending.opaque_region = cairo_region_copy (cr_region);
}
}
@ -597,7 +560,8 @@ wl_surface_set_input_region (struct wl_client *client,
if (region_resource)
{
MetaWaylandRegion *region = wl_resource_get_user_data (region_resource);
surface->pending.input_region = cairo_region_copy (region->region);
cairo_region_t *cr_region = meta_wayland_region_peek_cairo_region (region);
surface->pending.input_region = cairo_region_copy (cr_region);
}
}
@ -654,7 +618,7 @@ surface_should_be_reactive (MetaWaylandSurface *surface)
return TRUE;
/* If we're a subsurface, we should be reactive */
if (surface->subsurface.resource)
if (surface->wl_subsurface)
return TRUE;
return FALSE;
@ -734,33 +698,6 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
return surface;
}
static void
destroy_surface_extension (MetaWaylandSurfaceExtension *extension)
{
extension->resource = NULL;
}
static gboolean
create_surface_extension (MetaWaylandSurfaceExtension *extension,
const struct wl_interface *interface,
const void *implementation,
wl_resource_destroy_func_t destructor,
MetaWaylandSurface *surface,
struct wl_resource *master_resource,
guint32 id)
{
struct wl_client *client;
if (extension->resource != NULL)
return FALSE;
client = wl_resource_get_client (surface->resource);
extension->resource = wl_resource_create (client, interface, wl_resource_get_version (master_resource), id);
wl_resource_set_implementation (extension->resource, implementation, surface, destructor);
return TRUE;
}
static void
xdg_shell_use_unstable_version (struct wl_client *client,
struct wl_resource *resource,
@ -787,7 +724,7 @@ xdg_surface_destructor (struct wl_resource *resource)
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
destroy_window (surface);
destroy_surface_extension (&surface->xdg_surface);
surface->xdg_surface = NULL;
}
static void
@ -1025,11 +962,7 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWindow *window;
if (!create_surface_extension (&surface->xdg_surface,
&xdg_surface_interface,
&meta_wayland_xdg_surface_interface,
xdg_surface_destructor,
surface, resource, id))
if (surface->xdg_surface != NULL)
{
wl_resource_post_error (surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
@ -1037,6 +970,9 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
return;
}
surface->xdg_surface = wl_resource_create (client, &xdg_surface_interface, wl_resource_get_version (resource), id);
wl_resource_set_implementation (surface->xdg_surface, &meta_wayland_xdg_surface_interface, surface, xdg_surface_destructor);
surface->xdg_shell_resource = resource;
window = meta_window_wayland_new (meta_get_display (), surface);
@ -1049,7 +985,7 @@ xdg_popup_destructor (struct wl_resource *resource)
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
destroy_window (surface);
destroy_surface_extension (&surface->xdg_popup);
surface->xdg_popup = NULL;
}
static void
@ -1079,15 +1015,12 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource);
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
MetaWindow *window;
MetaDisplay *display = meta_get_display ();
if (parent_surf == NULL || parent_surf->window == NULL)
return;
if (!create_surface_extension (&surface->xdg_popup,
&xdg_popup_interface,
&meta_wayland_xdg_popup_interface,
xdg_popup_destructor,
surface, resource, id))
if (surface->xdg_popup != NULL)
{
wl_resource_post_error (surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
@ -1095,9 +1028,12 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
return;
}
surface->xdg_popup = wl_resource_create (client, &xdg_popup_interface, wl_resource_get_version (resource), id);
wl_resource_set_implementation (surface->xdg_popup, &meta_wayland_xdg_popup_interface, surface, xdg_popup_destructor);
surface->xdg_shell_resource = resource;
window = meta_window_wayland_new (meta_get_display (), surface);
window = meta_window_wayland_new (display, surface);
meta_window_move_frame (window, FALSE,
parent_surf->window->rect.x + x,
parent_surf->window->rect.y + y);
@ -1108,6 +1044,7 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
meta_wayland_surface_set_window (surface, window);
meta_window_focus (window, meta_display_get_current_time (display));
meta_wayland_pointer_start_popup_grab (&seat->pointer, surface);
}
@ -1141,7 +1078,7 @@ wl_shell_surface_destructor (struct wl_resource *resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
destroy_surface_extension (&surface->wl_shell_surface);
surface->wl_shell_surface = NULL;
}
static void
@ -1349,11 +1286,7 @@ wl_shell_get_shell_surface (struct wl_client *client,
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWindow *window;
if (!create_surface_extension (&surface->wl_shell_surface,
&wl_shell_surface_interface,
&meta_wayland_wl_shell_surface_interface,
wl_shell_surface_destructor,
surface, resource, id))
if (surface->wl_shell_surface != NULL)
{
wl_resource_post_error (surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
@ -1361,6 +1294,9 @@ wl_shell_get_shell_surface (struct wl_client *client,
return;
}
surface->wl_shell_surface = wl_resource_create (client, &wl_shell_surface_interface, wl_resource_get_version (resource), id);
wl_resource_set_implementation (surface->wl_shell_surface, &meta_wayland_wl_shell_surface_interface, surface, wl_shell_surface_destructor);
window = meta_window_wayland_new (meta_get_display (), surface);
meta_wayland_surface_set_window (surface, window);
}
@ -1386,7 +1322,7 @@ gtk_surface_destructor (struct wl_resource *resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
destroy_surface_extension (&surface->gtk_surface);
surface->gtk_surface = NULL;
}
static void
@ -1429,17 +1365,16 @@ get_gtk_surface (struct wl_client *client,
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
if (!create_surface_extension (&surface->gtk_surface,
&gtk_surface_interface,
&meta_wayland_gtk_surface_interface,
gtk_surface_destructor,
surface, resource, id))
if (surface->gtk_surface != NULL)
{
wl_resource_post_error (surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"gtk_shell::get_gtk_surface already requested");
return;
}
surface->gtk_surface = wl_resource_create (client, &gtk_surface_interface, wl_resource_get_version (resource), id);
wl_resource_set_implementation (surface->gtk_surface, &meta_wayland_gtk_surface_interface, surface, gtk_surface_destructor);
}
static const struct gtk_shell_interface meta_wayland_gtk_shell_interface = {
@ -1540,7 +1475,7 @@ wl_subsurface_destructor (struct wl_resource *resource)
}
pending_state_destroy (&surface->sub.pending);
destroy_surface_extension (&surface->subsurface);
surface->wl_subsurface = NULL;
}
static void
@ -1666,7 +1601,7 @@ wl_subsurface_set_desync (struct wl_client *client,
surface->sub.synchronous = FALSE;
}
static const struct wl_subsurface_interface meta_wayland_subsurface_interface = {
static const struct wl_subsurface_interface meta_wayland_wl_subsurface_interface = {
wl_subsurface_destroy,
wl_subsurface_set_position,
wl_subsurface_place_above,
@ -1704,11 +1639,7 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWaylandSurface *parent = wl_resource_get_user_data (parent_resource);
if (!create_surface_extension (&surface->subsurface,
&wl_subsurface_interface,
&meta_wayland_subsurface_interface,
wl_subsurface_destructor,
surface, resource, id))
if (surface->wl_subsurface != NULL)
{
wl_resource_post_error (surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
@ -1716,6 +1647,9 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
return;
}
surface->wl_subsurface = wl_resource_create (client, &wl_subsurface_interface, wl_resource_get_version (resource), id);
wl_resource_set_implementation (surface->wl_subsurface, &meta_wayland_wl_subsurface_interface, surface, wl_subsurface_destructor);
pending_state_init (&surface->sub.pending);
surface->sub.synchronous = TRUE;
surface->sub.parent = parent;
@ -1807,9 +1741,9 @@ meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
int new_height,
MetaWaylandSerial *sent_serial)
{
if (surface->xdg_surface.resource)
if (surface->xdg_surface)
{
struct wl_client *client = wl_resource_get_client (surface->xdg_surface.resource);
struct wl_client *client = wl_resource_get_client (surface->xdg_surface);
struct wl_display *display = wl_client_get_display (client);
uint32_t serial = wl_display_next_serial (display);
struct wl_array states;
@ -1823,7 +1757,7 @@ meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
new_width /= surface->scale;
new_height /= surface->scale;
xdg_surface_send_configure (surface->xdg_surface.resource, new_width, new_height, &states, serial);
xdg_surface_send_configure (surface->xdg_surface, new_width, new_height, &states, serial);
wl_array_release (&states);
@ -1833,13 +1767,13 @@ meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
sent_serial->value = serial;
}
}
else if (surface->xdg_popup.resource)
else if (surface->xdg_popup)
{
/* This can happen if the popup window loses or receives focus.
* Just ignore it. */
}
else if (surface->wl_shell_surface.resource)
wl_shell_surface_send_configure (surface->wl_shell_surface.resource,
else if (surface->wl_shell_surface)
wl_shell_surface_send_configure (surface->wl_shell_surface,
0, new_width, new_height);
else
g_assert_not_reached ();
@ -1851,15 +1785,15 @@ meta_wayland_surface_ping (MetaWaylandSurface *surface,
{
if (surface->xdg_shell_resource)
xdg_shell_send_ping (surface->xdg_shell_resource, serial);
else if (surface->wl_shell_surface.resource)
wl_shell_surface_send_ping (surface->wl_shell_surface.resource, serial);
else if (surface->wl_shell_surface)
wl_shell_surface_send_ping (surface->wl_shell_surface, serial);
}
void
meta_wayland_surface_delete (MetaWaylandSurface *surface)
{
if (surface->xdg_surface.resource)
xdg_surface_send_close (surface->xdg_surface.resource);
if (surface->xdg_surface)
xdg_surface_send_close (surface->xdg_surface);
}
void
@ -1869,8 +1803,8 @@ meta_wayland_surface_popup_done (MetaWaylandSurface *surface)
struct wl_display *display = wl_client_get_display (client);
uint32_t serial = wl_display_next_serial (display);
if (surface->xdg_popup.resource)
xdg_popup_send_popup_done (surface->xdg_popup.resource, serial);
else if (surface->wl_shell_surface.resource)
wl_shell_surface_send_popup_done (surface->wl_shell_surface.resource);
if (surface->xdg_popup)
xdg_popup_send_popup_done (surface->xdg_popup, serial);
else if (surface->wl_shell_surface)
wl_shell_surface_send_popup_done (surface->wl_shell_surface);
}

View File

@ -36,16 +36,6 @@ struct _MetaWaylandSerial {
uint32_t value;
};
struct _MetaWaylandBuffer
{
struct wl_resource *resource;
struct wl_signal destroy_signal;
struct wl_listener destroy_listener;
CoglTexture *texture;
uint32_t ref_count;
};
typedef struct
{
/* wl_surface.attach */
@ -70,30 +60,35 @@ typedef struct
gboolean has_new_geometry;
} MetaWaylandPendingState;
typedef struct
{
struct wl_resource *resource;
} MetaWaylandSurfaceExtension;
struct _MetaWaylandSurface
{
/* Generic stuff */
struct wl_resource *resource;
MetaWaylandCompositor *compositor;
MetaSurfaceActor *surface_actor;
MetaWindow *window;
struct wl_resource *xdg_shell_resource;
MetaWaylandSurfaceExtension xdg_surface;
MetaWaylandSurfaceExtension xdg_popup;
MetaWaylandSurfaceExtension wl_shell_surface;
MetaWaylandSurfaceExtension gtk_surface;
MetaWaylandSurfaceExtension subsurface;
int scale;
MetaWaylandBuffer *buffer;
struct wl_listener buffer_destroy_listener;
int scale;
int32_t offset_x, offset_y;
GList *subsurfaces;
/* All the pending state that wl_surface.commit will apply. */
MetaWaylandPendingState pending;
/* Extension resources. */
struct wl_resource *xdg_surface;
struct wl_resource *xdg_popup;
struct wl_resource *wl_shell_surface;
struct wl_resource *gtk_surface;
struct wl_resource *wl_subsurface;
/* xdg_surface stuff */
struct wl_resource *xdg_shell_resource;
MetaWaylandSerial acked_configure_serial;
gboolean has_set_geometry;
/* wl_subsurface stuff. */
struct {
MetaWaylandSurface *parent;
struct wl_listener parent_destroy_listener;
@ -114,15 +109,6 @@ struct _MetaWaylandSurface
gboolean pending_pos;
GSList *pending_placement_ops;
} sub;
int32_t offset_x, offset_y;
gboolean has_set_geometry;
/* All the pending state that wl_surface.commit will apply. */
MetaWaylandPendingState pending;
MetaWaylandSerial acked_configure_serial;
};
void meta_wayland_shell_init (MetaWaylandCompositor *compositor);

View File

@ -32,7 +32,7 @@ typedef struct _MetaWaylandDataSource MetaWaylandDataSource;
typedef struct _MetaWaylandDataDevice MetaWaylandDataDevice;
typedef struct _MetaWaylandBuffer MetaWaylandBuffer;
typedef struct _MetaWaylandBufferReference MetaWaylandBufferReference;
typedef struct _MetaWaylandRegion MetaWaylandRegion;
typedef struct _MetaWaylandSurface MetaWaylandSurface;

View File

@ -19,40 +19,26 @@
* 02111-1307, USA.
*/
#include <config.h>
#include "config.h"
#include "meta-wayland.h"
#include <clutter/clutter.h>
#include <clutter/wayland/clutter-wayland-compositor.h>
#include <clutter/wayland/clutter-wayland-surface.h>
#include <glib.h>
#include <sys/time.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <wayland-server.h>
#include <meta/meta-backend.h>
#include "meta-wayland-private.h"
#include "meta-xwayland-private.h"
#include "meta-window-actor-private.h"
#include "meta-wayland-region.h"
#include "meta-wayland-seat.h"
#include "meta-wayland-keyboard.h"
#include "meta-wayland-pointer.h"
#include "meta-wayland-outputs.h"
#include "meta-wayland-data-device.h"
#include "meta-cursor-tracker-private.h"
#include "display-private.h"
#include "window-private.h"
#include <meta/types.h>
#include <meta/main.h>
#include "frame.h"
static MetaWaylandCompositor _meta_wayland_compositor;
@ -70,6 +56,13 @@ get_time (void)
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
typedef struct
{
GSource source;
GPollFD pfd;
struct wl_display *display;
} WaylandEventSource;
static gboolean
wayland_event_source_prepare (GSource *base, int *timeout)
{
@ -126,61 +119,6 @@ wayland_event_source_new (struct wl_display *display)
return &source->source;
}
static void
meta_wayland_buffer_destroy_handler (struct wl_listener *listener,
void *data)
{
MetaWaylandBuffer *buffer =
wl_container_of (listener, buffer, destroy_listener);
wl_signal_emit (&buffer->destroy_signal, buffer);
g_slice_free (MetaWaylandBuffer, buffer);
}
void
meta_wayland_buffer_ref (MetaWaylandBuffer *buffer)
{
buffer->ref_count++;
}
void
meta_wayland_buffer_unref (MetaWaylandBuffer *buffer)
{
buffer->ref_count--;
if (buffer->ref_count == 0)
{
g_clear_pointer (&buffer->texture, cogl_object_unref);
wl_resource_queue_event (buffer->resource, WL_BUFFER_RELEASE);
}
}
MetaWaylandBuffer *
meta_wayland_buffer_from_resource (struct wl_resource *resource)
{
MetaWaylandBuffer *buffer;
struct wl_listener *listener;
listener =
wl_resource_get_destroy_listener (resource,
meta_wayland_buffer_destroy_handler);
if (listener)
{
buffer = wl_container_of (listener, buffer, destroy_listener);
}
else
{
buffer = g_slice_new0 (MetaWaylandBuffer);
buffer->resource = resource;
wl_signal_init (&buffer->destroy_signal);
buffer->destroy_listener.notify = meta_wayland_buffer_destroy_handler;
wl_resource_add_destroy_listener (resource, &buffer->destroy_listener);
}
return buffer;
}
void
meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,
MetaWindow *window)
@ -202,91 +140,23 @@ wl_compositor_create_surface (struct wl_client *client,
guint32 id)
{
MetaWaylandCompositor *compositor = wl_resource_get_user_data (resource);
meta_wayland_surface_create (compositor, client, resource, id);
}
static void
wl_region_destroy (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static void
wl_region_add (struct wl_client *client,
struct wl_resource *resource,
gint32 x,
gint32 y,
gint32 width,
gint32 height)
{
MetaWaylandRegion *region = wl_resource_get_user_data (resource);
cairo_rectangle_int_t rectangle = { x, y, width, height };
cairo_region_union_rectangle (region->region, &rectangle);
}
static void
wl_region_subtract (struct wl_client *client,
struct wl_resource *resource,
gint32 x,
gint32 y,
gint32 width,
gint32 height)
{
MetaWaylandRegion *region = wl_resource_get_user_data (resource);
cairo_rectangle_int_t rectangle = { x, y, width, height };
cairo_region_subtract_rectangle (region->region, &rectangle);
}
static const struct wl_region_interface meta_wayland_region_interface = {
wl_region_destroy,
wl_region_add,
wl_region_subtract
};
static void
meta_wayland_region_resource_destroy_cb (struct wl_resource *resource)
{
MetaWaylandRegion *region = wl_resource_get_user_data (resource);
cairo_region_destroy (region->region);
g_slice_free (MetaWaylandRegion, region);
}
static void
wl_compositor_create_region (struct wl_client *client,
struct wl_resource *compositor_resource,
struct wl_resource *resource,
uint32_t id)
{
MetaWaylandRegion *region = g_slice_new0 (MetaWaylandRegion);
region->resource = wl_resource_create (client, &wl_region_interface, wl_resource_get_version (compositor_resource), id);
wl_resource_set_implementation (region->resource, &meta_wayland_region_interface, region, meta_wayland_region_resource_destroy_cb);
region->region = cairo_region_create ();
MetaWaylandCompositor *compositor = wl_resource_get_user_data (resource);
meta_wayland_region_create (compositor, client, resource, id);
}
const static struct wl_compositor_interface meta_wayland_compositor_interface = {
const static struct wl_compositor_interface meta_wayland_wl_compositor_interface = {
wl_compositor_create_surface,
wl_compositor_create_region
};
void
meta_wayland_compositor_paint_finished (MetaWaylandCompositor *compositor)
{
while (!wl_list_empty (&compositor->frame_callbacks))
{
MetaWaylandFrameCallback *callback =
wl_container_of (compositor->frame_callbacks.next, callback, link);
wl_callback_send_done (callback->resource, get_time ());
wl_resource_destroy (callback->resource);
}
}
static void
compositor_bind (struct wl_client *client,
void *data,
@ -297,7 +167,7 @@ compositor_bind (struct wl_client *client,
struct wl_resource *resource;
resource = wl_resource_create (client, &wl_compositor_interface, version, id);
wl_resource_set_implementation (resource, &meta_wayland_compositor_interface, compositor, NULL);
wl_resource_set_implementation (resource, &meta_wayland_wl_compositor_interface, compositor, NULL);
}
/**
@ -316,6 +186,19 @@ meta_wayland_compositor_update (MetaWaylandCompositor *compositor,
meta_wayland_seat_update (compositor->seat, event);
}
void
meta_wayland_compositor_paint_finished (MetaWaylandCompositor *compositor)
{
while (!wl_list_empty (&compositor->frame_callbacks))
{
MetaWaylandFrameCallback *callback =
wl_container_of (compositor->frame_callbacks.next, callback, link);
wl_callback_send_done (callback->resource, get_time ());
wl_resource_destroy (callback->resource);
}
}
/**
* meta_wayland_compositor_handle_event:
* @compositor: the #MetaWaylandCompositor instance
@ -385,7 +268,6 @@ meta_wayland_pre_clutter_init (void)
meta_wayland_compositor_init (compositor);
/* Set up our logging. */
wl_log_set_handler_server (meta_wayland_log_func);
compositor->wayland_display = wl_display_create ();
@ -401,12 +283,6 @@ meta_wayland_init (void)
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
GSource *wayland_event_source;
if (!wl_global_create (compositor->wayland_display,
&wl_compositor_interface,
META_WL_COMPOSITOR_VERSION,
compositor, compositor_bind))
g_error ("Failed to register the global wl_compositor");
wayland_event_source = wayland_event_source_new (compositor->wayland_display);
/* XXX: Here we are setting the wayland event source to have a
@ -414,13 +290,16 @@ meta_wayland_init (void)
* much more likely to get confused being told about surface changes
* relating to X clients when we don't know what's happened to them
* according to the X protocol.
*
* At some point we could perhaps try and get the X protocol proxied
* over the wayland protocol so that we don't have to worry about
* synchronizing the two command streams. */
*/
g_source_set_priority (wayland_event_source, GDK_PRIORITY_EVENTS + 1);
g_source_attach (wayland_event_source, NULL);
if (!wl_global_create (compositor->wayland_display,
&wl_compositor_interface,
META_WL_COMPOSITOR_VERSION,
compositor, compositor_bind))
g_error ("Failed to register the global wl_compositor");
wl_display_init_shm (compositor->wayland_display);
meta_wayland_outputs_init (compositor);
@ -428,21 +307,10 @@ meta_wayland_init (void)
meta_wayland_shell_init (compositor);
meta_wayland_seat_init (compositor);
/* FIXME: find the first free name instead */
compositor->display_name = wl_display_add_socket_auto (compositor->wayland_display);
if (compositor->display_name == NULL)
g_error ("Failed to create socket");
/* XXX: It's important that we only try and start xwayland after we
* have initialized EGL because EGL implements the "wl_drm"
* interface which xwayland requires to determine what drm device
* name it should use.
*
* By waiting until we've shown the stage above we ensure that the
* underlying GL resources for the surface have also been allocated
* and so EGL must be initialized by this point.
*/
if (!meta_xwayland_start (&compositor->xwayland_manager, compositor->wayland_display))
g_error ("Failed to start X Wayland");

View File

@ -23,6 +23,8 @@
#ifndef META_WAYLAND_H
#define META_WAYLAND_H
#include <clutter/clutter.h>
#include <meta/types.h>
#include "meta-wayland-types.h"
void meta_wayland_pre_clutter_init (void);

View File

@ -509,8 +509,6 @@ meta_window_x11_manage (MetaWindow *window)
meta_icon_cache_init (&priv->icon_cache);
meta_display_register_x_window (display, &window->xwindow, window);
meta_window_x11_update_shape_region (window);
meta_window_x11_update_input_region (window);
/* assign the window to its group, or create a new group if needed */
window->group = NULL;
@ -568,6 +566,9 @@ meta_window_x11_manage (MetaWindow *window)
meta_window_client_rect_to_frame_rect (window, &rect, &rect);
meta_window_move_resize_internal (window, flags, gravity, rect);
}
meta_window_x11_update_shape_region (window);
meta_window_x11_update_input_region (window);
}
static void