Compare commits
82 Commits
wip/dnd-su
...
3.14.3
Author | SHA1 | Date | |
---|---|---|---|
fc1f78e8cc | |||
25aa942a0e | |||
56e74b1ea8 | |||
7d3204b196 | |||
d7ff632c67 | |||
6d3e64226d | |||
2e7b9e0dfe | |||
08d81b6f7f | |||
e01077914d | |||
d7cf6bed63 | |||
d071ba8446 | |||
4d08e89c16 | |||
21d8c4b032 | |||
c98686da92 | |||
a19eda5ae7 | |||
0a9bbe0109 | |||
a8eb42e43c | |||
9d0c9f1f42 | |||
9fa0743394 | |||
bb79a20fac | |||
3e511b9591 | |||
5664c703b7 | |||
5c80c4b006 | |||
22f91eba8d | |||
d07e2f4090 | |||
cd32e4a68a | |||
4040a70781 | |||
cb084cc841 | |||
2deea6e0a3 | |||
a116509301 | |||
ead79f834c | |||
7e431bd6bc | |||
272e1fb296 | |||
c39f18c2d4 | |||
33acb5fea0 | |||
591718dc02 | |||
b6127eeda4 | |||
eeff1b8b02 | |||
354cc466af | |||
9f5c38d121 | |||
ead0e902ed | |||
5d16194b03 | |||
a74acf0ec2 | |||
3044cfb7bf | |||
f658740043 | |||
c1613a16c0 | |||
8e85015f91 | |||
f127ee3bde | |||
acd928044f | |||
4ef2f2ce09 | |||
bc81736e6b | |||
49092397f2 | |||
97705d3cfe | |||
0364ea9140 | |||
c0bdb3018b | |||
924eaac358 | |||
a9f5a5661f | |||
9c589b6798 | |||
113be01ce8 | |||
28e59c5a8f | |||
b588baf9f5 | |||
9a825d9bee | |||
f211b3ec90 | |||
0510c3a621 | |||
18db5d0799 | |||
c061e26da5 | |||
166668adc4 | |||
ec797b055d | |||
082cc9c83a | |||
993bec37d7 | |||
e496ed50d6 | |||
a127d05790 | |||
607730e96c | |||
9203db0655 | |||
64d40792c4 | |||
e7356917b0 | |||
fa58752276 | |||
478b75e803 | |||
492a1b244f | |||
5d8ff2e34d | |||
310083aeb2 | |||
0faa900207 |
54
NEWS
54
NEWS
@ -1,3 +1,57 @@
|
||||
3.14.3
|
||||
======
|
||||
* Fix crash when trying to unredirect a destroyed window [Florian; #740133]
|
||||
* Fix "flicker" during startup transition [Ray; #740377]
|
||||
* Don't leave left-over frames queued [Owen; #738686]
|
||||
* Set CRTC configuration even if it might be redundant [Rui; #740838]
|
||||
|
||||
Contributors:
|
||||
Rui Matos, Florian Müllner, Jasper St. Pierre, Ray Strode, Owen W. Taylor
|
||||
|
||||
3.14.2
|
||||
======
|
||||
* Prevent crash applying monitor config for a closed lid [Rui; #739450]
|
||||
* Misc. fixes [Rui, Jonathon, Jasper; #738630]
|
||||
|
||||
Contributors:
|
||||
Jonathon Jongsma, Rui Matos, Jasper St. Pierre
|
||||
|
||||
3.14.1.5
|
||||
========
|
||||
* Fix wayland hiDPI regressions [Adel; #739161]
|
||||
|
||||
Contributors:
|
||||
Adel Gadllah, Florian Müllner, Jasper St. Pierre
|
||||
|
||||
Translations:
|
||||
Dušan Kazik [sk]
|
||||
|
||||
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]
|
||||
|
@ -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], [3])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
@ -77,9 +77,7 @@ 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
|
||||
gnome-desktop-3.0
|
||||
xcomposite >= 0.2
|
||||
@ -202,7 +200,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 gbm >= 10.3], [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
|
||||
|
@ -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 \
|
||||
|
@ -29,8 +29,11 @@
|
||||
|
||||
typedef struct {
|
||||
CoglTexture2D *texture;
|
||||
struct gbm_bo *bo;
|
||||
int hot_x, hot_y;
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
struct gbm_bo *bo;
|
||||
#endif
|
||||
} MetaCursorImage;
|
||||
|
||||
struct _MetaCursorReference {
|
||||
@ -44,8 +47,10 @@ CoglTexture *meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor
|
||||
int *hot_x,
|
||||
int *hot_y);
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
struct gbm_bo *meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
|
||||
int *hot_x,
|
||||
int *hot_y);
|
||||
#endif
|
||||
|
||||
#endif /* META_CURSOR_PRIVATE_H */
|
||||
|
@ -56,8 +56,11 @@ static void
|
||||
meta_cursor_image_free (MetaCursorImage *image)
|
||||
{
|
||||
cogl_object_unref (image->texture);
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
if (image->bo)
|
||||
gbm_bo_destroy (image->bo);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
@ -139,10 +142,10 @@ load_cursor_on_client (MetaCursor cursor)
|
||||
meta_prefs_get_cursor_size ());
|
||||
}
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
static void
|
||||
get_hardware_cursor_size (uint64_t *cursor_width, uint64_t *cursor_height)
|
||||
{
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
MetaBackend *meta_backend = meta_get_backend ();
|
||||
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
|
||||
|
||||
@ -151,11 +154,12 @@ get_hardware_cursor_size (uint64_t *cursor_width, uint64_t *cursor_height)
|
||||
meta_cursor_renderer_native_get_cursor_size (META_CURSOR_RENDERER_NATIVE (renderer), cursor_width, cursor_height);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
static void
|
||||
meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
|
||||
MetaCursorImage *image,
|
||||
@ -193,20 +197,21 @@ meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
|
||||
else
|
||||
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
static struct gbm_device *
|
||||
get_gbm_device (void)
|
||||
{
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
MetaBackend *meta_backend = meta_get_backend ();
|
||||
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
|
||||
|
||||
if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
|
||||
return meta_cursor_renderer_native_get_gbm_device (META_CURSOR_RENDERER_NATIVE (renderer));
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
|
||||
@ -214,16 +219,13 @@ meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
|
||||
{
|
||||
uint width, height, rowstride;
|
||||
CoglPixelFormat cogl_format;
|
||||
uint32_t gbm_format;
|
||||
ClutterBackend *clutter_backend;
|
||||
CoglContext *cogl_context;
|
||||
struct gbm_device *gbm;
|
||||
|
||||
width = xc_image->width;
|
||||
height = xc_image->height;
|
||||
rowstride = width * 4;
|
||||
|
||||
gbm_format = GBM_FORMAT_ARGB8888;
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
|
||||
#else
|
||||
@ -242,13 +244,15 @@ meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
|
||||
(uint8_t *) xc_image->pixels,
|
||||
NULL);
|
||||
|
||||
gbm = get_gbm_device ();
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
struct gbm_device *gbm = get_gbm_device ();
|
||||
if (gbm)
|
||||
meta_cursor_image_load_gbm_buffer (gbm,
|
||||
image,
|
||||
(uint8_t *) xc_image->pixels,
|
||||
width, height, rowstride,
|
||||
gbm_format);
|
||||
GBM_FORMAT_ARGB8888);
|
||||
#endif
|
||||
}
|
||||
|
||||
MetaCursorReference *
|
||||
@ -277,14 +281,8 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
|
||||
int hot_x,
|
||||
int hot_y)
|
||||
{
|
||||
struct gbm_device *gbm = get_gbm_device ();
|
||||
|
||||
ClutterBackend *backend;
|
||||
CoglContext *cogl_context;
|
||||
struct wl_shm_buffer *shm_buffer;
|
||||
uint32_t gbm_format;
|
||||
uint64_t cursor_width, cursor_height;
|
||||
uint width, height;
|
||||
|
||||
image->hot_x = hot_x;
|
||||
image->hot_y = hot_y;
|
||||
@ -294,13 +292,19 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
|
||||
|
||||
image->texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL);
|
||||
|
||||
width = cogl_texture_get_width (COGL_TEXTURE (image->texture));
|
||||
height = cogl_texture_get_height (COGL_TEXTURE (image->texture));
|
||||
|
||||
shm_buffer = wl_shm_buffer_get (buffer);
|
||||
if (shm_buffer)
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
struct gbm_device *gbm = get_gbm_device ();
|
||||
if (gbm)
|
||||
{
|
||||
if (gbm)
|
||||
uint32_t gbm_format;
|
||||
uint64_t cursor_width, cursor_height;
|
||||
uint width, height;
|
||||
|
||||
width = cogl_texture_get_width (COGL_TEXTURE (image->texture));
|
||||
height = cogl_texture_get_height (COGL_TEXTURE (image->texture));
|
||||
|
||||
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (buffer);
|
||||
if (shm_buffer)
|
||||
{
|
||||
int rowstride = wl_shm_buffer_get_stride (shm_buffer);
|
||||
|
||||
@ -332,10 +336,7 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
|
||||
width, height, rowstride,
|
||||
gbm_format);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gbm)
|
||||
else
|
||||
{
|
||||
/* HW cursors have a predefined size (at least 64x64), which usually is bigger than cursor theme
|
||||
size, so themed cursors must be padded with transparent pixels to fill the
|
||||
@ -356,6 +357,7 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
|
||||
meta_warning ("Importing HW cursor from wl_buffer failed\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
MetaCursorReference *
|
||||
@ -385,6 +387,7 @@ meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor,
|
||||
return COGL_TEXTURE (cursor->image.texture);
|
||||
}
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
struct gbm_bo *
|
||||
meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
|
||||
int *hot_x,
|
||||
@ -396,6 +399,7 @@ meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
|
||||
*hot_y = cursor->image.hot_y;
|
||||
return cursor->image.bo;
|
||||
}
|
||||
#endif
|
||||
|
||||
MetaCursor
|
||||
meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor)
|
||||
|
@ -796,27 +796,6 @@ make_config_key (MetaConfiguration *key,
|
||||
key->n_outputs = o;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_monitor_config_match_current (MetaMonitorConfig *self,
|
||||
MetaMonitorManager *manager)
|
||||
{
|
||||
MetaOutput *outputs;
|
||||
unsigned n_outputs;
|
||||
MetaConfiguration key;
|
||||
gboolean ok;
|
||||
|
||||
if (self->current == NULL)
|
||||
return FALSE;
|
||||
|
||||
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
|
||||
|
||||
make_config_key (&key, outputs, n_outputs, -1);
|
||||
ok = config_equal (&key, self->current);
|
||||
|
||||
config_clear (&key);
|
||||
return ok;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager)
|
||||
{
|
||||
@ -945,6 +924,19 @@ laptop_display_is_on (MetaConfiguration *config)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
multiple_outputs_are_enabled (MetaConfiguration *config)
|
||||
{
|
||||
unsigned int i, enabled;
|
||||
|
||||
enabled = 0;
|
||||
for (i = 0; i < config->n_outputs; i++)
|
||||
if (config->outputs[i].enabled)
|
||||
enabled++;
|
||||
|
||||
return enabled > 1;
|
||||
}
|
||||
|
||||
static MetaConfiguration *
|
||||
make_laptop_lid_config (MetaConfiguration *reference)
|
||||
{
|
||||
@ -954,7 +946,7 @@ make_laptop_lid_config (MetaConfiguration *reference)
|
||||
int x_after, y_after;
|
||||
int x_offset, y_offset;
|
||||
|
||||
g_assert (reference->n_outputs > 1);
|
||||
g_assert (multiple_outputs_are_enabled (reference));
|
||||
|
||||
new = g_slice_new0 (MetaConfiguration);
|
||||
new->n_outputs = reference->n_outputs;
|
||||
@ -1025,7 +1017,7 @@ meta_monitor_config_apply_stored (MetaMonitorConfig *self,
|
||||
if (stored)
|
||||
{
|
||||
if (self->lid_is_closed &&
|
||||
stored->n_outputs > 1 &&
|
||||
multiple_outputs_are_enabled (stored) &&
|
||||
laptop_display_is_on (stored))
|
||||
{
|
||||
if (apply_configuration (self, make_laptop_lid_config (stored),
|
||||
@ -1287,7 +1279,7 @@ meta_monitor_config_make_default (MetaMonitorConfig *self,
|
||||
if (default_config != NULL)
|
||||
{
|
||||
if (self->lid_is_closed &&
|
||||
default_config->n_outputs > 1 &&
|
||||
multiple_outputs_are_enabled (default_config) &&
|
||||
laptop_display_is_on (default_config))
|
||||
{
|
||||
ok = apply_configuration (self, make_laptop_lid_config (default_config),
|
||||
@ -1378,7 +1370,7 @@ turn_off_laptop_display (MetaMonitorConfig *self,
|
||||
{
|
||||
MetaConfiguration *new;
|
||||
|
||||
if (self->current->n_outputs == 1)
|
||||
if (!multiple_outputs_are_enabled (self->current))
|
||||
return;
|
||||
|
||||
new = make_laptop_lid_config (self->current);
|
||||
|
@ -36,9 +36,6 @@ GType meta_monitor_config_get_type (void) G_GNUC_CONST;
|
||||
|
||||
MetaMonitorConfig *meta_monitor_config_new (void);
|
||||
|
||||
gboolean meta_monitor_config_match_current (MetaMonitorConfig *config,
|
||||
MetaMonitorManager *manager);
|
||||
|
||||
gboolean meta_monitor_config_apply_stored (MetaMonitorConfig *config,
|
||||
MetaMonitorManager *manager);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -140,6 +140,30 @@ meta_monitor_transform_from_xrandr_all (Rotation rotation)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
output_get_property_exists (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output, const char *propname)
|
||||
{
|
||||
gboolean exists = FALSE;
|
||||
Atom atom, actual_type;
|
||||
int actual_format;
|
||||
unsigned long nitems, bytes_after;
|
||||
unsigned char *buffer;
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, propname, False);
|
||||
XRRGetOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->winsys_id,
|
||||
atom,
|
||||
0, G_MAXLONG, False, False, AnyPropertyType,
|
||||
&actual_type, &actual_format,
|
||||
&nitems, &bytes_after, &buffer);
|
||||
|
||||
exists = (actual_type != None);
|
||||
|
||||
XFree (buffer);
|
||||
return exists;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
output_get_boolean_property (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output, const char *propname)
|
||||
@ -330,7 +354,7 @@ static gboolean
|
||||
output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output)
|
||||
{
|
||||
return output_get_boolean_property (manager_xrandr, output, "hotplug_mode_update");
|
||||
return output_get_property_exists (manager_xrandr, output, "hotplug_mode_update");
|
||||
}
|
||||
|
||||
static char *
|
||||
@ -814,26 +838,12 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
unsigned int j, n_outputs;
|
||||
int width, height;
|
||||
Status ok;
|
||||
unsigned long old_controlled_mask;
|
||||
unsigned long new_controlled_mask;
|
||||
|
||||
mode = crtc_info->mode;
|
||||
|
||||
n_outputs = crtc_info->outputs->len;
|
||||
outputs = g_new (XID, n_outputs);
|
||||
|
||||
old_controlled_mask = 0;
|
||||
for (j = 0; j < manager->n_outputs; j++)
|
||||
{
|
||||
MetaOutput *output;
|
||||
|
||||
output = &manager->outputs[j];
|
||||
|
||||
if (output->crtc == crtc)
|
||||
old_controlled_mask |= 1UL << j;
|
||||
}
|
||||
|
||||
new_controlled_mask = 0;
|
||||
for (j = 0; j < n_outputs; j++)
|
||||
{
|
||||
MetaOutput *output;
|
||||
@ -842,21 +852,10 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
|
||||
output->is_dirty = TRUE;
|
||||
output->crtc = crtc;
|
||||
new_controlled_mask |= 1UL << j;
|
||||
|
||||
outputs[j] = output->winsys_id;
|
||||
}
|
||||
|
||||
if (crtc->current_mode == mode &&
|
||||
crtc->rect.x == crtc_info->x &&
|
||||
crtc->rect.y == crtc_info->y &&
|
||||
crtc->transform == crtc_info->transform &&
|
||||
old_controlled_mask == new_controlled_mask)
|
||||
{
|
||||
/* No change */
|
||||
goto next;
|
||||
}
|
||||
|
||||
ok = XRRSetCrtcConfig (manager_xrandr->xdisplay,
|
||||
manager_xrandr->resources,
|
||||
(XID)crtc->crtc_id,
|
||||
@ -1075,6 +1074,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 +1091,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)
|
||||
{
|
||||
/* 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);
|
||||
|
@ -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;
|
||||
|
@ -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 ())
|
||||
{
|
||||
|
@ -708,6 +708,7 @@ on_background_changed (MetaBackground *background,
|
||||
MetaBackgroundActor *self)
|
||||
{
|
||||
invalidate_pipeline (self, CHANGED_BACKGROUND);
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
|
||||
}
|
||||
|
||||
void
|
||||
|
64
src/compositor/meta-dnd-actor-private.h
Normal file
64
src/compositor/meta-dnd-actor-private.h
Normal 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 */
|
231
src/compositor/meta-dnd-actor.c
Normal file
231
src/compositor/meta-dnd-actor.c
Normal 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);
|
||||
}
|
||||
}
|
74
src/compositor/meta-feedback-actor-private.h
Normal file
74
src/compositor/meta-feedback-actor-private.h
Normal 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 */
|
249
src/compositor/meta-feedback-actor.c
Normal file
249
src/compositor/meta-feedback-actor.c
Normal 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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ struct _MetaWindowActorPrivate
|
||||
guint disposed : 1;
|
||||
|
||||
/* If set, the client needs to be sent a _NET_WM_FRAME_DRAWN
|
||||
* client message using the most recent frame in ->frames */
|
||||
* client message for one or more messages in ->frames */
|
||||
guint needs_frame_drawn : 1;
|
||||
guint repaint_scheduled : 1;
|
||||
|
||||
@ -118,10 +118,21 @@ struct _MetaWindowActorPrivate
|
||||
|
||||
typedef struct _FrameData FrameData;
|
||||
|
||||
/* Each time the application updates the sync request counter to a new even value
|
||||
* value, we queue a frame into the windows list of frames. Once we're painting
|
||||
* an update "in response" to the window, we fill in frame_counter with the
|
||||
* Cogl counter for that frame, and send _NET_WM_FRAME_DRAWN at the end of the
|
||||
* frame. _NET_WM_FRAME_TIMINGS is sent when we get a frame_complete callback.
|
||||
*
|
||||
* As an exception, if a window is completely obscured, we try to throttle drawning
|
||||
* to a slower frame rate. In this case, frame_counter stays -1 until
|
||||
* send_frame_message_timeout() runs, at which point we send both the
|
||||
* _NET_WM_FRAME_DRAWN and _NET_WM_FRAME_TIMINGS messages.
|
||||
*/
|
||||
struct _FrameData
|
||||
{
|
||||
int64_t frame_counter;
|
||||
guint64 sync_request_serial;
|
||||
int64_t frame_counter;
|
||||
gint64 frame_drawn_time;
|
||||
};
|
||||
|
||||
@ -655,6 +666,30 @@ clip_shadow_under_window (MetaWindowActor *self)
|
||||
return is_non_opaque (self) && priv->window->frame;
|
||||
}
|
||||
|
||||
static void
|
||||
assign_frame_counter_to_frames (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
GList *l;
|
||||
|
||||
/* If the window is obscured, then we're expecting to deal with sending
|
||||
* frame messages in a timeout, rather than in this paint cycle.
|
||||
*/
|
||||
if (priv->send_frame_messages_timer != 0)
|
||||
return;
|
||||
|
||||
for (l = priv->frames; l; l = l->next)
|
||||
{
|
||||
FrameData *frame = l->data;
|
||||
|
||||
if (frame->frame_counter == -1)
|
||||
{
|
||||
CoglOnscreen *onscreen = COGL_ONSCREEN (cogl_get_draw_framebuffer());
|
||||
frame->frame_counter = cogl_onscreen_get_frame_counter (onscreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_actor_paint (ClutterActor *actor)
|
||||
{
|
||||
@ -671,6 +706,8 @@ meta_window_actor_paint (ClutterActor *actor)
|
||||
{
|
||||
g_source_remove (priv->send_frame_messages_timer);
|
||||
priv->send_frame_messages_timer = 0;
|
||||
|
||||
assign_frame_counter_to_frames (self);
|
||||
}
|
||||
|
||||
if (shadow != NULL)
|
||||
@ -873,16 +910,27 @@ send_frame_messages_timeout (gpointer data)
|
||||
{
|
||||
MetaWindowActor *self = (MetaWindowActor *) data;
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
FrameData *frame = g_slice_new0 (FrameData);
|
||||
GList *l;
|
||||
|
||||
frame->sync_request_serial = priv->window->sync_request_serial;
|
||||
for (l = priv->frames; l;)
|
||||
{
|
||||
GList *l_next = l->next;
|
||||
FrameData *frame = l->data;
|
||||
|
||||
do_send_frame_drawn (self, frame);
|
||||
do_send_frame_timings (self, frame, 0, 0);
|
||||
if (frame->frame_counter == -1)
|
||||
{
|
||||
do_send_frame_drawn (self, frame);
|
||||
do_send_frame_timings (self, frame, 0, 0);
|
||||
|
||||
priv->frames = g_list_delete_link (priv->frames, l);
|
||||
frame_data_free (frame);
|
||||
}
|
||||
|
||||
l = l_next;
|
||||
}
|
||||
|
||||
priv->needs_frame_drawn = FALSE;
|
||||
priv->send_frame_messages_timer = 0;
|
||||
frame_data_free (frame);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@ -891,6 +939,10 @@ static void
|
||||
queue_send_frame_messages_timeout (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
if (priv->send_frame_messages_timer != 0)
|
||||
return;
|
||||
|
||||
MetaDisplay *display = meta_window_get_display (priv->window);
|
||||
gint64 current_time = meta_compositor_monotonic_time_to_server_time (display, g_get_monotonic_time ());
|
||||
MetaMonitorManager *monitor_manager = meta_monitor_manager_get ();
|
||||
@ -933,6 +985,7 @@ meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
|
||||
return;
|
||||
|
||||
frame = g_slice_new0 (FrameData);
|
||||
frame->frame_counter = -1;
|
||||
|
||||
priv->needs_frame_drawn = TRUE;
|
||||
|
||||
@ -1155,7 +1208,7 @@ gboolean
|
||||
meta_window_actor_should_unredirect (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
if (priv->surface)
|
||||
if (!meta_window_actor_is_destroyed (self) && priv->surface)
|
||||
return meta_surface_actor_should_unredirect (priv->surface);
|
||||
else
|
||||
return FALSE;
|
||||
@ -1905,24 +1958,12 @@ meta_window_actor_handle_updates (MetaWindowActor *self)
|
||||
void
|
||||
meta_window_actor_pre_paint (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
GList *l;
|
||||
|
||||
if (meta_window_actor_is_destroyed (self))
|
||||
return;
|
||||
|
||||
meta_window_actor_handle_updates (self);
|
||||
|
||||
for (l = priv->frames; l != NULL; l = l->next)
|
||||
{
|
||||
FrameData *frame = l->data;
|
||||
|
||||
if (frame->frame_counter == 0)
|
||||
{
|
||||
CoglOnscreen *onscreen = COGL_ONSCREEN (cogl_get_draw_framebuffer());
|
||||
frame->frame_counter = cogl_onscreen_get_frame_counter (onscreen);
|
||||
}
|
||||
}
|
||||
assign_frame_counter_to_frames (self);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1963,16 +2004,23 @@ meta_window_actor_post_paint (MetaWindowActor *self)
|
||||
if (meta_window_actor_is_destroyed (self))
|
||||
return;
|
||||
|
||||
/* This window had damage, but wasn't actually redrawn because
|
||||
* it is obscured. So we should wait until timer expiration
|
||||
* before sending _NET_WM_FRAME_* messages.
|
||||
*/
|
||||
if (priv->send_frame_messages_timer != 0)
|
||||
return;
|
||||
|
||||
if (priv->needs_frame_drawn)
|
||||
/* If the window had damage, but wasn't actually redrawn because
|
||||
* it is obscured, we should wait until timer expiration before
|
||||
* sending _NET_WM_FRAME_* messages.
|
||||
*/
|
||||
if (priv->send_frame_messages_timer == 0 &&
|
||||
priv->needs_frame_drawn)
|
||||
{
|
||||
do_send_frame_drawn (self, priv->frames->data);
|
||||
GList *l;
|
||||
|
||||
for (l = priv->frames; l; l = l->next)
|
||||
{
|
||||
FrameData *frame = l->data;
|
||||
|
||||
if (frame->frame_drawn_time == 0)
|
||||
do_send_frame_drawn (self, frame);
|
||||
}
|
||||
|
||||
priv->needs_frame_drawn = FALSE;
|
||||
}
|
||||
|
||||
@ -2057,15 +2105,20 @@ meta_window_actor_frame_complete (MetaWindowActor *self,
|
||||
{
|
||||
GList *l_next = l->next;
|
||||
FrameData *frame = l->data;
|
||||
gint64 frame_counter = cogl_frame_info_get_frame_counter (frame_info);
|
||||
|
||||
if (frame->frame_counter == cogl_frame_info_get_frame_counter (frame_info))
|
||||
if (frame->frame_counter != -1 && frame->frame_counter <= frame_counter)
|
||||
{
|
||||
if (frame->frame_drawn_time != 0)
|
||||
{
|
||||
priv->frames = g_list_delete_link (priv->frames, l);
|
||||
send_frame_timings (self, frame, frame_info, presentation_time);
|
||||
frame_data_free (frame);
|
||||
}
|
||||
if (G_UNLIKELY (frame->frame_drawn_time == 0))
|
||||
g_warning ("%s: Frame has assigned frame counter but no frame drawn time",
|
||||
priv->window->desc);
|
||||
if (G_UNLIKELY (frame->frame_counter < frame_counter))
|
||||
g_warning ("%s: frame_complete callback never occurred for frame %" G_GINT64_FORMAT,
|
||||
priv->window->desc, frame->frame_counter);
|
||||
|
||||
priv->frames = g_list_delete_link (priv->frames, l);
|
||||
send_frame_timings (self, frame, frame_info, presentation_time);
|
||||
frame_data_free (frame);
|
||||
}
|
||||
|
||||
l = l_next;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 ||
|
||||
@ -1965,7 +1965,7 @@ meta_display_end_grab_op (MetaDisplay *display,
|
||||
* beginning of the grab_op.
|
||||
*/
|
||||
if (!meta_prefs_get_raise_on_click () &&
|
||||
display->grab_threshold_movement_reached)
|
||||
!display->grab_threshold_movement_reached)
|
||||
meta_window_raise (display->grab_window);
|
||||
|
||||
meta_window_grab_op_ended (grab_window, grab_op);
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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,
|
||||
|
@ -496,15 +496,6 @@ create_guard_window (Display *xdisplay, MetaScreen *screen)
|
||||
return guard_window;
|
||||
}
|
||||
|
||||
/* Set a black background on the root window so that we don't
|
||||
* see confusing old copies of old windows when debugging
|
||||
* and testing. */
|
||||
static void
|
||||
meta_screen_set_background (MetaScreen *screen)
|
||||
{
|
||||
XSetWindowBackground (screen->display->xdisplay, screen->xroot, 0x00000000);
|
||||
}
|
||||
|
||||
MetaScreen*
|
||||
meta_screen_new (MetaDisplay *display,
|
||||
int number,
|
||||
@ -709,7 +700,6 @@ meta_screen_new (MetaDisplay *display,
|
||||
reload_monitor_infos (screen);
|
||||
|
||||
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
|
||||
meta_screen_set_background (screen);
|
||||
|
||||
/* Handle creating a no_focus_window for this screen */
|
||||
screen->no_focus_window =
|
||||
@ -3021,38 +3011,32 @@ static gboolean
|
||||
check_fullscreen_func (gpointer data)
|
||||
{
|
||||
MetaScreen *screen = data;
|
||||
GSList *windows;
|
||||
GSList *tmp;
|
||||
MetaWindow *window;
|
||||
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 +3046,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 +3067,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++)
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
137
src/wayland/meta-wayland-buffer.c
Normal file
137
src/wayland/meta-wayland-buffer.c
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
51
src/wayland/meta-wayland-buffer.h
Normal file
51
src/wayland/meta-wayland-buffer.h
Normal 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 */
|
@ -34,6 +34,7 @@
|
||||
#include "meta-wayland-seat.h"
|
||||
#include "meta-wayland-pointer.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-dnd-actor-private.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -46,6 +47,7 @@ struct _MetaWaylandDataSource
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
struct wl_array mime_types;
|
||||
gboolean has_target;
|
||||
};
|
||||
|
||||
static void
|
||||
@ -67,7 +69,10 @@ data_offer_accept (struct wl_client *client,
|
||||
* this be a wl_data_device request? */
|
||||
|
||||
if (offer->source)
|
||||
wl_data_source_send_target (offer->source->resource, mime_type);
|
||||
{
|
||||
wl_data_source_send_target (offer->source->resource, mime_type);
|
||||
offer->source->has_target = mime_type != NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -162,7 +167,7 @@ static struct wl_data_source_interface data_source_interface = {
|
||||
data_source_destroy
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
struct _MetaWaylandDragGrab {
|
||||
MetaWaylandPointerGrab generic;
|
||||
|
||||
MetaWaylandSeat *seat;
|
||||
@ -177,7 +182,14 @@ typedef struct {
|
||||
|
||||
MetaWaylandDataSource *drag_data_source;
|
||||
struct wl_listener drag_data_source_listener;
|
||||
} MetaWaylandDragGrab;
|
||||
|
||||
ClutterActor *feedback_actor;
|
||||
|
||||
MetaWaylandSurface *drag_origin;
|
||||
struct wl_listener drag_origin_listener;
|
||||
|
||||
int drag_start_x, drag_start_y;
|
||||
};
|
||||
|
||||
static void
|
||||
destroy_drag_focus (struct wl_listener *listener, void *data)
|
||||
@ -257,11 +269,21 @@ drag_grab_motion (MetaWaylandPointerGrab *grab,
|
||||
clutter_event_get_time (event),
|
||||
sx, sy);
|
||||
}
|
||||
|
||||
if (drag_grab->drag_surface)
|
||||
meta_feedback_actor_update (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
|
||||
event);
|
||||
}
|
||||
|
||||
static void
|
||||
data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
|
||||
{
|
||||
if (drag_grab->drag_origin)
|
||||
{
|
||||
drag_grab->drag_origin = NULL;
|
||||
wl_list_remove (&drag_grab->drag_origin_listener.link);
|
||||
}
|
||||
|
||||
if (drag_grab->drag_surface)
|
||||
{
|
||||
drag_grab->drag_surface = NULL;
|
||||
@ -269,7 +291,18 @@ data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
|
||||
}
|
||||
|
||||
if (drag_grab->drag_data_source)
|
||||
wl_list_remove (&drag_grab->drag_data_source_listener.link);
|
||||
{
|
||||
drag_grab->drag_data_source->has_target = FALSE;
|
||||
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);
|
||||
|
||||
@ -285,10 +318,23 @@ drag_grab_button (MetaWaylandPointerGrab *grab,
|
||||
MetaWaylandSeat *seat = drag_grab->seat;
|
||||
ClutterEventType event_type = clutter_event_type (event);
|
||||
|
||||
if (drag_grab->drag_focus_data_device &&
|
||||
drag_grab->generic.pointer->grab_button == clutter_event_get_button (event) &&
|
||||
if (drag_grab->generic.pointer->grab_button == clutter_event_get_button (event) &&
|
||||
event_type == CLUTTER_BUTTON_RELEASE)
|
||||
wl_data_device_send_drop (drag_grab->drag_focus_data_device);
|
||||
{
|
||||
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);
|
||||
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 &&
|
||||
event_type == CLUTTER_BUTTON_RELEASE)
|
||||
@ -301,6 +347,16 @@ static const MetaWaylandPointerGrabInterface drag_grab_interface = {
|
||||
drag_grab_button,
|
||||
};
|
||||
|
||||
static void
|
||||
destroy_data_device_origin (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandDragGrab *drag_grab =
|
||||
wl_container_of (listener, drag_grab, drag_origin_listener);
|
||||
|
||||
drag_grab->drag_origin = NULL;
|
||||
data_device_end_drag_grab (drag_grab);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_data_device_source (struct wl_listener *listener, void *data)
|
||||
{
|
||||
@ -318,6 +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;
|
||||
|
||||
if (drag_grab->feedback_actor)
|
||||
clutter_actor_remove_all_children (drag_grab->feedback_actor);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -329,20 +388,29 @@ data_device_start_drag (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
||||
MetaWaylandSurface *surface = NULL;
|
||||
MetaWaylandDragGrab *drag_grab;
|
||||
ClutterPoint pos;
|
||||
|
||||
if ((seat->pointer.button_count == 0 ||
|
||||
seat->pointer.grab_serial != serial ||
|
||||
!seat->pointer.focus_surface ||
|
||||
seat->pointer.focus_surface != wl_resource_get_user_data (origin_resource)))
|
||||
if (origin_resource)
|
||||
surface = wl_resource_get_user_data (origin_resource);
|
||||
|
||||
if (!surface)
|
||||
return;
|
||||
|
||||
if (seat->pointer.button_count == 0 ||
|
||||
seat->pointer.grab_serial != serial ||
|
||||
!seat->pointer.focus_surface ||
|
||||
seat->pointer.focus_surface != surface)
|
||||
return;
|
||||
|
||||
/* FIXME: Check that the data source type array isn't empty. */
|
||||
|
||||
if (seat->pointer.grab != &seat->pointer.default_grab)
|
||||
if (data_device->current_grab ||
|
||||
seat->pointer.grab != &seat->pointer.default_grab)
|
||||
return;
|
||||
|
||||
drag_grab = g_slice_new0 (MetaWaylandDragGrab);
|
||||
data_device->current_grab = drag_grab = g_slice_new0 (MetaWaylandDragGrab);
|
||||
|
||||
drag_grab->generic.interface = &drag_grab_interface;
|
||||
drag_grab->generic.pointer = &seat->pointer;
|
||||
@ -350,6 +418,17 @@ data_device_start_drag (struct wl_client *client,
|
||||
drag_grab->drag_client = client;
|
||||
drag_grab->seat = seat;
|
||||
|
||||
drag_grab->drag_origin = surface;
|
||||
drag_grab->drag_origin_listener.notify = destroy_data_device_origin;
|
||||
wl_resource_add_destroy_listener (origin_resource,
|
||||
&drag_grab->drag_origin_listener);
|
||||
|
||||
clutter_input_device_get_coords (seat->pointer.device, NULL, &pos);
|
||||
clutter_actor_transform_stage_point (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface->surface_actor)),
|
||||
pos.x, pos.y, &pos.x, &pos.y);
|
||||
drag_grab->drag_start_x = pos.x;
|
||||
drag_grab->drag_start_y = pos.y;
|
||||
|
||||
if (source_resource)
|
||||
{
|
||||
drag_grab->drag_data_source = wl_resource_get_user_data (source_resource);
|
||||
@ -364,6 +443,19 @@ 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);
|
||||
@ -551,3 +643,29 @@ meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_device)
|
||||
wl_data_device_send_selection (data_device_resource, offer);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_data_device_is_dnd_surface (MetaWaylandDataDevice *data_device,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
return data_device->current_grab &&
|
||||
data_device->current_grab->drag_surface == surface;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_device_update_dnd_surface (MetaWaylandDataDevice *data_device)
|
||||
{
|
||||
MetaWaylandDragGrab *drag_grab;
|
||||
|
||||
if (!data_device->current_grab)
|
||||
return;
|
||||
|
||||
drag_grab = data_device->current_grab;
|
||||
|
||||
if (!drag_grab->feedback_actor || !drag_grab->drag_surface)
|
||||
return;
|
||||
|
||||
meta_feedback_actor_set_anchor (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
|
||||
-drag_grab->drag_surface->offset_x,
|
||||
-drag_grab->drag_surface->offset_y);
|
||||
}
|
||||
|
@ -27,12 +27,15 @@
|
||||
|
||||
#include "meta-wayland-types.h"
|
||||
|
||||
typedef struct _MetaWaylandDragGrab MetaWaylandDragGrab;
|
||||
|
||||
struct _MetaWaylandDataDevice
|
||||
{
|
||||
uint32_t selection_serial;
|
||||
MetaWaylandDataSource *selection_data_source;
|
||||
struct wl_listener selection_data_source_listener;
|
||||
struct wl_list resource_list;
|
||||
MetaWaylandDragGrab *current_grab;
|
||||
};
|
||||
|
||||
void meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor);
|
||||
@ -41,4 +44,8 @@ void meta_wayland_data_device_init (MetaWaylandDataDevice *data_device);
|
||||
|
||||
void meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_device);
|
||||
|
||||
gboolean meta_wayland_data_device_is_dnd_surface (MetaWaylandDataDevice *data_device,
|
||||
MetaWaylandSurface *surface);
|
||||
void meta_wayland_data_device_update_dnd_surface (MetaWaylandDataDevice *data_device);
|
||||
|
||||
#endif /* META_WAYLAND_DATA_DEVICE_H */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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"
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -545,6 +540,8 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
meta_wayland_pointer_update_cursor_surface (pointer);
|
||||
}
|
||||
|
||||
void
|
||||
@ -569,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 {
|
||||
@ -718,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;
|
||||
@ -753,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
|
||||
|
@ -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 */
|
||||
|
105
src/wayland/meta-wayland-region.c
Normal file
105
src/wayland/meta-wayland-region.c
Normal 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;
|
||||
}
|
40
src/wayland/meta-wayland-region.h
Normal file
40
src/wayland/meta-wayland-region.h
Normal 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 */
|
@ -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)
|
||||
@ -175,6 +137,13 @@ cursor_surface_commit (MetaWaylandSurface *surface,
|
||||
meta_wayland_seat_update_cursor_surface (surface->compositor->seat);
|
||||
}
|
||||
|
||||
static void
|
||||
dnd_surface_commit (MetaWaylandSurface *surface,
|
||||
MetaWaylandPendingState *pending)
|
||||
{
|
||||
meta_wayland_data_device_update_dnd_surface (&surface->compositor->seat->data_device);
|
||||
}
|
||||
|
||||
static void
|
||||
calculate_surface_window_geometry (MetaWaylandSurface *surface,
|
||||
MetaRectangle *total_geometry,
|
||||
@ -418,8 +387,8 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -429,6 +398,9 @@ commit_pending_state (MetaWaylandSurface *surface,
|
||||
if (!cairo_region_is_empty (pending->damage))
|
||||
surface_process_damage (surface, pending->damage);
|
||||
|
||||
surface->offset_x += pending->dx;
|
||||
surface->offset_y += pending->dy;
|
||||
|
||||
if (pending->opaque_region)
|
||||
{
|
||||
pending->opaque_region = scale_region (pending->opaque_region, surface->scale);
|
||||
@ -436,19 +408,11 @@ commit_pending_state (MetaWaylandSurface *surface,
|
||||
}
|
||||
if (pending->input_region)
|
||||
{
|
||||
pending->input_region = scale_region (pending->input_region, surface->scale);
|
||||
pending->input_region = scale_region (pending->input_region,
|
||||
meta_surface_actor_wayland_get_scale (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor)));
|
||||
meta_surface_actor_set_input_region (surface->surface_actor, pending->input_region);
|
||||
}
|
||||
|
||||
if (surface == compositor->seat->pointer.cursor_surface)
|
||||
cursor_surface_commit (surface, pending);
|
||||
else if (surface->window)
|
||||
toplevel_surface_commit (surface, pending);
|
||||
else if (surface->subsurface.resource)
|
||||
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));
|
||||
|
||||
@ -456,6 +420,17 @@ commit_pending_state (MetaWaylandSurface *surface,
|
||||
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->wl_subsurface)
|
||||
subsurface_surface_commit (surface, pending);
|
||||
|
||||
g_list_foreach (surface->subsurfaces, parent_surface_committed, NULL);
|
||||
|
||||
pending_state_reset (pending);
|
||||
}
|
||||
|
||||
@ -566,7 +541,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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -585,7 +561,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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -642,7 +619,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;
|
||||
@ -722,33 +699,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,
|
||||
@ -775,7 +725,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
|
||||
@ -1013,11 +963,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,
|
||||
@ -1025,6 +971,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);
|
||||
@ -1037,7 +986,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
|
||||
@ -1067,15 +1016,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,
|
||||
@ -1083,9 +1029,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);
|
||||
@ -1096,6 +1045,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);
|
||||
}
|
||||
|
||||
@ -1129,7 +1079,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
|
||||
@ -1337,11 +1287,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,
|
||||
@ -1349,6 +1295,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);
|
||||
}
|
||||
@ -1374,7 +1323,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
|
||||
@ -1417,17 +1366,16 @@ get_gtk_surface (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||
|
||||
if (!create_surface_extension (&surface->gtk_surface,
|
||||
>k_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, >k_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 = {
|
||||
@ -1528,7 +1476,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
|
||||
@ -1654,7 +1602,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,
|
||||
@ -1692,11 +1640,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,
|
||||
@ -1704,6 +1648,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;
|
||||
@ -1795,9 +1742,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;
|
||||
@ -1811,7 +1758,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);
|
||||
|
||||
@ -1821,13 +1768,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 ();
|
||||
@ -1839,15 +1786,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
|
||||
@ -1857,8 +1804,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);
|
||||
}
|
||||
|
@ -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,13 +109,6 @@ struct _MetaWaylandSurface
|
||||
gboolean pending_pos;
|
||||
GSList *pending_placement_ops;
|
||||
} sub;
|
||||
|
||||
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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
@ -1683,7 +1684,7 @@ meta_window_x11_update_input_region (MetaWindow *window)
|
||||
/* Translate the set of XShape rectangles that we
|
||||
* get from the X server to a cairo_region. */
|
||||
XRectangle *rects = NULL;
|
||||
int n_rects, ordering;
|
||||
int n_rects = -1, ordering;
|
||||
|
||||
meta_error_trap_push (window->display);
|
||||
rects = XShapeGetRectangles (window->display->xdisplay,
|
||||
@ -1693,21 +1694,46 @@ meta_window_x11_update_input_region (MetaWindow *window)
|
||||
&ordering);
|
||||
meta_error_trap_pop (window->display);
|
||||
|
||||
/* XXX: The x shape extension doesn't provide a way to only test if an
|
||||
* input shape has been specified, so we have to query and throw away the
|
||||
* rectangles. */
|
||||
if (rects)
|
||||
{
|
||||
if (n_rects > 1 ||
|
||||
(n_rects == 1 &&
|
||||
(rects[0].x != 0 ||
|
||||
rects[0].y != 0 ||
|
||||
rects[0].width != priv->client_rect.width ||
|
||||
rects[0].height != priv->client_rect.height)))
|
||||
region = region_create_from_x_rectangles (rects, n_rects);
|
||||
/* XXX: The X Shape specification is quite unfortunately specified.
|
||||
*
|
||||
* By default, the window has a shape the same as its bounding region,
|
||||
* which we consider "NULL".
|
||||
*
|
||||
* If the window sets an empty region, then we'll get n_rects as 0
|
||||
* and rects as NULL, which we need to transform back into an empty
|
||||
* region.
|
||||
*
|
||||
* It would be great to have a less-broken extension for this, but
|
||||
* hey, it's X11!
|
||||
*/
|
||||
|
||||
XFree (rects);
|
||||
if (n_rects == -1)
|
||||
{
|
||||
/* We had an error. */
|
||||
region = NULL;
|
||||
}
|
||||
else if (n_rects == 0)
|
||||
{
|
||||
/* Client set an empty region. */
|
||||
region = cairo_region_create ();
|
||||
}
|
||||
else if (n_rects == 1 &&
|
||||
(rects[0].x == 0 ||
|
||||
rects[0].y == 0 ||
|
||||
rects[0].width == priv->client_rect.width ||
|
||||
rects[0].height == priv->client_rect.height))
|
||||
{
|
||||
/* This is the bounding region case. Keep the
|
||||
* region as NULL. */
|
||||
region = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Window has a custom shape. */
|
||||
region = region_create_from_x_rectangles (rects, n_rects);
|
||||
}
|
||||
|
||||
meta_XFree (rects);
|
||||
}
|
||||
|
||||
if (region != NULL)
|
||||
|
Reference in New Issue
Block a user