Compare commits
93 Commits
Author | SHA1 | Date | |
---|---|---|---|
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 | |||
b735571688 | |||
5e249ad5eb | |||
21bffe4aef | |||
68283df4d9 | |||
4f3de2ce39 | |||
9f8b641472 | |||
a9a21c801c | |||
482a97466d | |||
4e14bb9df3 | |||
df90545258 | |||
c954f9cc24 | |||
d06b39d13c | |||
f3595ebd08 | |||
1e1ca47ec1 | |||
2eec11b445 | |||
8ff4597201 | |||
d5f2468d88 | |||
488dd0b402 | |||
6565bca210 | |||
60c22b6236 | |||
d3111a9f07 | |||
cdfb301200 | |||
371560c2b6 | |||
7616881afa | |||
74c37d49c4 | |||
d3142b92f0 | |||
ae2afa7c5e | |||
4a71621fbc | |||
565b9d73d5 | |||
90bd02ff4d | |||
73ca0efaeb |
26
NEWS
26
NEWS
@ -1,3 +1,29 @@
|
||||
3.14.1
|
||||
======
|
||||
* Fix move-titlebar-onscreen function [Florian; #736915]
|
||||
* Fix stacking of the guard window [Owen; #737233]
|
||||
* Fix keycode lookup for non-default layouts [Rui; #737134]
|
||||
* Fix workspaces-only-on-primary handling [Florian; #737178]
|
||||
* Don't unstick sticky windows on workspace removal [Florian; #737625]
|
||||
* Do not auto-minimize fullscreen windows [Jasper; #705177]
|
||||
* Upload keymap to newly added keyboard devices [Rui; #737673]
|
||||
* Apply keyboard repeat settings [Rui; #728055]
|
||||
* Don't send pressed keys on enter [Rui; #727178]
|
||||
* Fix build without wayland/native [Rico; #738225]
|
||||
* Send modifiers after the key event [Rui; #738238]
|
||||
* Fix unredirect heuristic [Adel; #738271]
|
||||
* Do not show system chrome over fullscreen windows [Florian; #693991]
|
||||
* Misc. bug fixes [Florian, Adel, Tom; #737135, #737581, #738146, #738384]
|
||||
|
||||
Contributors:
|
||||
Tom Beckmann, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner,
|
||||
Jasper St. Pierre, Rico Tzschichholz, Owen W. Taylor
|
||||
|
||||
Translations:
|
||||
Krishnababu Krothapalli [te], Мирослав Николић [sr, sr@latin],
|
||||
Alexander Shopov [bg], Saibal Ray [bn_IN], Milo Casagrande [it],
|
||||
Rūdolfs Mazurs [lv]
|
||||
|
||||
3.14.0
|
||||
======
|
||||
* Fix placement of popup windows on wayland [Jasper; #736812]
|
||||
|
@ -2,7 +2,7 @@ AC_PREREQ(2.62)
|
||||
|
||||
m4_define([mutter_major_version], [3])
|
||||
m4_define([mutter_minor_version], [14])
|
||||
m4_define([mutter_micro_version], [0])
|
||||
m4_define([mutter_micro_version], [1])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
@ -77,9 +77,8 @@ 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
|
||||
gbm >= 10.3
|
||||
upower-glib >= 0.99.0
|
||||
gnome-desktop-3.0
|
||||
xcomposite >= 0.2
|
||||
@ -202,7 +201,7 @@ AC_SUBST(XWAYLAND_PATH)
|
||||
|
||||
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
|
||||
|
||||
PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [libdrm libsystemd libinput], [have_native_backend=yes], [have_native_backend=no])
|
||||
PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [clutter-egl-1.0 libdrm libsystemd libinput], [have_native_backend=yes], [have_native_backend=no])
|
||||
if test $have_native_backend = yes; then
|
||||
AC_DEFINE([HAVE_NATIVE_BACKEND],[1],[Define if you want to enable the native (KMS) backend based on systemd])
|
||||
fi
|
||||
|
2028
po/bn_IN.po
2028
po/bn_IN.po
File diff suppressed because it is too large
Load Diff
1300
po/sr@latin.po
1300
po/sr@latin.po
File diff suppressed because it is too large
Load Diff
@ -7,6 +7,7 @@ stackingdir = $(pkgdatadir)/tests/stacking
|
||||
dist_stacking_DATA = \
|
||||
tests/stacking/basic-x11.metatest \
|
||||
tests/stacking/basic-wayland.metatest \
|
||||
tests/stacking/minimized.metatest \
|
||||
tests/stacking/mixed-windows.metatest \
|
||||
tests/stacking/override-redirect.metatest
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -139,35 +139,56 @@ load_cursor_on_client (MetaCursor cursor)
|
||||
meta_prefs_get_cursor_size ());
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
|
||||
{
|
||||
meta_cursor_renderer_native_get_cursor_size (META_CURSOR_RENDERER_NATIVE (renderer), cursor_width, cursor_height);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
|
||||
MetaCursorImage *image,
|
||||
uint8_t *pixels,
|
||||
int width,
|
||||
int height,
|
||||
uint width,
|
||||
uint height,
|
||||
int rowstride,
|
||||
uint32_t gbm_format)
|
||||
{
|
||||
if (width > 64 || height > 64)
|
||||
uint64_t cursor_width, cursor_height;
|
||||
get_hardware_cursor_size (&cursor_width, &cursor_height);
|
||||
|
||||
if (width > cursor_width || height > cursor_height)
|
||||
{
|
||||
meta_warning ("Invalid theme cursor size (must be at most 64x64)\n");
|
||||
meta_warning ("Invalid theme cursor size (must be at most %ux%u)\n",
|
||||
(unsigned int)cursor_width, (unsigned int)cursor_height);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gbm_device_is_format_supported (gbm, gbm_format,
|
||||
GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE))
|
||||
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE))
|
||||
{
|
||||
uint8_t buf[4 * 64 * 64];
|
||||
int i;
|
||||
uint8_t buf[4 * cursor_width * cursor_height];
|
||||
uint i;
|
||||
|
||||
image->bo = gbm_bo_create (gbm, 64, 64,
|
||||
gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
|
||||
image->bo = gbm_bo_create (gbm, cursor_width, cursor_height,
|
||||
gbm_format, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
|
||||
|
||||
memset (buf, 0, sizeof(buf));
|
||||
for (i = 0; i < height; i++)
|
||||
memcpy (buf + i * 4 * 64, pixels + i * rowstride, width * 4);
|
||||
memcpy (buf + i * 4 * cursor_width, pixels + i * rowstride, width * 4);
|
||||
|
||||
gbm_bo_write (image->bo, buf, 64 * 64 * 4);
|
||||
gbm_bo_write (image->bo, buf, cursor_width * cursor_height * 4);
|
||||
}
|
||||
else
|
||||
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
|
||||
@ -191,7 +212,7 @@ static void
|
||||
meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
|
||||
XcursorImage *xc_image)
|
||||
{
|
||||
int width, height, rowstride;
|
||||
uint width, height, rowstride;
|
||||
CoglPixelFormat cogl_format;
|
||||
uint32_t gbm_format;
|
||||
ClutterBackend *clutter_backend;
|
||||
@ -262,7 +283,8 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
|
||||
CoglContext *cogl_context;
|
||||
struct wl_shm_buffer *shm_buffer;
|
||||
uint32_t gbm_format;
|
||||
int width, height;
|
||||
uint64_t cursor_width, cursor_height;
|
||||
uint width, height;
|
||||
|
||||
image->hot_x = hot_x;
|
||||
image->hot_y = hot_y;
|
||||
@ -313,22 +335,23 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* HW cursors must be 64x64, but 64x64 is huge, and no cursor theme actually uses
|
||||
that, so themed cursors must be padded with transparent pixels to fill the
|
||||
overlay. This is trivial if we have CPU access to the data, but it's not
|
||||
possible if the buffer is in GPU memory (and possibly tiled too), so if we
|
||||
don't get the right size, we fallback to GL.
|
||||
*/
|
||||
if (width != 64 || height != 64)
|
||||
{
|
||||
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (gbm)
|
||||
{
|
||||
image->bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER,
|
||||
buffer, GBM_BO_USE_CURSOR_64X64);
|
||||
/* HW cursors have a predefined size (at least 64x64), which usually is bigger than cursor theme
|
||||
size, so themed cursors must be padded with transparent pixels to fill the
|
||||
overlay. This is trivial if we have CPU access to the data, but it's not
|
||||
possible if the buffer is in GPU memory (and possibly tiled too), so if we
|
||||
don't get the right size, we fallback to GL.
|
||||
*/
|
||||
get_hardware_cursor_size (&cursor_width, &cursor_height);
|
||||
|
||||
if (width != cursor_width || height != cursor_height)
|
||||
{
|
||||
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
|
||||
return;
|
||||
}
|
||||
|
||||
image->bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER, buffer, GBM_BO_USE_CURSOR);
|
||||
if (!image->bo)
|
||||
meta_warning ("Importing HW cursor from wl_buffer failed\n");
|
||||
}
|
||||
|
@ -44,12 +44,6 @@ enum {
|
||||
SIGNALS_LAST
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_POWER_SAVE_MODE,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static int signals[SIGNALS_LAST];
|
||||
|
||||
static void meta_monitor_manager_display_config_init (MetaDBusDisplayConfigIface *iface);
|
||||
@ -167,11 +161,39 @@ make_logical_config (MetaMonitorManager *manager)
|
||||
manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
power_save_mode_changed (MetaMonitorManager *manager,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaMonitorManagerClass *klass;
|
||||
int mode = meta_dbus_display_config_get_power_save_mode (META_DBUS_DISPLAY_CONFIG (manager));
|
||||
|
||||
if (mode == META_POWER_SAVE_UNSUPPORTED)
|
||||
return;
|
||||
|
||||
/* If DPMS is unsupported, force the property back. */
|
||||
if (manager->power_save_mode == META_POWER_SAVE_UNSUPPORTED)
|
||||
{
|
||||
meta_dbus_display_config_set_power_save_mode (META_DBUS_DISPLAY_CONFIG (manager), META_POWER_SAVE_UNSUPPORTED);
|
||||
return;
|
||||
}
|
||||
|
||||
klass = META_MONITOR_MANAGER_GET_CLASS (manager);
|
||||
if (klass->set_power_save_mode)
|
||||
klass->set_power_save_mode (manager, mode);
|
||||
|
||||
manager->power_save_mode = mode;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_constructed (GObject *object)
|
||||
{
|
||||
MetaMonitorManager *manager = META_MONITOR_MANAGER (object);
|
||||
|
||||
g_signal_connect_object (manager, "notify::power-save-mode",
|
||||
G_CALLBACK (power_save_mode_changed), manager, 0);
|
||||
|
||||
manager->in_init = TRUE;
|
||||
|
||||
manager->config = meta_monitor_config_new ();
|
||||
@ -214,23 +236,6 @@ meta_monitor_manager_constructed (GObject *object)
|
||||
manager->in_init = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_set_power_save_mode (MetaMonitorManager *manager,
|
||||
MetaPowerSave mode)
|
||||
{
|
||||
MetaMonitorManagerClass *klass;
|
||||
|
||||
if (manager->power_save_mode == META_POWER_SAVE_UNSUPPORTED ||
|
||||
mode == META_POWER_SAVE_UNSUPPORTED)
|
||||
return;
|
||||
|
||||
klass = META_MONITOR_MANAGER_GET_CLASS (manager);
|
||||
if (klass->set_power_save_mode)
|
||||
klass->set_power_save_mode (manager, mode);
|
||||
|
||||
manager->power_save_mode = mode;
|
||||
}
|
||||
|
||||
void
|
||||
meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
|
||||
int n_old_outputs)
|
||||
@ -298,44 +303,6 @@ meta_monitor_manager_dispose (GObject *object)
|
||||
G_OBJECT_CLASS (meta_monitor_manager_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaMonitorManager *self = META_MONITOR_MANAGER (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_POWER_SAVE_MODE:
|
||||
meta_monitor_manager_set_power_save_mode (self, g_value_get_int (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaMonitorManager *self = META_MONITOR_MANAGER (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_POWER_SAVE_MODE:
|
||||
g_value_set_int (value, self->power_save_mode);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
meta_monitor_manager_real_read_edid (MetaMonitorManager *manager,
|
||||
MetaOutput *output)
|
||||
@ -356,8 +323,6 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->constructed = meta_monitor_manager_constructed;
|
||||
object_class->get_property = meta_monitor_manager_get_property;
|
||||
object_class->set_property = meta_monitor_manager_set_property;
|
||||
object_class->dispose = meta_monitor_manager_dispose;
|
||||
object_class->finalize = meta_monitor_manager_finalize;
|
||||
|
||||
@ -371,8 +336,6 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
g_object_class_override_property (object_class, PROP_POWER_SAVE_MODE, "power-save-mode");
|
||||
}
|
||||
|
||||
static const double known_diagonals[] = {
|
||||
|
@ -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
|
||||
|
@ -27,16 +27,27 @@
|
||||
#include "meta-cursor-renderer-native.h"
|
||||
|
||||
#include <gbm.h>
|
||||
#include <xf86drm.h>
|
||||
|
||||
#include "meta-cursor-private.h"
|
||||
#include "meta-monitor-manager.h"
|
||||
|
||||
#ifndef DRM_CAP_CURSOR_WIDTH
|
||||
#define DRM_CAP_CURSOR_WIDTH 0x8
|
||||
#endif
|
||||
#ifndef DRM_CAP_CURSOR_HEIGHT
|
||||
#define DRM_CAP_CURSOR_HEIGHT 0x9
|
||||
#endif
|
||||
|
||||
struct _MetaCursorRendererNativePrivate
|
||||
{
|
||||
gboolean has_hw_cursor;
|
||||
|
||||
int drm_fd;
|
||||
struct gbm_device *gbm;
|
||||
|
||||
uint64_t cursor_width;
|
||||
uint64_t cursor_height;
|
||||
};
|
||||
typedef struct _MetaCursorRendererNativePrivate MetaCursorRendererNativePrivate;
|
||||
|
||||
@ -71,17 +82,13 @@ set_crtc_cursor (MetaCursorRendererNative *native,
|
||||
{
|
||||
struct gbm_bo *bo;
|
||||
union gbm_bo_handle handle;
|
||||
int width, height;
|
||||
int hot_x, hot_y;
|
||||
|
||||
bo = meta_cursor_reference_get_gbm_bo (cursor, &hot_x, &hot_y);
|
||||
|
||||
handle = gbm_bo_get_handle (bo);
|
||||
width = gbm_bo_get_width (bo);
|
||||
height = gbm_bo_get_height (bo);
|
||||
|
||||
drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, handle.u32,
|
||||
width, height, hot_x, hot_y);
|
||||
priv->cursor_width, priv->cursor_height, hot_x, hot_y);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -186,6 +193,19 @@ meta_cursor_renderer_native_init (MetaCursorRendererNative *native)
|
||||
CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (ctx));
|
||||
priv->drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
|
||||
priv->gbm = gbm_create_device (priv->drm_fd);
|
||||
|
||||
uint64_t width, height;
|
||||
if (drmGetCap (priv->drm_fd, DRM_CAP_CURSOR_WIDTH, &width) == 0 &&
|
||||
drmGetCap (priv->drm_fd, DRM_CAP_CURSOR_HEIGHT, &height) == 0)
|
||||
{
|
||||
priv->cursor_width = width;
|
||||
priv->cursor_height = height;
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->cursor_width = 64;
|
||||
priv->cursor_height = 64;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -198,6 +218,16 @@ meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *native)
|
||||
return priv->gbm;
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_renderer_native_get_cursor_size (MetaCursorRendererNative *native,
|
||||
uint64_t *width, uint64_t *height)
|
||||
{
|
||||
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
|
||||
|
||||
*width = priv->cursor_width;
|
||||
*height = priv->cursor_height;
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_renderer_native_force_update (MetaCursorRendererNative *native)
|
||||
{
|
||||
|
@ -50,6 +50,7 @@ struct _MetaCursorRendererNativeClass
|
||||
GType meta_cursor_renderer_native_get_type (void) G_GNUC_CONST;
|
||||
|
||||
struct gbm_device * meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *renderer);
|
||||
void meta_cursor_renderer_native_get_cursor_size (MetaCursorRendererNative *native, uint64_t *width, uint64_t *height);
|
||||
void meta_cursor_renderer_native_force_update (MetaCursorRendererNative *renderer);
|
||||
|
||||
#endif /* META_CURSOR_RENDERER_NATIVE_H */
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -144,7 +144,7 @@ static gboolean
|
||||
output_get_boolean_property (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output, const char *propname)
|
||||
{
|
||||
gboolean value;
|
||||
gboolean value = FALSE;
|
||||
Atom atom, actual_type;
|
||||
int actual_format;
|
||||
unsigned long nitems, bytes_after;
|
||||
@ -158,12 +158,12 @@ output_get_boolean_property (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
&actual_type, &actual_format,
|
||||
&nitems, &bytes_after, &buffer);
|
||||
|
||||
if (actual_type != XA_CARDINAL || actual_format != 32 ||
|
||||
nitems < 1)
|
||||
return FALSE;
|
||||
if (actual_type != XA_CARDINAL || actual_format != 32 || nitems < 1)
|
||||
goto out;
|
||||
|
||||
value = ((int*)buffer)[0];
|
||||
|
||||
out:
|
||||
XFree (buffer);
|
||||
return value;
|
||||
}
|
||||
@ -187,7 +187,7 @@ static int
|
||||
output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output)
|
||||
{
|
||||
gboolean value;
|
||||
int value = -1;
|
||||
Atom atom, actual_type;
|
||||
int actual_format;
|
||||
unsigned long nitems, bytes_after;
|
||||
@ -201,14 +201,17 @@ output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
&actual_type, &actual_format,
|
||||
&nitems, &bytes_after, &buffer);
|
||||
|
||||
if (actual_type != XA_INTEGER || actual_format != 32 ||
|
||||
nitems < 1)
|
||||
return -1;
|
||||
if (actual_type != XA_INTEGER || actual_format != 32 || nitems < 1)
|
||||
goto out;
|
||||
|
||||
value = ((int*)buffer)[0];
|
||||
|
||||
out:
|
||||
XFree (buffer);
|
||||
return normalize_backlight (output, value);
|
||||
if (value > 0)
|
||||
return normalize_backlight (output, value);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1072,6 +1075,7 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
|
||||
MetaMonitorMode *old_modes;
|
||||
unsigned int n_old_outputs, n_old_modes;
|
||||
gboolean new_config;
|
||||
gboolean applied_config = FALSE;
|
||||
|
||||
if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
|
||||
return FALSE;
|
||||
@ -1088,39 +1092,32 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
|
||||
manager->serial++;
|
||||
meta_monitor_manager_xrandr_read_current (manager);
|
||||
|
||||
new_config = manager_xrandr->resources->timestamp >=
|
||||
manager_xrandr->resources->configTimestamp;
|
||||
if (meta_monitor_manager_has_hotplug_mode_update (manager))
|
||||
new_config = manager_xrandr->resources->timestamp >= manager_xrandr->resources->configTimestamp;
|
||||
|
||||
/* If this is the X server telling us we set a new configuration,
|
||||
* we can simply short-cut to rebuilding our logical configuration.
|
||||
*/
|
||||
if (new_config || meta_monitor_config_match_current (manager->config, manager))
|
||||
{
|
||||
/* Check if the current intended configuration is a result of an
|
||||
XRandR call. Otherwise, hotplug_mode_update tells us to get
|
||||
a new preferred mode on hotplug events to handle dynamic
|
||||
guest resizing. */
|
||||
if (new_config)
|
||||
meta_monitor_manager_xrandr_rebuild_derived (manager);
|
||||
else
|
||||
meta_monitor_config_make_default (manager->config, manager);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check if the current intended configuration has the same outputs
|
||||
as the new real one, or if the event is a result of an XRandR call.
|
||||
If so, we can go straight to rebuild the logical config and tell
|
||||
the outside world.
|
||||
Otherwise, this event was caused by hotplug, so give a chance to
|
||||
MetaMonitorConfig.
|
||||
|
||||
Note that we need to check both the timestamps and the list of
|
||||
outputs, because the X server might emit spurious events with new
|
||||
configTimestamps (bug 702804), and the driver may have changed
|
||||
the EDID for some other reason (old qxl and vbox drivers). */
|
||||
if (new_config || meta_monitor_config_match_current (manager->config, manager))
|
||||
meta_monitor_manager_xrandr_rebuild_derived (manager);
|
||||
else if (!meta_monitor_config_apply_stored (manager->config, manager))
|
||||
meta_monitor_config_make_default (manager->config, manager);
|
||||
meta_monitor_manager_xrandr_rebuild_derived (manager);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* If the monitor has hotplug_mode_update (which is used by VMs), don't bother
|
||||
* applying our stored configuration, because it's likely the user just resizing
|
||||
* the window.
|
||||
*/
|
||||
if (!meta_monitor_manager_has_hotplug_mode_update (manager))
|
||||
{
|
||||
if (meta_monitor_config_apply_stored (manager->config, manager))
|
||||
applied_config = TRUE;
|
||||
}
|
||||
|
||||
/* If we haven't applied any configuration, apply the default configuration. */
|
||||
if (!applied_config)
|
||||
meta_monitor_config_make_default (manager->config, manager);
|
||||
|
||||
out:
|
||||
meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
|
||||
meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
|
||||
g_free (old_crtcs);
|
||||
|
@ -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
|
||||
|
@ -185,6 +185,9 @@ file_loaded (GObject *source_object,
|
||||
image->texture = texture;
|
||||
|
||||
out:
|
||||
if (pixbuf != NULL)
|
||||
g_object_unref (pixbuf);
|
||||
|
||||
image->loaded = TRUE;
|
||||
g_signal_emit (image, signals[LOADED], 0);
|
||||
}
|
||||
|
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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -612,9 +612,14 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
*/
|
||||
if (window->frame && window->decorated)
|
||||
{
|
||||
MetaRectangle titlebar_rect;
|
||||
MetaRectangle titlebar_rect, frame_rect;
|
||||
|
||||
meta_window_get_titlebar_rect (window, &titlebar_rect);
|
||||
meta_window_get_frame_rect (window, &frame_rect);
|
||||
|
||||
/* translate into screen coordinates */
|
||||
titlebar_rect.x = frame_rect.x;
|
||||
titlebar_rect.y = frame_rect.y;
|
||||
|
||||
old = window->require_titlebar_visible;
|
||||
window->require_titlebar_visible =
|
||||
|
@ -57,6 +57,7 @@ typedef struct MetaEdgeResistanceData MetaEdgeResistanceData;
|
||||
typedef enum {
|
||||
META_LIST_DEFAULT = 0, /* normal windows */
|
||||
META_LIST_INCLUDE_OVERRIDE_REDIRECT = 1 << 0, /* normal and O-R */
|
||||
META_LIST_SORTED = 1 << 1, /* sort list by mru */
|
||||
} MetaListWindowsFlags;
|
||||
|
||||
#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
|
||||
|
@ -150,6 +150,9 @@ static void update_cursor_theme (void);
|
||||
static void prefs_changed_callback (MetaPreference pref,
|
||||
void *data);
|
||||
|
||||
static int mru_cmp (gconstpointer a,
|
||||
gconstpointer b);
|
||||
|
||||
static void
|
||||
meta_display_get_property(GObject *object,
|
||||
guint prop_id,
|
||||
@ -1004,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 ||
|
||||
@ -1017,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 ||
|
||||
@ -1061,6 +1064,9 @@ meta_display_list_windows (MetaDisplay *display,
|
||||
tmp = next;
|
||||
}
|
||||
|
||||
if (flags & META_LIST_SORTED)
|
||||
winlist = g_slist_sort (winlist, mru_cmp);
|
||||
|
||||
return winlist;
|
||||
}
|
||||
|
||||
@ -2434,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"
|
||||
|
@ -101,6 +101,8 @@ typedef struct
|
||||
MetaKeyCombo *iso_next_group_combos;
|
||||
int n_iso_next_group_combos;
|
||||
|
||||
xkb_level_index_t keymap_num_levels;
|
||||
|
||||
/* Alt+click button grabs */
|
||||
ClutterModifierType window_grab_modifiers;
|
||||
} MetaKeyBindingManager;
|
||||
|
@ -40,7 +40,11 @@
|
||||
#include <meta/prefs.h>
|
||||
#include "meta-accel-parse.h"
|
||||
|
||||
#ifdef __linux__
|
||||
#include <linux/input.h>
|
||||
#elif !defined KEY_GRAVE
|
||||
#define KEY_GRAVE 0x29 /* assume the use of xf86-input-keyboard */
|
||||
#endif
|
||||
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
#include "x11/window-x11.h"
|
||||
@ -236,29 +240,19 @@ reload_modmap (MetaKeyBindingManager *keys)
|
||||
|
||||
static gboolean
|
||||
is_keycode_for_keysym (struct xkb_keymap *keymap,
|
||||
xkb_layout_index_t layout,
|
||||
xkb_level_index_t level,
|
||||
xkb_keycode_t keycode,
|
||||
xkb_keysym_t keysym)
|
||||
{
|
||||
xkb_layout_index_t num_layouts, i;
|
||||
const xkb_keysym_t *syms;
|
||||
int num_syms, k;
|
||||
|
||||
num_layouts = xkb_keymap_num_layouts_for_key (keymap, keycode);
|
||||
for (i = 0; i < num_layouts; i++)
|
||||
num_syms = xkb_keymap_key_get_syms_by_level (keymap, keycode, layout, level, &syms);
|
||||
for (k = 0; k < num_syms; k++)
|
||||
{
|
||||
xkb_level_index_t num_levels, j;
|
||||
|
||||
num_levels = xkb_keymap_num_levels_for_key (keymap, keycode, i);
|
||||
for (j = 0; j < num_levels; j++)
|
||||
{
|
||||
const xkb_keysym_t *syms;
|
||||
int num_syms, k;
|
||||
|
||||
num_syms = xkb_keymap_key_get_syms_by_level (keymap, keycode, i, j, &syms);
|
||||
for (k = 0; k < num_syms; k++)
|
||||
{
|
||||
if (syms[k] == keysym)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if (syms[k] == keysym)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
@ -268,6 +262,8 @@ typedef struct
|
||||
{
|
||||
GArray *keycodes;
|
||||
xkb_keysym_t keysym;
|
||||
xkb_layout_index_t layout;
|
||||
xkb_level_index_t level;
|
||||
} FindKeysymData;
|
||||
|
||||
static void
|
||||
@ -278,8 +274,10 @@ get_keycodes_for_keysym_iter (struct xkb_keymap *keymap,
|
||||
FindKeysymData *search_data = data;
|
||||
GArray *keycodes = search_data->keycodes;
|
||||
xkb_keysym_t keysym = search_data->keysym;
|
||||
xkb_layout_index_t layout = search_data->layout;
|
||||
xkb_level_index_t level = search_data->level;
|
||||
|
||||
if (is_keycode_for_keysym (keymap, keycode, keysym))
|
||||
if (is_keycode_for_keysym (keymap, layout, level, keycode, keysym))
|
||||
g_array_append_val (keycodes, keycode);
|
||||
}
|
||||
|
||||
@ -307,8 +305,15 @@ get_keycodes_for_keysym (MetaKeyBindingManager *keys,
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
struct xkb_keymap *keymap = meta_backend_get_keymap (backend);
|
||||
FindKeysymData search_data = { retval, keysym };
|
||||
xkb_keymap_key_for_each (keymap, get_keycodes_for_keysym_iter, &search_data);
|
||||
xkb_layout_index_t i;
|
||||
xkb_level_index_t j;
|
||||
|
||||
for (i = 0; i < xkb_keymap_num_layouts (keymap); i++)
|
||||
for (j = 0; j < keys->keymap_num_levels; j++)
|
||||
{
|
||||
FindKeysymData search_data = { retval, keysym, i, j };
|
||||
xkb_keymap_key_for_each (keymap, get_keycodes_for_keysym_iter, &search_data);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
@ -319,7 +324,7 @@ get_keycodes_for_keysym (MetaKeyBindingManager *keys,
|
||||
|
||||
static guint
|
||||
get_first_keycode_for_keysym (MetaKeyBindingManager *keys,
|
||||
guint keysym)
|
||||
guint keysym)
|
||||
{
|
||||
int *keycodes;
|
||||
int n_keycodes;
|
||||
@ -336,6 +341,32 @@ get_first_keycode_for_keysym (MetaKeyBindingManager *keys,
|
||||
return keycode;
|
||||
}
|
||||
|
||||
static void
|
||||
determine_keymap_num_levels_iter (struct xkb_keymap *keymap,
|
||||
xkb_keycode_t keycode,
|
||||
void *data)
|
||||
{
|
||||
xkb_level_index_t *num_levels = data;
|
||||
xkb_layout_index_t i;
|
||||
|
||||
for (i = 0; i < xkb_keymap_num_layouts_for_key (keymap, keycode); i++)
|
||||
{
|
||||
xkb_level_index_t level = xkb_keymap_num_levels_for_key (keymap, keycode, i);
|
||||
if (level > *num_levels)
|
||||
*num_levels = level;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
determine_keymap_num_levels (MetaKeyBindingManager *keys)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
struct xkb_keymap *keymap = meta_backend_get_keymap (backend);
|
||||
|
||||
keys->keymap_num_levels = 0;
|
||||
xkb_keymap_key_for_each (keymap, determine_keymap_num_levels_iter, &keys->keymap_num_levels);
|
||||
}
|
||||
|
||||
static void
|
||||
reload_iso_next_group_combos (MetaKeyBindingManager *keys)
|
||||
{
|
||||
@ -484,6 +515,8 @@ reload_keycodes (MetaKeyBindingManager *keys)
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Reloading keycodes for binding tables\n");
|
||||
|
||||
determine_keymap_num_levels (keys);
|
||||
|
||||
if (keys->overlay_key_combo.keysym != 0)
|
||||
{
|
||||
keys->overlay_key_combo.keycode =
|
||||
@ -2922,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,
|
||||
|
@ -1187,7 +1187,6 @@ settings_changed (GSettings *settings,
|
||||
{
|
||||
/* Unknown preference type. This quite likely simply isn't
|
||||
* a preference we track changes to. */
|
||||
return;
|
||||
}
|
||||
|
||||
g_variant_unref (value);
|
||||
|
@ -3021,38 +3021,33 @@ static gboolean
|
||||
check_fullscreen_func (gpointer data)
|
||||
{
|
||||
MetaScreen *screen = data;
|
||||
GSList *windows;
|
||||
MetaWindow *window;
|
||||
GSList *tmp;
|
||||
GSList *fullscreen_monitors = NULL;
|
||||
GSList *obscured_monitors = NULL;
|
||||
gboolean in_fullscreen_changed = FALSE;
|
||||
int i;
|
||||
|
||||
screen->check_fullscreen_later = 0;
|
||||
|
||||
windows = meta_display_list_windows (screen->display,
|
||||
META_LIST_INCLUDE_OVERRIDE_REDIRECT);
|
||||
|
||||
for (tmp = windows; tmp != NULL; tmp = tmp->next)
|
||||
/* We consider a monitor in fullscreen if it contains a fullscreen window;
|
||||
* however we make an exception for maximized windows above the fullscreen
|
||||
* one, as in that case window+chrome fully obscure the fullscreen window.
|
||||
*/
|
||||
for (window = meta_stack_get_top (screen->stack);
|
||||
window;
|
||||
window = meta_stack_get_below (screen->stack, window, FALSE))
|
||||
{
|
||||
MetaWindow *window = tmp->data;
|
||||
gboolean covers_monitors = FALSE;
|
||||
|
||||
if (window->screen != screen || window->hidden)
|
||||
continue;
|
||||
|
||||
if (window->fullscreen)
|
||||
/* The checks for determining a fullscreen window's layer are quite
|
||||
* elaborate, and we do a poor job at keeping it dynamically up-to-date.
|
||||
* (It depends, for example, on whether the focus window is on the
|
||||
* same monitor as the fullscreen window.) But because we minimize
|
||||
* fullscreen windows not in LAYER_FULLSCREEN (see below), if the
|
||||
* layer is stale here, it's really bad, so just force recomputation for
|
||||
* here. This is expensive, but hopefully this function won't be
|
||||
* called too often.
|
||||
*/
|
||||
meta_window_update_layer (window);
|
||||
|
||||
if (window->override_redirect)
|
||||
{
|
||||
covers_monitors = TRUE;
|
||||
}
|
||||
else if (window->override_redirect)
|
||||
{
|
||||
/* We want to handle the case where an application is creating an
|
||||
* override-redirect window the size of the screen (monitor) and treat
|
||||
@ -3062,10 +3057,14 @@ check_fullscreen_func (gpointer data)
|
||||
if (meta_window_is_monitor_sized (window))
|
||||
covers_monitors = TRUE;
|
||||
}
|
||||
else
|
||||
else if (window->maximized_horizontally &&
|
||||
window->maximized_vertically)
|
||||
{
|
||||
if (window->layer == META_LAYER_FULLSCREEN)
|
||||
covers_monitors = TRUE;
|
||||
int monitor_index = meta_window_get_monitor (window);
|
||||
/* + 1 to avoid NULL */
|
||||
gpointer monitor_p = GINT_TO_POINTER(monitor_index + 1);
|
||||
if (!g_slist_find (obscured_monitors, monitor_p))
|
||||
obscured_monitors = g_slist_prepend (obscured_monitors, monitor_p);
|
||||
}
|
||||
|
||||
if (covers_monitors)
|
||||
@ -3079,30 +3078,16 @@ check_fullscreen_func (gpointer data)
|
||||
{
|
||||
/* + 1 to avoid NULL */
|
||||
gpointer monitor_p = GINT_TO_POINTER(monitors[j] + 1);
|
||||
if (!g_slist_find (fullscreen_monitors, monitor_p))
|
||||
if (!g_slist_find (fullscreen_monitors, monitor_p) &&
|
||||
!g_slist_find (obscured_monitors, monitor_p))
|
||||
fullscreen_monitors = g_slist_prepend (fullscreen_monitors, monitor_p);
|
||||
}
|
||||
|
||||
g_free (monitors);
|
||||
}
|
||||
|
||||
/* If we find a window that is fullscreen but not in the FULLSCREEN
|
||||
* layer, it means that we've kicked it out of the layer because
|
||||
* we've focused another window on the same monitor. In this case
|
||||
* it would be confusing to keep the window fullscreen and visible,
|
||||
* so minimize it. We can't do the same thing for override-redirect
|
||||
* windows, so we just hope the application does the right thing.
|
||||
*/
|
||||
if (!covers_monitors && window->fullscreen)
|
||||
{
|
||||
meta_window_minimize (window);
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Minimizing %s: was fullscreen but in a lower layer\n",
|
||||
window->desc);
|
||||
}
|
||||
}
|
||||
|
||||
g_slist_free (windows);
|
||||
g_slist_free (obscured_monitors);
|
||||
|
||||
for (i = 0; i < screen->n_monitor_infos; i++)
|
||||
{
|
||||
|
@ -1056,10 +1056,6 @@ stack_sync_to_xserver (MetaStack *stack)
|
||||
all_root_children_stacked = g_array_new (FALSE, FALSE, sizeof (guint64));
|
||||
x11_hidden_stack_ids = g_array_new (FALSE, FALSE, sizeof (guint64));
|
||||
|
||||
/* The screen guard window sits above all hidden windows and acts as
|
||||
* a barrier to input reaching these windows. */
|
||||
g_array_append_val (x11_hidden_stack_ids, stack->screen->guard_window);
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "Top to bottom: ");
|
||||
meta_push_no_msg_prefix ();
|
||||
|
||||
@ -1107,6 +1103,10 @@ stack_sync_to_xserver (MetaStack *stack)
|
||||
meta_topic (META_DEBUG_STACK, "\n");
|
||||
meta_pop_no_msg_prefix ();
|
||||
|
||||
/* The screen guard window sits above all hidden windows and acts as
|
||||
* a barrier to input reaching these windows. */
|
||||
g_array_append_val (x11_hidden_stack_ids, stack->screen->guard_window);
|
||||
|
||||
/* Sync to server */
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "Restacking %u windows\n",
|
||||
|
@ -1062,8 +1062,8 @@ _meta_window_shared_new (MetaDisplay *display,
|
||||
|
||||
if (window->initial_workspace_set)
|
||||
{
|
||||
gboolean on_all_workspaces;
|
||||
MetaWorkspace *workspace;
|
||||
gboolean on_all_workspaces = window->on_all_workspaces;
|
||||
MetaWorkspace *workspace = NULL;
|
||||
|
||||
if (window->initial_workspace == (int) 0xFFFFFFFF)
|
||||
{
|
||||
@ -1077,15 +1077,13 @@ _meta_window_shared_new (MetaDisplay *display,
|
||||
window->on_all_workspaces_requested = TRUE;
|
||||
|
||||
on_all_workspaces = TRUE;
|
||||
workspace = NULL;
|
||||
}
|
||||
else
|
||||
else if (!on_all_workspaces)
|
||||
{
|
||||
meta_topic (META_DEBUG_PLACEMENT,
|
||||
"Window %s is initially on space %d\n",
|
||||
window->desc, window->initial_workspace);
|
||||
|
||||
on_all_workspaces = FALSE;
|
||||
workspace = meta_screen_get_workspace_by_index (window->screen,
|
||||
window->initial_workspace);
|
||||
}
|
||||
@ -1099,9 +1097,9 @@ _meta_window_shared_new (MetaDisplay *display,
|
||||
* but appear on other workspaces. override-redirect windows are part
|
||||
* of no workspace.
|
||||
*/
|
||||
if (!window->override_redirect)
|
||||
if (!window->override_redirect && window->workspace == NULL)
|
||||
{
|
||||
if (window->workspace == NULL && window->transient_for != NULL)
|
||||
if (window->transient_for != NULL)
|
||||
{
|
||||
meta_topic (META_DEBUG_PLACEMENT,
|
||||
"Putting window %s on same workspace as parent %s\n",
|
||||
@ -1112,7 +1110,15 @@ _meta_window_shared_new (MetaDisplay *display,
|
||||
window->transient_for->workspace);
|
||||
}
|
||||
|
||||
if (window->workspace == NULL)
|
||||
if (window->on_all_workspaces)
|
||||
{
|
||||
meta_topic (META_DEBUG_PLACEMENT,
|
||||
"Putting window %s on all workspaces\n",
|
||||
window->desc);
|
||||
|
||||
set_workspace_state (window, TRUE, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_topic (META_DEBUG_PLACEMENT,
|
||||
"Putting window %s on active workspace\n",
|
||||
@ -2089,7 +2095,7 @@ windows_overlap (const MetaWindow *w1, const MetaWindow *w2)
|
||||
static gboolean
|
||||
window_would_be_covered (const MetaWindow *newbie)
|
||||
{
|
||||
MetaWorkspace *workspace = newbie->workspace;
|
||||
MetaWorkspace *workspace = meta_window_get_workspace ((MetaWindow *)newbie);
|
||||
GList *tmp, *windows;
|
||||
|
||||
windows = meta_workspace_list_windows (workspace);
|
||||
@ -2616,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]);
|
||||
@ -3060,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));
|
||||
@ -4291,7 +4302,7 @@ meta_window_focus (MetaWindow *window,
|
||||
* - workspace->windows is a list of windows that is located on
|
||||
* that workspace.
|
||||
*
|
||||
* - If the window is on_all_workspaces, then then
|
||||
* - If the window is on_all_workspaces, then
|
||||
* window->workspace == NULL, but workspace->windows contains
|
||||
* the window.
|
||||
*/
|
||||
@ -4313,7 +4324,8 @@ set_workspace_state (MetaWindow *window,
|
||||
g_return_if_fail ((window->constructing && on_all_workspaces) || window->unmanaging);
|
||||
|
||||
if (on_all_workspaces == window->on_all_workspaces &&
|
||||
workspace == window->workspace)
|
||||
workspace == window->workspace &&
|
||||
!window->constructing)
|
||||
return;
|
||||
|
||||
if (window->workspace)
|
||||
@ -4645,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
|
||||
@ -4668,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;
|
||||
|
||||
@ -5385,7 +5423,7 @@ meta_window_shove_titlebar_onscreen (MetaWindow *window)
|
||||
gboolean
|
||||
meta_window_titlebar_is_onscreen (MetaWindow *window)
|
||||
{
|
||||
MetaRectangle titlebar_rect;
|
||||
MetaRectangle titlebar_rect, frame_rect;
|
||||
GList *onscreen_region;
|
||||
gboolean is_onscreen;
|
||||
|
||||
@ -5400,6 +5438,11 @@ meta_window_titlebar_is_onscreen (MetaWindow *window)
|
||||
/* Get the rectangle corresponding to the titlebar */
|
||||
meta_window_get_titlebar_rect (window, &titlebar_rect);
|
||||
|
||||
/* Translate into screen coordinates */
|
||||
meta_window_get_frame_rect (window, &frame_rect);
|
||||
titlebar_rect.x = frame_rect.x;
|
||||
titlebar_rect.y = frame_rect.y;
|
||||
|
||||
/* Run through the spanning rectangles for the screen and see if one of
|
||||
* them overlaps with the titlebar sufficiently to consider it onscreen.
|
||||
*/
|
||||
@ -6719,7 +6762,7 @@ meta_window_set_demands_attention (MetaWindow *window)
|
||||
other_window = stack->data;
|
||||
stack = stack->next;
|
||||
|
||||
if (meta_window_located_on_workspace (other_window, window->workspace))
|
||||
if (meta_window_located_on_workspace (other_window, workspace))
|
||||
{
|
||||
meta_window_get_frame_rect (other_window, &other_rect);
|
||||
|
||||
|
@ -170,6 +170,7 @@ MetaWorkspace*
|
||||
meta_workspace_new (MetaScreen *screen)
|
||||
{
|
||||
MetaWorkspace *workspace;
|
||||
GSList *windows, *l;
|
||||
|
||||
workspace = g_object_new (META_TYPE_WORKSPACE, NULL);
|
||||
|
||||
@ -197,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;
|
||||
}
|
||||
|
||||
@ -358,7 +366,7 @@ meta_workspace_relocate_windows (MetaWorkspace *workspace,
|
||||
{
|
||||
MetaWindow *window = l->data;
|
||||
|
||||
if (!window->override_redirect)
|
||||
if (!window->on_all_workspaces)
|
||||
meta_window_change_workspace (window, new_home);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -28,7 +28,7 @@
|
||||
#define META_TYPE_WORKSPACE (meta_workspace_get_type ())
|
||||
#define META_WORKSPACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_WORKSPACE, MetaWorkspace))
|
||||
#define META_WORKSPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_WORKSPACE, MetaWorkspaceClass))
|
||||
#define META_IS_WORKSPACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_WORKSPACE_TYPE))
|
||||
#define META_IS_WORKSPACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_WORKSPACE))
|
||||
#define META_IS_WORKSPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_WORKSPACE))
|
||||
#define META_WORKSPACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_WORKSPACE, MetaWorkspaceClass))
|
||||
|
||||
|
@ -71,6 +71,11 @@ lower <client-id>/<window-id>
|
||||
for Wayland clients. (It's also considered discouraged, but supported, for
|
||||
non-override-redirect X11 clients.)
|
||||
|
||||
minimize <client-id>/<window-id>
|
||||
unminimize <client-id>/<window-id>
|
||||
Ask the client to minimize or unminimize the given window ID. This older
|
||||
term for this operation is "iconify".
|
||||
|
||||
destroy <client-id>/<window-id>
|
||||
Destroy the given window
|
||||
|
||||
@ -80,7 +85,10 @@ wait
|
||||
|
||||
assert_stacking <client-id>/<window-id> <client-id>/<window-id> ...
|
||||
Assert that the list of client windows known to Mutter is as given and in
|
||||
the given order, bottom to top.
|
||||
the given order, bottom to top. The character '|' can be present in the
|
||||
list of windows to indicate the guard window that separates hidden and
|
||||
visible windows. If '|' isn't present, the guard window is asserted to
|
||||
be below all client windows.
|
||||
|
||||
This function also queries the X server stack and verifies that Mutter's
|
||||
expectation of the X server stack matches reality.
|
||||
|
18
src/tests/stacking/minimized.metatest
Normal file
18
src/tests/stacking/minimized.metatest
Normal file
@ -0,0 +1,18 @@
|
||||
new_client 1 x11
|
||||
create 1/1
|
||||
show 1/1
|
||||
create 1/2
|
||||
show 1/2
|
||||
wait
|
||||
assert_stacking 1/1 1/2
|
||||
|
||||
minimize 1/2
|
||||
wait
|
||||
assert_stacking 1/2 | 1/1
|
||||
|
||||
# unminimize doesn't work for GTK+ currently, because GTK+ expects
|
||||
# to be able to de-iconify with MapWindow, but the window is already
|
||||
# mapped.
|
||||
activate 1/2
|
||||
wait
|
||||
assert_stacking 1/1 1/2
|
@ -12,7 +12,7 @@ assert_stacking 1/1 1/2
|
||||
|
||||
lower 1/2
|
||||
wait
|
||||
assert_stacking 1/2 1/1
|
||||
assert_stacking 1/2 | 1/1
|
||||
|
||||
raise 1/2
|
||||
wait
|
||||
|
@ -263,6 +263,34 @@ process_line (const char *line)
|
||||
XSyncSetCounter (gdk_x11_display_get_xdisplay (gdk_display_get_default ()),
|
||||
counter, sync_value);
|
||||
}
|
||||
else if (strcmp (argv[0], "minimize") == 0)
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
g_print ("usage: minimize <id>");
|
||||
goto out;
|
||||
}
|
||||
|
||||
GtkWidget *window = lookup_window (argv[1]);
|
||||
if (!window)
|
||||
goto out;
|
||||
|
||||
gtk_window_iconify (GTK_WINDOW (window));
|
||||
}
|
||||
else if (strcmp (argv[0], "unminimize") == 0)
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
g_print ("usage: unminimize <id>");
|
||||
goto out;
|
||||
}
|
||||
|
||||
GtkWidget *window = lookup_window (argv[1]);
|
||||
if (!window)
|
||||
goto out;
|
||||
|
||||
gtk_window_deiconify (GTK_WINDOW (window));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_print ("Unknown command %s", argv[0]);
|
||||
|
@ -413,6 +413,7 @@ typedef struct {
|
||||
AsyncWaiter *waiter;
|
||||
guint log_handler_id;
|
||||
GString *warning_messages;
|
||||
GMainLoop *loop;
|
||||
} TestCase;
|
||||
|
||||
static gboolean
|
||||
@ -483,10 +484,21 @@ test_case_new (void)
|
||||
|
||||
test->clients = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
test->waiter = async_waiter_new ();
|
||||
test->loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
test_case_before_redraw (gpointer data)
|
||||
{
|
||||
TestCase *test = data;
|
||||
|
||||
g_main_loop_quit (test->loop);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
test_case_wait (TestCase *test,
|
||||
GError **error)
|
||||
@ -494,11 +506,30 @@ test_case_wait (TestCase *test,
|
||||
GHashTableIter iter;
|
||||
gpointer key, value;
|
||||
|
||||
/* First have each client set a XSync counter, and wait until
|
||||
* we receive the resulting event - so we know we've received
|
||||
* everything that the client have sent us.
|
||||
*/
|
||||
g_hash_table_iter_init (&iter, test->clients);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
if (!test_client_wait (value, error))
|
||||
return FALSE;
|
||||
|
||||
/* Then wait until we've done any outstanding queued up work.
|
||||
* Though we add this as BEFORE_REDRAW, the iteration that runs the
|
||||
* BEFORE_REDRAW idles will proceed on and do the redraw, so we're
|
||||
* waiting until after *all* frame processing.
|
||||
*/
|
||||
meta_later_add (META_LATER_BEFORE_REDRAW,
|
||||
test_case_before_redraw,
|
||||
test,
|
||||
NULL);
|
||||
g_main_loop_run (test->loop);
|
||||
|
||||
/* Then set an XSync counter ourselves and and wait until
|
||||
* we receive the resulting event - this makes sure that we've
|
||||
* received back any X events we generated.
|
||||
*/
|
||||
async_waiter_set_and_wait (test->waiter);
|
||||
return TRUE;
|
||||
}
|
||||
@ -579,6 +610,13 @@ test_case_assert_stacking (TestCase *test,
|
||||
else
|
||||
g_string_append_printf (stack_string, "(%s)", window->title);
|
||||
}
|
||||
else if (windows[i] == display->screen->guard_window)
|
||||
{
|
||||
if (stack_string->len > 0)
|
||||
g_string_append_c (stack_string, ' ');
|
||||
|
||||
g_string_append_c (stack_string, '|');
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < n_expected_windows; i++)
|
||||
@ -589,6 +627,16 @@ test_case_assert_stacking (TestCase *test,
|
||||
g_string_append (expected_string, expected_windows[i]);
|
||||
}
|
||||
|
||||
/* Don't require '| ' as a prefix if there are no hidden windows - we
|
||||
* remove the prefix from the actual string instead of adding it to the
|
||||
* expected string for clarity of the error message
|
||||
*/
|
||||
if (index (expected_string->str, '|') == NULL && stack_string->str[0] == '|')
|
||||
{
|
||||
g_string_erase (stack_string,
|
||||
0, stack_string->str[1] == ' ' ? 2 : 1);
|
||||
}
|
||||
|
||||
if (strcmp (expected_string->str, stack_string->str) != 0)
|
||||
{
|
||||
g_set_error (error, TEST_RUNNER_ERROR, TEST_RUNNER_ERROR_ASSERTION_FAILED,
|
||||
@ -725,6 +773,8 @@ test_case_do (TestCase *test,
|
||||
strcmp (argv[0], "activate") == 0 ||
|
||||
strcmp (argv[0], "raise") == 0 ||
|
||||
strcmp (argv[0], "lower") == 0 ||
|
||||
strcmp (argv[0], "minimize") == 0 ||
|
||||
strcmp (argv[0], "unminimize") == 0 ||
|
||||
strcmp (argv[0], "destroy") == 0)
|
||||
{
|
||||
if (argc != 2)
|
||||
@ -766,6 +816,7 @@ test_case_do (TestCase *test,
|
||||
{
|
||||
if (!test_case_assert_stacking (test, argv + 1, argc - 1, error))
|
||||
return FALSE;
|
||||
|
||||
if (!test_case_check_xserver_stacking (test, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -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,17 +387,23 @@ commit_pending_state (MetaWaylandSurface *surface,
|
||||
|
||||
if (pending->buffer)
|
||||
{
|
||||
ensure_buffer_texture (pending->buffer);
|
||||
meta_surface_actor_wayland_set_texture (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor), pending->buffer->texture);
|
||||
CoglTexture *texture = meta_wayland_buffer_ensure_texture (pending->buffer);
|
||||
meta_surface_actor_wayland_set_texture (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor), texture);
|
||||
}
|
||||
}
|
||||
|
||||
if (pending->scale > 0)
|
||||
surface->scale = pending->scale;
|
||||
{
|
||||
surface->scale = pending->scale;
|
||||
meta_surface_actor_wayland_scale_texture (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor));
|
||||
}
|
||||
|
||||
if (!cairo_region_is_empty (pending->damage))
|
||||
surface_process_damage (surface, pending->damage);
|
||||
|
||||
surface->offset_x += pending->dx;
|
||||
surface->offset_y += pending->dy;
|
||||
|
||||
if (pending->opaque_region)
|
||||
{
|
||||
pending->opaque_region = scale_region (pending->opaque_region, surface->scale);
|
||||
@ -440,22 +415,21 @@ commit_pending_state (MetaWaylandSurface *surface,
|
||||
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));
|
||||
|
||||
/* wl_surface.frame */
|
||||
wl_list_insert_list (&compositor->frame_callbacks, &pending->frame_callback_list);
|
||||
wl_list_init (&pending->frame_callback_list);
|
||||
|
||||
if (surface == compositor->seat->pointer.cursor_surface)
|
||||
cursor_surface_commit (surface, pending);
|
||||
else if (meta_wayland_data_device_is_dnd_surface (&compositor->seat->data_device, surface))
|
||||
dnd_surface_commit (surface, pending);
|
||||
else if (surface->window)
|
||||
toplevel_surface_commit (surface, pending);
|
||||
else if (surface->wl_subsurface)
|
||||
subsurface_surface_commit (surface, pending);
|
||||
|
||||
g_list_foreach (surface->subsurfaces, parent_surface_committed, NULL);
|
||||
|
||||
pending_state_reset (pending);
|
||||
}
|
||||
|
||||
@ -566,7 +540,8 @@ wl_surface_set_opaque_region (struct wl_client *client,
|
||||
if (region_resource)
|
||||
{
|
||||
MetaWaylandRegion *region = wl_resource_get_user_data (region_resource);
|
||||
surface->pending.opaque_region = cairo_region_copy (region->region);
|
||||
cairo_region_t *cr_region = meta_wayland_region_peek_cairo_region (region);
|
||||
surface->pending.opaque_region = cairo_region_copy (cr_region);
|
||||
}
|
||||
}
|
||||
|
||||
@ -585,7 +560,8 @@ wl_surface_set_input_region (struct wl_client *client,
|
||||
if (region_resource)
|
||||
{
|
||||
MetaWaylandRegion *region = wl_resource_get_user_data (region_resource);
|
||||
surface->pending.input_region = cairo_region_copy (region->region);
|
||||
cairo_region_t *cr_region = meta_wayland_region_peek_cairo_region (region);
|
||||
surface->pending.input_region = cairo_region_copy (cr_region);
|
||||
}
|
||||
}
|
||||
|
||||
@ -642,7 +618,7 @@ surface_should_be_reactive (MetaWaylandSurface *surface)
|
||||
return TRUE;
|
||||
|
||||
/* If we're a subsurface, we should be reactive */
|
||||
if (surface->subsurface.resource)
|
||||
if (surface->wl_subsurface)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
@ -722,33 +698,6 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
|
||||
return surface;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_surface_extension (MetaWaylandSurfaceExtension *extension)
|
||||
{
|
||||
extension->resource = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
create_surface_extension (MetaWaylandSurfaceExtension *extension,
|
||||
const struct wl_interface *interface,
|
||||
const void *implementation,
|
||||
wl_resource_destroy_func_t destructor,
|
||||
MetaWaylandSurface *surface,
|
||||
struct wl_resource *master_resource,
|
||||
guint32 id)
|
||||
{
|
||||
struct wl_client *client;
|
||||
|
||||
if (extension->resource != NULL)
|
||||
return FALSE;
|
||||
|
||||
client = wl_resource_get_client (surface->resource);
|
||||
extension->resource = wl_resource_create (client, interface, wl_resource_get_version (master_resource), id);
|
||||
wl_resource_set_implementation (extension->resource, implementation, surface, destructor);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_shell_use_unstable_version (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
@ -775,7 +724,7 @@ xdg_surface_destructor (struct wl_resource *resource)
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
destroy_window (surface);
|
||||
destroy_surface_extension (&surface->xdg_surface);
|
||||
surface->xdg_surface = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1013,11 +962,7 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||
MetaWindow *window;
|
||||
|
||||
if (!create_surface_extension (&surface->xdg_surface,
|
||||
&xdg_surface_interface,
|
||||
&meta_wayland_xdg_surface_interface,
|
||||
xdg_surface_destructor,
|
||||
surface, resource, id))
|
||||
if (surface->xdg_surface != NULL)
|
||||
{
|
||||
wl_resource_post_error (surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
@ -1025,6 +970,9 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
|
||||
return;
|
||||
}
|
||||
|
||||
surface->xdg_surface = wl_resource_create (client, &xdg_surface_interface, wl_resource_get_version (resource), id);
|
||||
wl_resource_set_implementation (surface->xdg_surface, &meta_wayland_xdg_surface_interface, surface, xdg_surface_destructor);
|
||||
|
||||
surface->xdg_shell_resource = resource;
|
||||
|
||||
window = meta_window_wayland_new (meta_get_display (), surface);
|
||||
@ -1037,7 +985,7 @@ xdg_popup_destructor (struct wl_resource *resource)
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
destroy_window (surface);
|
||||
destroy_surface_extension (&surface->xdg_popup);
|
||||
surface->xdg_popup = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1067,15 +1015,12 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
|
||||
MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource);
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
MetaWindow *window;
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
if (parent_surf == NULL || parent_surf->window == NULL)
|
||||
return;
|
||||
|
||||
if (!create_surface_extension (&surface->xdg_popup,
|
||||
&xdg_popup_interface,
|
||||
&meta_wayland_xdg_popup_interface,
|
||||
xdg_popup_destructor,
|
||||
surface, resource, id))
|
||||
if (surface->xdg_popup != NULL)
|
||||
{
|
||||
wl_resource_post_error (surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
@ -1083,9 +1028,12 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
|
||||
return;
|
||||
}
|
||||
|
||||
surface->xdg_popup = wl_resource_create (client, &xdg_popup_interface, wl_resource_get_version (resource), id);
|
||||
wl_resource_set_implementation (surface->xdg_popup, &meta_wayland_xdg_popup_interface, surface, xdg_popup_destructor);
|
||||
|
||||
surface->xdg_shell_resource = resource;
|
||||
|
||||
window = meta_window_wayland_new (meta_get_display (), surface);
|
||||
window = meta_window_wayland_new (display, surface);
|
||||
meta_window_move_frame (window, FALSE,
|
||||
parent_surf->window->rect.x + x,
|
||||
parent_surf->window->rect.y + y);
|
||||
@ -1096,6 +1044,7 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
|
||||
|
||||
meta_wayland_surface_set_window (surface, window);
|
||||
|
||||
meta_window_focus (window, meta_display_get_current_time (display));
|
||||
meta_wayland_pointer_start_popup_grab (&seat->pointer, surface);
|
||||
}
|
||||
|
||||
@ -1129,7 +1078,7 @@ wl_shell_surface_destructor (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
destroy_surface_extension (&surface->wl_shell_surface);
|
||||
surface->wl_shell_surface = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1337,11 +1286,7 @@ wl_shell_get_shell_surface (struct wl_client *client,
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||
MetaWindow *window;
|
||||
|
||||
if (!create_surface_extension (&surface->wl_shell_surface,
|
||||
&wl_shell_surface_interface,
|
||||
&meta_wayland_wl_shell_surface_interface,
|
||||
wl_shell_surface_destructor,
|
||||
surface, resource, id))
|
||||
if (surface->wl_shell_surface != NULL)
|
||||
{
|
||||
wl_resource_post_error (surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
@ -1349,6 +1294,9 @@ wl_shell_get_shell_surface (struct wl_client *client,
|
||||
return;
|
||||
}
|
||||
|
||||
surface->wl_shell_surface = wl_resource_create (client, &wl_shell_surface_interface, wl_resource_get_version (resource), id);
|
||||
wl_resource_set_implementation (surface->wl_shell_surface, &meta_wayland_wl_shell_surface_interface, surface, wl_shell_surface_destructor);
|
||||
|
||||
window = meta_window_wayland_new (meta_get_display (), surface);
|
||||
meta_wayland_surface_set_window (surface, window);
|
||||
}
|
||||
@ -1374,7 +1322,7 @@ gtk_surface_destructor (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
destroy_surface_extension (&surface->gtk_surface);
|
||||
surface->gtk_surface = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1417,17 +1365,16 @@ get_gtk_surface (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||
|
||||
if (!create_surface_extension (&surface->gtk_surface,
|
||||
>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 = {
|
||||
@ -1441,12 +1388,15 @@ bind_gtk_shell (struct wl_client *client,
|
||||
guint32 id)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
uint32_t capabilities = 0;
|
||||
|
||||
resource = wl_resource_create (client, >k_shell_interface, version, id);
|
||||
wl_resource_set_implementation (resource, &meta_wayland_gtk_shell_interface, data, NULL);
|
||||
|
||||
/* FIXME: ask the plugin */
|
||||
gtk_shell_send_capabilities (resource, GTK_SHELL_CAPABILITY_GLOBAL_APP_MENU);
|
||||
if (!meta_prefs_get_show_fallback_app_menu ())
|
||||
capabilities = GTK_SHELL_CAPABILITY_GLOBAL_APP_MENU;
|
||||
|
||||
gtk_shell_send_capabilities (resource, capabilities);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1525,7 +1475,7 @@ wl_subsurface_destructor (struct wl_resource *resource)
|
||||
}
|
||||
|
||||
pending_state_destroy (&surface->sub.pending);
|
||||
destroy_surface_extension (&surface->subsurface);
|
||||
surface->wl_subsurface = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1651,7 +1601,7 @@ wl_subsurface_set_desync (struct wl_client *client,
|
||||
surface->sub.synchronous = FALSE;
|
||||
}
|
||||
|
||||
static const struct wl_subsurface_interface meta_wayland_subsurface_interface = {
|
||||
static const struct wl_subsurface_interface meta_wayland_wl_subsurface_interface = {
|
||||
wl_subsurface_destroy,
|
||||
wl_subsurface_set_position,
|
||||
wl_subsurface_place_above,
|
||||
@ -1689,11 +1639,7 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||
MetaWaylandSurface *parent = wl_resource_get_user_data (parent_resource);
|
||||
|
||||
if (!create_surface_extension (&surface->subsurface,
|
||||
&wl_subsurface_interface,
|
||||
&meta_wayland_subsurface_interface,
|
||||
wl_subsurface_destructor,
|
||||
surface, resource, id))
|
||||
if (surface->wl_subsurface != NULL)
|
||||
{
|
||||
wl_resource_post_error (surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
@ -1701,6 +1647,9 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
|
||||
return;
|
||||
}
|
||||
|
||||
surface->wl_subsurface = wl_resource_create (client, &wl_subsurface_interface, wl_resource_get_version (resource), id);
|
||||
wl_resource_set_implementation (surface->wl_subsurface, &meta_wayland_wl_subsurface_interface, surface, wl_subsurface_destructor);
|
||||
|
||||
pending_state_init (&surface->sub.pending);
|
||||
surface->sub.synchronous = TRUE;
|
||||
surface->sub.parent = parent;
|
||||
@ -1792,9 +1741,9 @@ meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
|
||||
int new_height,
|
||||
MetaWaylandSerial *sent_serial)
|
||||
{
|
||||
if (surface->xdg_surface.resource)
|
||||
if (surface->xdg_surface)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (surface->xdg_surface.resource);
|
||||
struct wl_client *client = wl_resource_get_client (surface->xdg_surface);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial = wl_display_next_serial (display);
|
||||
struct wl_array states;
|
||||
@ -1808,7 +1757,7 @@ meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
|
||||
new_width /= surface->scale;
|
||||
new_height /= surface->scale;
|
||||
|
||||
xdg_surface_send_configure (surface->xdg_surface.resource, new_width, new_height, &states, serial);
|
||||
xdg_surface_send_configure (surface->xdg_surface, new_width, new_height, &states, serial);
|
||||
|
||||
wl_array_release (&states);
|
||||
|
||||
@ -1818,13 +1767,13 @@ meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
|
||||
sent_serial->value = serial;
|
||||
}
|
||||
}
|
||||
else if (surface->xdg_popup.resource)
|
||||
else if (surface->xdg_popup)
|
||||
{
|
||||
/* This can happen if the popup window loses or receives focus.
|
||||
* Just ignore it. */
|
||||
}
|
||||
else if (surface->wl_shell_surface.resource)
|
||||
wl_shell_surface_send_configure (surface->wl_shell_surface.resource,
|
||||
else if (surface->wl_shell_surface)
|
||||
wl_shell_surface_send_configure (surface->wl_shell_surface,
|
||||
0, new_width, new_height);
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
@ -1836,15 +1785,15 @@ meta_wayland_surface_ping (MetaWaylandSurface *surface,
|
||||
{
|
||||
if (surface->xdg_shell_resource)
|
||||
xdg_shell_send_ping (surface->xdg_shell_resource, serial);
|
||||
else if (surface->wl_shell_surface.resource)
|
||||
wl_shell_surface_send_ping (surface->wl_shell_surface.resource, serial);
|
||||
else if (surface->wl_shell_surface)
|
||||
wl_shell_surface_send_ping (surface->wl_shell_surface, serial);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_delete (MetaWaylandSurface *surface)
|
||||
{
|
||||
if (surface->xdg_surface.resource)
|
||||
xdg_surface_send_close (surface->xdg_surface.resource);
|
||||
if (surface->xdg_surface)
|
||||
xdg_surface_send_close (surface->xdg_surface);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1854,8 +1803,8 @@ meta_wayland_surface_popup_done (MetaWaylandSurface *surface)
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial = wl_display_next_serial (display);
|
||||
|
||||
if (surface->xdg_popup.resource)
|
||||
xdg_popup_send_popup_done (surface->xdg_popup.resource, serial);
|
||||
else if (surface->wl_shell_surface.resource)
|
||||
wl_shell_surface_send_popup_done (surface->wl_shell_surface.resource);
|
||||
if (surface->xdg_popup)
|
||||
xdg_popup_send_popup_done (surface->xdg_popup, serial);
|
||||
else if (surface->wl_shell_surface)
|
||||
wl_shell_surface_send_popup_done (surface->wl_shell_surface);
|
||||
}
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user