Compare commits

..

2 Commits

Author SHA1 Message Date
Rui Matos
f7e243108d Bump version to 3.16.1.1
Update NEWS.
2015-04-15 14:48:56 +02:00
Carlos Garnacho
0d6420df51 backend: Apply the right settings to the right input devices
Since 8769b3d55, the checks performed on which update_* function was
called for each device got quite more lax, leading to failed asserts
on code that assumed the previous behavior.

Change update_[mouse|touchpad|trackball]_* to bail out early if the
device received has not the right type, and remove the asserts.

https://bugzilla.gnome.org/show_bug.cgi?id=747886
2015-04-15 14:44:11 +02:00
35 changed files with 196 additions and 1701 deletions

23
NEWS
View File

@@ -1,24 +1,9 @@
3.17.2
======
* Honor default value for click method setting [Rui; #746290]
* Add X11/wayland clipboard interoperation [Carlos; #738312]
* Misc. bug fixes [Rui; #749076, #749711]
3.16.1.1
========
* Prevent a crash when switching VTs or adding input devices [Carlos; #747886]
Contributors:
Carlos Garnacho, Rui Matos, Jasper St. Pierre
3.17.1
======
* Add public method to get neighboring monitor [Florian; #633994]
* Apply the right settings to the right input devices [Carlos; #747886]
* Fix scroll button setting [Ondrej; #747967]
* Add support for modal hint on wayland [Jonas; #745720]
* Don't reset idle time for non-hardware events [Rui; #748541]
* Misc. bug fixes [Ray, Rui; #748380, #748478]
Contributors:
Jonas Ådahl, Carlos Garnacho, Ondrej Holy, Rui Matos, Florian Müllner,
Jasper St. Pierre, Ray Strode, Tomeu Vizoso
Carlos Garnacho
3.16.1
======

View File

@@ -1,8 +1,8 @@
AC_PREREQ(2.62)
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [17])
m4_define([mutter_micro_version], [2])
m4_define([mutter_minor_version], [16])
m4_define([mutter_micro_version], [1.1])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])

View File

@@ -210,9 +210,10 @@ libmutter_la_SOURCES = \
meta/theme.h \
ui/theme-private.h \
ui/ui.c \
x11/iconcache.c \
x11/iconcache.h \
x11/async-getprop.c \
x11/async-getprop.h \
x11/atomnames.h \
x11/events.c \
x11/events.h \
x11/group-private.h \
@@ -220,8 +221,6 @@ libmutter_la_SOURCES = \
x11/group-props.h \
x11/group.c \
meta/group.h \
x11/iconcache.c \
x11/iconcache.h \
x11/session.c \
x11/session.h \
x11/window-props.c \
@@ -243,7 +242,6 @@ libmutter_la_SOURCES += \
wayland/meta-wayland-private.h \
wayland/meta-xwayland.c \
wayland/meta-xwayland.h \
wayland/meta-xwayland-selection.c \
wayland/meta-xwayland-private.h \
wayland/meta-wayland-buffer.c \
wayland/meta-wayland-buffer.h \
@@ -267,8 +265,8 @@ libmutter_la_SOURCES += \
wayland/meta-wayland-versions.h \
wayland/meta-wayland-outputs.c \
wayland/meta-wayland-outputs.h \
wayland/meta-window-wayland.c \
wayland/meta-window-wayland.h \
wayland/window-wayland.c \
wayland/window-wayland.h \
$(NULL)
endif
@@ -340,10 +338,16 @@ libmutterinclude_base_headers = \
$(libmutterinclude_headers) \
$(libmutterinclude_built_headers)
# Excluded from scanning for introspection but installed
# atomnames.h: macros cause problems for scanning process
libmutterinclude_extra_headers = \
meta/atomnames.h
libmutterincludedir = $(includedir)/mutter/meta
libmutterinclude_HEADERS = \
$(libmutterinclude_headers)
$(libmutterinclude_headers) \
$(libmutterinclude_extra_headers)
nodist_libmutterinclude_HEADERS = \
$(libmutterinclude_built_headers)

View File

@@ -65,7 +65,6 @@ typedef struct {
gboolean is_primary;
gboolean is_presentation;
gboolean is_underscanning;
} MetaOutputConfig;
typedef struct {
@@ -83,8 +82,7 @@ struct _MetaMonitorConfig {
gboolean current_is_for_laptop_lid;
MetaConfiguration *previous;
GFile *user_file;
GFile *system_file;
GFile *file;
GCancellable *save_cancellable;
UpClient *up_client;
@@ -240,7 +238,6 @@ meta_monitor_config_init (MetaMonitorConfig *self)
{
const char *filename;
char *path;
const char * const *system_dirs;
self->configs = g_hash_table_new_full (config_hash, config_equal, NULL, (GDestroyNotify) config_unref);
@@ -249,17 +246,9 @@ meta_monitor_config_init (MetaMonitorConfig *self)
filename = "monitors.xml";
path = g_build_filename (g_get_user_config_dir (), filename, NULL);
self->user_file = g_file_new_for_path (path);
self->file = g_file_new_for_path (path);
g_free (path);
for (system_dirs = g_get_system_config_dirs (); !self->system_file && *system_dirs; system_dirs++)
{
path = g_build_filename (*system_dirs, filename, NULL);
if (g_file_test (path, G_FILE_TEST_EXISTS))
self->system_file = g_file_new_for_path (path);
g_free (path);
}
self->up_client = up_client_new ();
self->lid_is_closed = up_client_get_lid_is_closed (self->up_client);
@@ -404,8 +393,7 @@ handle_start_element (GMarkupParseContext *context,
strcmp (element_name, "reflect_x") == 0 ||
strcmp (element_name, "reflect_y") == 0 ||
strcmp (element_name, "primary") == 0 ||
strcmp (element_name, "presentation") == 0 ||
strcmp (element_name, "underscanning") == 0) && parser->unknown_count == 0)
strcmp (element_name, "presentation") == 0) && parser->unknown_count == 0)
{
parser->state = STATE_OUTPUT_FIELD;
@@ -712,8 +700,6 @@ handle_text (GMarkupParseContext *context,
parser->output.is_primary = read_bool (text, text_len, error);
else if (strcmp (parser->output_field, "presentation") == 0)
parser->output.is_presentation = read_bool (text, text_len, error);
else if (strcmp (parser->output_field, "underscanning") == 0)
parser->output.is_underscanning = read_bool (text, text_len, error);
else
g_assert_not_reached ();
return;
@@ -731,8 +717,8 @@ static const GMarkupParser config_parser = {
.text = handle_text,
};
static gboolean
load_config_file (MetaMonitorConfig *self, GFile *file)
static void
meta_monitor_config_load (MetaMonitorConfig *self)
{
char *contents;
gsize size;
@@ -750,12 +736,14 @@ load_config_file (MetaMonitorConfig *self, GFile *file)
*/
error = NULL;
ok = g_file_load_contents (file, NULL, &contents, &size, NULL, &error);
ok = g_file_load_contents (self->file, NULL, &contents, &size, NULL, &error);
if (!ok)
{
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
meta_warning ("Failed to load stored monitor configuration: %s\n", error->message);
g_error_free (error);
return FALSE;
return;
}
memset (&parser, 0, sizeof (ConfigParser));
@@ -784,17 +772,6 @@ load_config_file (MetaMonitorConfig *self, GFile *file)
g_markup_parse_context_free (context);
g_free (contents);
return ok;
}
static void
meta_monitor_config_load (MetaMonitorConfig *self)
{
if (self->user_file && load_config_file (self, self->user_file))
return;
if (self->system_file && load_config_file (self, self->system_file))
return;
}
MetaMonitorConfig *
@@ -1431,7 +1408,6 @@ init_config_from_output (MetaOutputConfig *config,
config->transform = output->crtc->transform;
config->is_primary = output->is_primary;
config->is_presentation = output->is_presentation;
config->is_underscanning = output->is_underscanning;
}
void
@@ -1622,8 +1598,7 @@ meta_monitor_config_save (MetaMonitorConfig *self)
" <reflect_x>%s</reflect_x>\n"
" <reflect_y>no</reflect_y>\n"
" <primary>%s</primary>\n"
" <presentation>%s</presentation>\n"
" <underscanning>%s</underscanning>\n",
" <presentation>%s</presentation>\n",
output->rect.width,
output->rect.height,
refresh_rate,
@@ -1632,8 +1607,7 @@ meta_monitor_config_save (MetaMonitorConfig *self)
rotation_map[output->transform & 0x3],
output->transform >= META_MONITOR_TRANSFORM_FLIPPED ? "yes" : "no",
output->is_primary ? "yes" : "no",
output->is_presentation ? "yes" : "no",
output->is_underscanning ? "yes" : "no");
output->is_presentation ? "yes" : "no");
}
g_string_append (buffer, " </output>\n");
@@ -1648,7 +1622,7 @@ meta_monitor_config_save (MetaMonitorConfig *self)
closure->config = g_object_ref (self);
closure->buffer = buffer;
g_file_replace_contents_async (self->user_file,
g_file_replace_contents_async (self->file,
buffer->str, buffer->len,
NULL, /* etag */
TRUE,
@@ -1967,7 +1941,6 @@ meta_monitor_config_assign_crtcs (MetaConfiguration *config,
&config->keys[i]);
output_info->is_primary = output_config->is_primary;
output_info->is_presentation = output_config->is_presentation;
output_info->is_underscanning = output_config->is_underscanning;
g_ptr_array_add (outputs, output_info);
}

View File

@@ -132,7 +132,6 @@ struct _MetaOutput
*/
gboolean is_primary;
gboolean is_presentation;
gboolean is_underscanning;
gpointer driver_private;
GDestroyNotify driver_notify;
@@ -160,9 +159,6 @@ struct _MetaCRTC
gboolean is_dirty;
MetaCursorReference *cursor;
gpointer driver_private;
GDestroyNotify driver_notify;
};
struct _MetaMonitorMode
@@ -234,7 +230,6 @@ struct _MetaOutputInfo {
MetaOutput *output;
gboolean is_primary;
gboolean is_presentation;
gboolean is_underscanning;
};
#define META_TYPE_MONITOR_MANAGER (meta_monitor_manager_get_type ())

View File

@@ -264,21 +264,6 @@ meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
g_free (old_modes);
}
static void
meta_monitor_manager_free_crtc_array (MetaCRTC *old_crtcs,
int n_old_crtcs)
{
int i;
for (i = 0; i < n_old_crtcs; i++)
{
if (old_crtcs[i].driver_notify)
old_crtcs[i].driver_notify (&old_crtcs[i]);
}
g_free (old_crtcs);
}
static void
meta_monitor_manager_finalize (GObject *object)
{
@@ -286,8 +271,8 @@ meta_monitor_manager_finalize (GObject *object)
meta_monitor_manager_free_output_array (manager->outputs, manager->n_outputs);
meta_monitor_manager_free_mode_array (manager->modes, manager->n_modes);
meta_monitor_manager_free_crtc_array (manager->crtcs, manager->n_crtcs);
g_free (manager->monitor_infos);
g_free (manager->crtcs);
G_OBJECT_CLASS (meta_monitor_manager_parent_class)->finalize (object);
}
@@ -535,8 +520,6 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
g_variant_new_boolean (output->is_presentation));
g_variant_builder_add (&properties, "{sv}", "connector-type",
g_variant_new_string (get_connector_type_name (output->connector_type)));
g_variant_builder_add (&properties, "{sv}", "underscanning",
g_variant_new_boolean (output->is_underscanning));
edid_file = manager_class->get_edid_file (manager, output);
if (edid_file)
@@ -825,7 +808,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
while (g_variant_iter_loop (&output_iter, "(u@a{sv})", &output_index, &properties))
{
MetaOutputInfo *output_info;
gboolean primary, presentation, underscanning;
gboolean primary, presentation;
if (output_index >= manager->n_outputs)
{
@@ -844,9 +827,6 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
if (g_variant_lookup (properties, "presentation", "b", &presentation))
output_info->is_presentation = presentation;
if (g_variant_lookup (properties, "underscanning", "b", &underscanning))
output_info->is_underscanning = underscanning;
g_ptr_array_add (output_infos, output_info);
}
@@ -1214,24 +1194,23 @@ meta_monitor_manager_read_current_config (MetaMonitorManager *manager)
MetaOutput *old_outputs;
MetaCRTC *old_crtcs;
MetaMonitorMode *old_modes;
unsigned int n_old_outputs, n_old_crtcs, n_old_modes;
unsigned int n_old_outputs, n_old_modes;
/* Some implementations of read_current use the existing information
* we have available, so don't free the old configuration until after
* read_current finishes. */
old_outputs = manager->outputs;
n_old_outputs = manager->n_outputs;
old_crtcs = manager->crtcs;
n_old_crtcs = manager->n_crtcs;
old_modes = manager->modes;
n_old_modes = manager->n_modes;
old_crtcs = manager->crtcs;
manager->serial++;
META_MONITOR_MANAGER_GET_CLASS (manager)->read_current (manager);
meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
meta_monitor_manager_free_crtc_array (old_crtcs, n_old_crtcs);
g_free (old_crtcs);
}
void

View File

@@ -29,7 +29,6 @@
#include <meta/main.h>
#include <clutter/evdev/clutter-evdev.h>
#include <libupower-glib/upower.h>
#include "meta-barrier-native.h"
#include "meta-idle-monitor-native.h"
@@ -40,8 +39,10 @@
struct _MetaBackendNativePrivate
{
MetaLauncher *launcher;
MetaBarrierManagerNative *barrier_manager;
UpClient *up_client;
GSettings *keyboard_settings;
};
typedef struct _MetaBackendNativePrivate MetaBackendNativePrivate;
@@ -55,22 +56,9 @@ meta_backend_native_finalize (GObject *object)
meta_launcher_free (priv->launcher);
g_object_unref (priv->up_client);
G_OBJECT_CLASS (meta_backend_native_parent_class)->finalize (object);
}
static void
lid_is_closed_changed_cb (UpClient *client,
GParamSpec *pspec,
gpointer user_data)
{
if (up_client_get_lid_is_closed (client))
return;
meta_idle_monitor_native_reset_idletime (meta_idle_monitor_get_core ());
}
static void
constrain_to_barriers (ClutterInputDevice *device,
guint32 time,
@@ -282,10 +270,6 @@ meta_backend_native_init (MetaBackendNative *native)
priv->launcher = meta_launcher_new ();
priv->barrier_manager = meta_barrier_manager_native_new ();
priv->up_client = up_client_new ();
g_signal_connect (priv->up_client, "notify::lid-is-closed",
G_CALLBACK (lid_is_closed_changed_cb), NULL);
}
gboolean

View File

@@ -57,12 +57,6 @@ typedef struct {
uint32_t edid_blob_id;
} MetaOutputKms;
typedef struct {
uint32_t underscan_prop_id;
uint32_t underscan_hborder_prop_id;
uint32_t underscan_vborder_prop_id;
} MetaCRTCKms;
struct _MetaMonitorManagerKms
{
MetaMonitorManager parent_instance;
@@ -143,12 +137,6 @@ meta_monitor_mode_destroy_notify (MetaMonitorMode *output)
g_slice_free (drmModeModeInfo, output->driver_private);
}
static void
meta_crtc_destroy_notify (MetaCRTC *crtc)
{
g_free (crtc->driver_private);
}
static gboolean
drm_mode_equal (gconstpointer one,
gconstpointer two)
@@ -193,57 +181,29 @@ drm_mode_hash (gconstpointer ptr)
}
static void
find_connector_properties (MetaMonitorManagerKms *manager_kms,
MetaOutputKms *output_kms)
find_properties (MetaMonitorManagerKms *manager_kms,
MetaOutputKms *output_kms)
{
drmModePropertyPtr prop;
int i;
for (i = 0; i < output_kms->connector->count_props; i++)
{
drmModePropertyPtr prop = drmModeGetProperty (manager_kms->fd, output_kms->connector->props[i]);
prop = drmModeGetProperty (manager_kms->fd, output_kms->connector->props[i]);
if (!prop)
continue;
if ((prop->flags & DRM_MODE_PROP_ENUM) && strcmp (prop->name, "DPMS") == 0)
if ((prop->flags & DRM_MODE_PROP_ENUM) &&
strcmp(prop->name, "DPMS") == 0)
output_kms->dpms_prop_id = prop->prop_id;
else if ((prop->flags & DRM_MODE_PROP_BLOB) && strcmp (prop->name, "EDID") == 0)
else if ((prop->flags & DRM_MODE_PROP_BLOB) &&
strcmp (prop->name, "EDID") == 0)
output_kms->edid_blob_id = output_kms->connector->prop_values[i];
drmModeFreeProperty (prop);
}
}
static void
find_crtc_properties (MetaMonitorManagerKms *manager_kms,
MetaCRTC *meta_crtc)
{
MetaCRTCKms *crtc_kms;
drmModeObjectPropertiesPtr props;
size_t i;
crtc_kms = meta_crtc->driver_private;
props = drmModeObjectGetProperties (manager_kms->fd, meta_crtc->crtc_id, DRM_MODE_OBJECT_CRTC);
if (!props)
return;
for (i = 0; i < props->count_props; i++)
{
drmModePropertyPtr prop = drmModeGetProperty (manager_kms->fd, props->props[i]);
if (!prop)
continue;
if ((prop->flags & DRM_MODE_PROP_ENUM) && strcmp (prop->name, "underscan") == 0)
crtc_kms->underscan_prop_id = prop->prop_id;
else if ((prop->flags & DRM_MODE_PROP_RANGE) && strcmp (prop->name, "underscan hborder") == 0)
crtc_kms->underscan_hborder_prop_id = prop->prop_id;
else if ((prop->flags & DRM_MODE_PROP_RANGE) && strcmp (prop->name, "underscan vborder") == 0)
crtc_kms->underscan_vborder_prop_id = prop->prop_id;
drmModeFreeProperty (prop);
}
}
static GBytes *
read_output_edid (MetaMonitorManagerKms *manager_kms,
MetaOutput *output)
@@ -482,10 +442,6 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
height = MAX (height, meta_crtc->rect.y + meta_crtc->rect.height);
}
meta_crtc->driver_private = g_new0 (MetaCRTCKms, 1);
meta_crtc->driver_notify = (GDestroyNotify) meta_crtc_destroy_notify;
find_crtc_properties (manager_kms, meta_crtc);
drmModeFreeCrtc (crtc);
}
@@ -611,7 +567,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_output->is_presentation = FALSE;
}
find_connector_properties (manager_kms, output_kms);
find_properties (manager_kms, output_kms);
edid = read_output_edid (manager_kms, meta_output);
meta_output_parse_edid (meta_output, edid);
@@ -767,9 +723,8 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
if (output_kms->dpms_prop_id != 0)
{
int ok = drmModeObjectSetProperty (manager_kms->fd, meta_output->winsys_id,
DRM_MODE_OBJECT_CONNECTOR,
output_kms->dpms_prop_id, state);
int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->winsys_id,
output_kms->dpms_prop_id, state);
if (ok < 0)
meta_warning ("Failed to set power save mode for output %s: %s\n",
@@ -793,48 +748,6 @@ crtc_free (CoglKmsCrtc *crtc)
g_slice_free (CoglKmsCrtc, crtc);
}
static void
set_underscan (MetaMonitorManagerKms *manager_kms,
MetaOutput *output)
{
if (!output->crtc)
return;
MetaCRTC *crtc = output->crtc;
MetaCRTCKms *crtc_kms = crtc->driver_private;
if (!crtc_kms->underscan_prop_id)
return;
if (output->is_underscanning)
{
drmModeObjectSetProperty (manager_kms->fd, crtc->crtc_id,
DRM_MODE_OBJECT_CRTC,
crtc_kms->underscan_prop_id, (uint64_t) 1);
if (crtc_kms->underscan_hborder_prop_id)
{
uint64_t value = crtc->current_mode->width * 0.05;
drmModeObjectSetProperty (manager_kms->fd, crtc->crtc_id,
DRM_MODE_OBJECT_CRTC,
crtc_kms->underscan_hborder_prop_id, value);
}
if (crtc_kms->underscan_vborder_prop_id)
{
uint64_t value = crtc->current_mode->height * 0.05;
drmModeObjectSetProperty (manager_kms->fd, crtc->crtc_id,
DRM_MODE_OBJECT_CRTC,
crtc_kms->underscan_vborder_prop_id, value);
}
}
else
{
drmModeObjectSetProperty (manager_kms->fd, crtc->crtc_id,
DRM_MODE_OBJECT_CRTC,
crtc_kms->underscan_prop_id, (uint64_t) 0);
}
}
static void
meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
MetaCRTCInfo **crtcs,
@@ -842,7 +755,6 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
MetaOutputInfo **outputs,
unsigned int n_outputs)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
ClutterBackend *backend;
CoglContext *cogl_context;
CoglDisplay *cogl_display;
@@ -988,9 +900,6 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
output->is_primary = output_info->is_primary;
output->is_presentation = output_info->is_presentation;
output->is_underscanning = output_info->is_underscanning;
set_underscan (manager_kms, output);
}
/* Disable outputs not mentioned in the list */

View File

@@ -26,7 +26,6 @@
#include "meta-backend-x11.h"
#include "meta-input-settings-x11.h"
#include <string.h>
#include <gdk/gdkx.h>
#include <X11/Xatom.h>
#include <X11/extensions/XInput2.h>
@@ -36,38 +35,6 @@
G_DEFINE_TYPE (MetaInputSettingsX11, meta_input_settings_x11, META_TYPE_INPUT_SETTINGS)
static void *
get_property (ClutterInputDevice *device,
const gchar *property,
Atom type,
int format,
gulong nitems)
{
MetaBackend *backend = meta_get_backend ();
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
gulong nitems_ret, bytes_after_ret;
int rc, device_id, format_ret;
Atom property_atom, type_ret;
guchar *data_ret = NULL;
property_atom = XInternAtom (xdisplay, property, False);
device_id = clutter_input_device_get_device_id (device);
rc = XIGetProperty (xdisplay, device_id, property_atom,
0, 10, False, type, &type_ret, &format_ret,
&nitems_ret, &bytes_after_ret, &data_ret);
if (rc == Success && type_ret == type && format_ret == format && nitems_ret >= nitems)
{
if (nitems_ret > nitems)
g_warning ("Property '%s' for device '%s' returned %lu items, expected %lu",
property, clutter_input_device_get_device_name (device), nitems_ret, nitems);
return data_ret;
}
meta_XFree (data_ret);
return NULL;
}
static void
change_property (ClutterInputDevice *device,
const gchar *property,
@@ -78,20 +45,23 @@ change_property (ClutterInputDevice *device,
{
MetaBackend *backend = meta_get_backend ();
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
int device_id;
Atom property_atom;
gulong nitems_ret, bytes_after_ret;
int rc, device_id, format_ret;
Atom property_atom, type_ret;
guchar *data_ret;
property_atom = XInternAtom (xdisplay, property, False);
device_id = clutter_input_device_get_device_id (device);
data_ret = get_property (device, property, type, format, nitems);
if (!data_ret)
return;
rc = XIGetProperty (xdisplay, device_id, property_atom,
0, 0, False, type, &type_ret, &format_ret,
&nitems_ret, &bytes_after_ret, &data_ret);
XIChangeProperty (xdisplay, device_id, property_atom, type,
format, XIPropModeReplace, data, nitems);
meta_XFree (data_ret);
if (rc == Success && type_ret == type && format_ret == format)
XIChangeProperty (xdisplay, device_id, property_atom, type,
format, XIPropModeReplace, data, nitems);
}
static void
@@ -210,7 +180,7 @@ meta_input_settings_x11_set_scroll_button (MetaInputSettings *settings,
ClutterInputDevice *device,
guint button)
{
change_property (device, "libinput Button Scrolling Button",
change_property (device, "libinput Scroll Method Enabled",
XA_INTEGER, 32, &button, 1);
}
@@ -220,23 +190,16 @@ meta_input_settings_x11_set_click_method (MetaInputSettings *settings,
GDesktopTouchpadClickMethod mode)
{
guchar values[2] = { 0 }; /* buttonareas, clickfinger */
guchar *defaults;
switch (mode)
{
case G_DESKTOP_TOUCHPAD_CLICK_METHOD_DEFAULT:
defaults = get_property (device, "libinput Click Method Enabled Default",
XA_INTEGER, 8, 2);
if (!defaults)
break;
memcpy (values, defaults, 2);
meta_XFree (defaults);
break;
case G_DESKTOP_TOUCHPAD_CLICK_METHOD_NONE:
break;
case G_DESKTOP_TOUCHPAD_CLICK_METHOD_AREAS:
values[0] = 1;
break;
case G_DESKTOP_TOUCHPAD_CLICK_METHOD_DEFAULT:
/* XXX: We can't be much smarter yet, x11 doesn't expose default settings */
case G_DESKTOP_TOUCHPAD_CLICK_METHOD_FINGERS:
values[1] = 1;
break;

View File

@@ -225,38 +225,6 @@ output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
return output_get_boolean_property (manager_xrandr, output, "_MUTTER_PRESENTATION_OUTPUT");
}
static gboolean
output_get_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output)
{
gboolean value = FALSE;
Atom atom, actual_type;
int actual_format;
unsigned long nitems, bytes_after;
unsigned char *buffer;
char *str;
atom = XInternAtom (manager_xrandr->xdisplay, "underscan", False);
XRRGetOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
atom,
0, G_MAXLONG, False, False, XA_ATOM,
&actual_type, &actual_format,
&nitems, &bytes_after, &buffer);
if (actual_type != XA_ATOM || actual_format != 32 ||
nitems < 1)
goto out;
str = XGetAtomName (manager_xrandr->xdisplay, *(Atom *)buffer);
value = !strcmp(str, "on");
XFree (str);
out:
XFree (buffer);
return value;
}
static int
normalize_backlight (MetaOutput *output,
int hw_value)
@@ -538,7 +506,7 @@ output_get_connector_type_from_name (MetaMonitorManagerXrandr *manager_xrandr,
if (g_str_has_prefix (name, "Virtual"))
return META_CONNECTOR_TYPE_VIRTUAL;
if (g_str_has_prefix (name, "Composite"))
return META_CONNECTOR_TYPE_Composite;
return META_CONNECTOR_TYPE_VGA;
if (g_str_has_prefix (name, "S-video"))
return META_CONNECTOR_TYPE_SVIDEO;
if (g_str_has_prefix (name, "TV"))
@@ -788,7 +756,6 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
meta_output->is_primary = ((XID)meta_output->winsys_id == primary_output);
meta_output->is_presentation = output_get_presentation_xrandr (manager_xrandr, meta_output);
meta_output->is_underscanning = output_get_underscanning_xrandr (manager_xrandr, meta_output);
output_get_backlight_limits_xrandr (manager_xrandr, meta_output);
if (!(meta_output->backlight_min == 0 && meta_output->backlight_max == 0))
@@ -909,49 +876,6 @@ output_set_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
(unsigned char*) &value, 1);
}
static void
output_set_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output,
gboolean underscanning)
{
Atom prop, valueatom;
const char *value;
prop = XInternAtom (manager_xrandr->xdisplay, "underscan", False);
value = underscanning ? "on" : "off";
valueatom = XInternAtom (manager_xrandr->xdisplay, value, False);
XRRChangeOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
prop,
XA_ATOM, 32, PropModeReplace,
(unsigned char*) &valueatom, 1);
/* Configure the border at the same time. Currently, we use a
* 5% of the width/height of the mode. In the future, we should
* make the border configurable. */
if (underscanning)
{
uint32_t border_value;
prop = XInternAtom (manager_xrandr->xdisplay, "underscan hborder", False);
border_value = output->crtc->current_mode->width * 0.05;
XRRChangeOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
prop,
XA_INTEGER, 32, PropModeReplace,
(unsigned char *) &border_value, 1);
prop = XInternAtom (manager_xrandr->xdisplay, "underscan vborder", False);
border_value = output->crtc->current_mode->height * 0.05;
XRRChangeOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
prop,
XA_INTEGER, 32, PropModeReplace,
(unsigned char *) &border_value, 1);
}
}
static void
meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
MetaCRTCInfo **crtcs,
@@ -1147,13 +1071,8 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
output_info->output,
output_info->is_presentation);
output_set_underscanning_xrandr (manager_xrandr,
output_info->output,
output_info->is_underscanning);
output->is_primary = output_info->is_primary;
output->is_presentation = output_info->is_presentation;
output->is_underscanning = output_info->is_underscanning;
}
/* Disable outputs not mentioned in the list */

View File

@@ -217,6 +217,19 @@ meta_core_show_window_menu_for_rect (Display *xdisplay,
meta_window_show_menu_for_rect (window, menu, rect);
}
const char*
meta_core_get_workspace_name_with_index (Display *xdisplay,
Window xroot,
int index)
{
MetaDisplay *display;
MetaWorkspace *workspace;
display = meta_display_for_x_display (xdisplay);
workspace = meta_screen_get_workspace_by_index (display->screen, index);
return workspace ? meta_workspace_get_name (workspace) : NULL;
}
gboolean
meta_core_begin_grab_op (Display *xdisplay,
Window frame_xwindow,

View File

@@ -47,6 +47,9 @@ void meta_core_change_workspace (Display *xdisplay,
int meta_core_get_frame_workspace (Display *xdisplay,
Window frame_xwindow);
const char* meta_core_get_workspace_name_with_index (Display *xdisplay,
Window xroot,
int index);
void meta_core_show_window_menu (Display *xdisplay,
Window frame_xwindow,

View File

@@ -160,7 +160,12 @@ void
meta_window_set_alive (MetaWindow *window,
gboolean is_alive)
{
if (is_alive)
if (window->is_alive == is_alive)
return;
window->is_alive = is_alive;
if (window->is_alive)
kill_delete_dialog (window);
else
show_delete_dialog (window, CurrentTime);

View File

@@ -121,7 +121,7 @@ struct _MetaDisplay
* class is constructed.
*/
#define item(x) Atom atom_##x;
#include <x11/atomnames.h>
#include <meta/atomnames.h>
#undef item
/* The window and serial of the most recent FocusIn event. */

View File

@@ -549,7 +549,7 @@ meta_display_open (void)
/* A list of all atom names, so that we can intern them in one go. */
char *atom_names[] = {
#define item(x) #x,
#include <x11/atomnames.h>
#include <meta/atomnames.h>
#undef item
};
Atom atoms[G_N_ELEMENTS(atom_names)];
@@ -610,7 +610,7 @@ meta_display_open (void)
{
int i = 0;
#define item(x) display->atom_##x = atoms[i++];
#include <x11/atomnames.h>
#include <meta/atomnames.h>
#undef item
}

View File

@@ -93,15 +93,6 @@ handle_idletime_for_event (const ClutterEvent *event)
if (device == NULL)
return;
if (event->any.flags & CLUTTER_EVENT_FLAG_SYNTHETIC ||
event->type == CLUTTER_ENTER ||
event->type == CLUTTER_LEAVE ||
event->type == CLUTTER_STAGE_STATE ||
event->type == CLUTTER_DESTROY_NOTIFY ||
event->type == CLUTTER_CLIENT_MESSAGE ||
event->type == CLUTTER_DELETE)
return;
device_id = clutter_input_device_get_device_id (device);
core_monitor = meta_idle_monitor_get_core ();
@@ -201,7 +192,6 @@ meta_display_handle_event (MetaDisplay *display,
{
MetaCursorTracker *tracker = meta_cursor_tracker_get_for_screen (NULL);
meta_cursor_tracker_update_position (tracker, event->motion.x, event->motion.y);
display->monitor_cache_invalidated = TRUE;
}
handle_idletime_for_event (event);

View File

@@ -41,6 +41,14 @@
typedef void (* MetaScreenWindowFunc) (MetaWindow *window,
gpointer user_data);
typedef enum
{
META_SCREEN_UP,
META_SCREEN_DOWN,
META_SCREEN_LEFT,
META_SCREEN_RIGHT
} MetaScreenDirection;
#define META_WIREFRAME_XOR_LINE_WIDTH 2
struct _MetaScreen

View File

@@ -294,7 +294,7 @@ set_supported_hint (MetaScreen *screen)
Atom atoms[] = {
#define EWMH_ATOMS_ONLY
#define item(x) screen->display->atom_##x,
#include <x11/atomnames.h>
#include <meta/atomnames.h>
#undef item
#undef EWMH_ATOMS_ONLY
@@ -1490,16 +1490,6 @@ meta_screen_get_monitor_neighbor (MetaScreen *screen,
return NULL;
}
int
meta_screen_get_monitor_neighbor_index (MetaScreen *screen,
int which_monitor,
MetaScreenDirection direction)
{
const MetaMonitorInfo *monitor;
monitor = meta_screen_get_monitor_neighbor (screen, which_monitor, direction);
return monitor ? monitor->number : -1;
}
void
meta_screen_get_natural_monitor_list (MetaScreen *screen,
int** monitors_list,

View File

@@ -434,6 +434,7 @@ struct _MetaWindow
/* Managed by delete.c */
int dialog_pid;
guint is_alive : 1;
/* maintained by group.c */
MetaGroup *group;

View File

@@ -57,7 +57,7 @@
#include "x11/xprops.h"
#ifdef HAVE_WAYLAND
#include "wayland/meta-window-wayland.h"
#include "wayland/window-wayland.h"
#include "wayland/meta-wayland-private.h"
#endif

View File

@@ -66,21 +66,6 @@ int meta_screen_get_active_workspace_index (MetaScreen *screen);
MetaWorkspace * meta_screen_get_active_workspace (MetaScreen *screen);
/**
* MetaScreenDirection:
* @META_SCREEN_UP: up
* @META_SCREEN_DOWN: down
* @META_SCREEN_LEFT: left
* @META_SCREEN_RIGHT: right
*/
typedef enum
{
META_SCREEN_UP,
META_SCREEN_DOWN,
META_SCREEN_LEFT,
META_SCREEN_RIGHT
} MetaScreenDirection;
int meta_screen_get_n_monitors (MetaScreen *screen);
int meta_screen_get_primary_monitor (MetaScreen *screen);
int meta_screen_get_current_monitor (MetaScreen *screen);
@@ -97,10 +82,6 @@ gboolean meta_screen_get_monitor_in_fullscreen (MetaScreen *screen,
int meta_screen_get_monitor_index_for_rect (MetaScreen *screen,
MetaRectangle *rect);
int meta_screen_get_monitor_neighbor_index (MetaScreen *screen,
int which_monitor,
MetaScreenDirection dir);
void meta_screen_focus_default_window (MetaScreen *screen,
guint32 timestamp);

View File

@@ -43,6 +43,13 @@ typedef struct
struct wl_listener source_destroy_listener;
} MetaWaylandDataOffer;
struct _MetaWaylandDataSource
{
struct wl_resource *resource;
struct wl_array mime_types;
gboolean has_target;
};
static void
unbind_resource (struct wl_resource *resource)
{
@@ -63,7 +70,7 @@ data_offer_accept (struct wl_client *client,
if (offer->source)
{
offer->source->funcs.target (offer->source, mime_type);
wl_data_source_send_target (offer->source->resource, mime_type);
offer->source->has_target = mime_type != NULL;
}
}
@@ -75,9 +82,9 @@ data_offer_receive (struct wl_client *client, struct wl_resource *resource,
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
if (offer->source)
meta_wayland_data_source_send (offer->source, mime_type, fd);
else
close (fd);
wl_data_source_send_send (offer->source->resource, mime_type, fd);
close (fd);
}
static void
@@ -97,7 +104,7 @@ destroy_data_offer (struct wl_resource *resource)
{
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
if (offer->source && offer->source->resource)
if (offer->source)
wl_list_remove (&offer->source_destroy_listener.link);
g_slice_free (MetaWaylandDataOffer, offer);
@@ -109,6 +116,7 @@ destroy_offer_data_source (struct wl_listener *listener, void *data)
MetaWaylandDataOffer *offer;
offer = wl_container_of (listener, offer, source_destroy_listener);
offer->source = NULL;
}
@@ -120,14 +128,11 @@ meta_wayland_data_source_send_offer (MetaWaylandDataSource *source,
char **p;
offer->source = source;
offer->source_destroy_listener.notify = destroy_offer_data_source;
offer->resource = wl_resource_create (wl_resource_get_client (target), &wl_data_offer_interface, wl_resource_get_version (target), 0);
wl_resource_set_implementation (offer->resource, &data_offer_interface, offer, destroy_data_offer);
if (source->resource)
{
offer->source_destroy_listener.notify = destroy_offer_data_source;
wl_resource_add_destroy_listener (source->resource, &offer->source_destroy_listener);
}
wl_resource_add_destroy_listener (source->resource, &offer->source_destroy_listener);
wl_data_device_send_data_offer (target, offer->resource);
@@ -142,8 +147,12 @@ data_source_offer (struct wl_client *client,
struct wl_resource *resource, const char *type)
{
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
char **p;
if (!meta_wayland_data_source_add_mime_type (source, type))
p = wl_array_add (&source->mime_types, sizeof *p);
if (p)
*p = strdup (type);
if (!p || !*p)
wl_resource_post_no_memory (resource);
}
@@ -282,7 +291,10 @@ 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)
{
@@ -343,7 +355,6 @@ destroy_data_device_origin (struct wl_listener *listener, void *data)
drag_grab->drag_origin = NULL;
data_device_end_drag_grab (drag_grab);
meta_wayland_data_device_set_dnd_source (&drag_grab->seat->data_device, NULL);
}
static void
@@ -354,14 +365,13 @@ destroy_data_device_source (struct wl_listener *listener, void *data)
drag_grab->drag_data_source = NULL;
data_device_end_drag_grab (drag_grab);
meta_wayland_data_device_set_dnd_source (&drag_grab->seat->data_device, NULL);
}
static void
destroy_data_device_icon (struct wl_listener *listener, void *data)
{
MetaWaylandDragGrab *drag_grab =
wl_container_of (listener, drag_grab, drag_icon_listener);
wl_container_of (listener, drag_grab, drag_data_source_listener);
drag_grab->drag_surface = NULL;
@@ -432,9 +442,6 @@ data_device_start_drag (struct wl_client *client,
drag_grab->drag_data_source_listener.notify = destroy_data_device_source;
wl_resource_add_destroy_listener (source_resource,
&drag_grab->drag_data_source_listener);
meta_wayland_data_device_set_dnd_source (data_device,
drag_grab->drag_data_source);
}
if (icon_resource)
@@ -482,48 +489,6 @@ destroy_selection_data_source (struct wl_listener *listener, void *data)
}
static void
meta_wayland_source_send (MetaWaylandDataSource *source,
const gchar *mime_type,
gint fd)
{
wl_data_source_send_send (source->resource, mime_type, fd);
close (fd);
}
static void
meta_wayland_source_target (MetaWaylandDataSource *source,
const gchar *mime_type)
{
wl_data_source_send_target (source->resource, mime_type);
}
static void
meta_wayland_source_cancel (MetaWaylandDataSource *source)
{
wl_data_source_send_cancelled (source->resource);
}
static const MetaWaylandDataSourceFuncs meta_wayland_source_funcs = {
meta_wayland_source_send,
meta_wayland_source_target,
meta_wayland_source_cancel
};
void
meta_wayland_data_device_set_dnd_source (MetaWaylandDataDevice *data_device,
MetaWaylandDataSource *source)
{
if (data_device->dnd_data_source == source)
return;
if (data_device->dnd_data_source)
meta_wayland_data_source_free (data_device->dnd_data_source);
data_device->dnd_data_source = source;
wl_signal_emit (&data_device->dnd_ownership_signal, source);
}
void
meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
MetaWaylandDataSource *source,
guint32 serial)
@@ -538,15 +503,8 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
if (data_device->selection_data_source)
{
data_device->selection_data_source->funcs.cancel (data_device->selection_data_source);
if (data_device->selection_data_source->resource)
{
wl_list_remove (&data_device->selection_data_source_listener.link);
data_device->selection_data_source->resource = NULL;
}
meta_wayland_data_source_free (data_device->selection_data_source);
wl_data_source_send_cancelled (data_device->selection_data_source->resource);
wl_list_remove (&data_device->selection_data_source_listener.link);
data_device->selection_data_source = NULL;
}
@@ -573,13 +531,8 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
if (source)
{
if (source->resource)
{
data_device->selection_data_source_listener.notify = destroy_selection_data_source;
wl_resource_add_destroy_listener (source->resource, &data_device->selection_data_source_listener);
}
wl_signal_emit (&data_device->selection_ownership_signal, source);
data_device->selection_data_source_listener.notify = destroy_selection_data_source;
wl_resource_add_destroy_listener (source->resource, &data_device->selection_data_source_listener);
}
}
@@ -617,23 +570,25 @@ static void
destroy_data_source (struct wl_resource *resource)
{
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
char **p;
source->resource = NULL;
wl_array_for_each (p, &source->mime_types) free (*p);
wl_array_release (&source->mime_types);
g_slice_free (MetaWaylandDataSource, source);
}
static void
create_data_source (struct wl_client *client,
struct wl_resource *resource, guint32 id)
{
MetaWaylandDataSource *source;
struct wl_resource *source_resource;
MetaWaylandDataSource *source = g_slice_new0 (MetaWaylandDataSource);
source_resource = wl_resource_create (client, &wl_data_source_interface,
wl_resource_get_version (resource), id);
source = meta_wayland_data_source_new (&meta_wayland_source_funcs,
source_resource, NULL);
wl_resource_set_implementation (source_resource, &data_source_interface,
source, destroy_data_source);
source->resource = wl_resource_create (client, &wl_data_source_interface, wl_resource_get_version (resource), id);
wl_resource_set_implementation (source->resource, &data_source_interface, source, destroy_data_source);
wl_array_init (&source->mime_types);
}
static void
@@ -677,8 +632,6 @@ void
meta_wayland_data_device_init (MetaWaylandDataDevice *data_device)
{
wl_list_init (&data_device->resource_list);
wl_signal_init (&data_device->selection_ownership_signal);
wl_signal_init (&data_device->dnd_ownership_signal);
}
void
@@ -730,75 +683,3 @@ meta_wayland_data_device_update_dnd_surface (MetaWaylandDataDevice *data_device)
-drag_grab->drag_surface->offset_x,
-drag_grab->drag_surface->offset_y);
}
void
meta_wayland_data_source_send (MetaWaylandDataSource *source,
const gchar *mime_type,
gint fd)
{
source->funcs.send (source, mime_type, fd);
}
gboolean
meta_wayland_data_source_has_mime_type (const MetaWaylandDataSource *source,
const gchar *mime_type)
{
gchar **p;
wl_array_for_each (p, &source->mime_types)
{
if (g_strcmp0 (mime_type, *p) == 0)
return TRUE;
}
return FALSE;
}
MetaWaylandDataSource *
meta_wayland_data_source_new (const MetaWaylandDataSourceFuncs *funcs,
struct wl_resource *wl_resource,
gpointer user_data)
{
MetaWaylandDataSource *source = g_slice_new0 (MetaWaylandDataSource);
source->funcs = *funcs;
source->resource = wl_resource;
source->user_data = user_data;
wl_array_init (&source->mime_types);
return source;
}
void
meta_wayland_data_source_free (MetaWaylandDataSource *source)
{
char **pos;
if (source->resource)
wl_resource_destroy (source->resource);
wl_array_for_each (pos, &source->mime_types)
{
g_free (*pos);
}
wl_array_release (&source->mime_types);
g_slice_free (MetaWaylandDataSource, source);
}
gboolean
meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source,
const gchar *mime_type)
{
gchar **pos;
pos = wl_array_add (&source->mime_types, sizeof (*pos));
if (pos)
{
*pos = g_strdup (mime_type);
return *pos != NULL;
}
return FALSE;
}

View File

@@ -28,38 +28,14 @@
#include "meta-wayland-types.h"
typedef struct _MetaWaylandDragGrab MetaWaylandDragGrab;
typedef struct _MetaWaylandDataSourceFuncs MetaWaylandDataSourceFuncs;
struct _MetaWaylandDataDevice
{
uint32_t selection_serial;
MetaWaylandDataSource *selection_data_source;
MetaWaylandDataSource *dnd_data_source;
struct wl_listener selection_data_source_listener;
struct wl_list resource_list;
MetaWaylandDragGrab *current_grab;
struct wl_signal selection_ownership_signal;
struct wl_signal dnd_ownership_signal;
};
struct _MetaWaylandDataSourceFuncs
{
void (* send) (MetaWaylandDataSource *source,
const gchar *mime_type,
gint fd);
void (* target) (MetaWaylandDataSource *source,
const gchar *mime_type);
void (* cancel) (MetaWaylandDataSource *source);
};
struct _MetaWaylandDataSource
{
MetaWaylandDataSourceFuncs funcs;
struct wl_resource *resource;
struct wl_array mime_types;
gpointer user_data;
gboolean has_target;
};
void meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor);
@@ -72,25 +48,4 @@ gboolean meta_wayland_data_device_is_dnd_surface (MetaWaylandDataDevice *data_de
MetaWaylandSurface *surface);
void meta_wayland_data_device_update_dnd_surface (MetaWaylandDataDevice *data_device);
void meta_wayland_data_device_set_dnd_source (MetaWaylandDataDevice *data_device,
MetaWaylandDataSource *source);
void meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
MetaWaylandDataSource *source,
guint32 serial);
MetaWaylandDataSource *
meta_wayland_data_source_new (const MetaWaylandDataSourceFuncs *funcs,
struct wl_resource *resource,
gpointer user_data);
void meta_wayland_data_source_free (MetaWaylandDataSource *source);
gboolean meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source,
const gchar *mime_type);
gboolean meta_wayland_data_source_has_mime_type (const MetaWaylandDataSource *source,
const gchar *mime_type);
void meta_wayland_data_source_send (MetaWaylandDataSource *source,
const gchar *mime_type,
gint fd);
#endif /* META_WAYLAND_DATA_DEVICE_H */

View File

@@ -33,8 +33,6 @@
#include "meta-wayland-surface.h"
#include "meta-wayland-seat.h"
typedef struct _MetaXWaylandSelection MetaXWaylandSelection;
typedef struct
{
struct wl_list link;
@@ -45,7 +43,7 @@ typedef struct
typedef struct
{
int display_index;
char *lock_file;
char *lockfile;
int abstract_fd;
int unix_fd;
pid_t pid;
@@ -54,8 +52,6 @@ typedef struct
char *display_name;
GMainLoop *init_loop;
MetaXWaylandSelection *selection_data;
} MetaXWaylandManager;
struct _MetaWaylandCompositor

View File

@@ -46,7 +46,7 @@
#include "meta-cursor-tracker-private.h"
#include "display-private.h"
#include "window-private.h"
#include "meta-window-wayland.h"
#include "window-wayland.h"
#include "compositor/region-utils.h"
@@ -215,52 +215,19 @@ calculate_surface_window_geometry (MetaWaylandSurface *surface,
}
}
static void
destroy_window (MetaWaylandSurface *surface)
{
if (surface->window)
{
MetaDisplay *display = meta_get_display ();
guint32 timestamp = meta_display_get_current_time_roundtrip (display);
meta_window_unmanage (surface->window, timestamp);
}
g_assert (surface->window == NULL);
}
static void
toplevel_surface_commit (MetaWaylandSurface *surface,
MetaWaylandPendingState *pending)
{
MetaWindow *window = surface->window;
if (surface->role == META_WAYLAND_SURFACE_ROLE_WL_SHELL_SURFACE)
/* Sanity check. */
if (surface->buffer == NULL)
{
/* For wl_shell, it's equivalent to an unmap. Semantics
* are poorly defined, so we can choose some that are
* convenient for us. */
if (surface->buffer && !window)
{
window = meta_window_wayland_new (meta_get_display (), surface);
meta_wayland_surface_set_window (surface, window);
}
else if (surface->buffer == NULL && window)
{
destroy_window (surface);
return;
}
}
else
{
if (surface->buffer == NULL)
{
/* XDG surfaces can't commit NULL buffers */
wl_resource_post_error (surface->resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"Cannot commit a NULL buffer to an xdg_surface");
return;
}
wl_resource_post_error (surface->resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"Cannot commit a NULL buffer to an xdg_surface");
return;
}
/* We resize X based surfaces according to X events */
@@ -756,6 +723,20 @@ meta_wayland_surface_set_window (MetaWaylandSurface *surface,
sync_reactive (surface);
}
static void
destroy_window (MetaWaylandSurface *surface)
{
if (surface->window)
{
MetaDisplay *display = meta_get_display ();
guint32 timestamp = meta_display_get_current_time_roundtrip (display);
meta_window_unmanage (surface->window, timestamp);
}
g_assert (surface->window == NULL);
}
static void
wl_surface_destructor (struct wl_resource *resource)
{
@@ -1525,6 +1506,7 @@ wl_shell_get_shell_surface (struct wl_client *client,
struct wl_resource *surface_resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWindow *window;
if (surface->wl_shell_surface != NULL)
{
@@ -1542,6 +1524,9 @@ wl_shell_get_shell_surface (struct wl_client *client,
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);
}
static const struct wl_shell_interface meta_wayland_wl_shell_interface = {
@@ -1569,14 +1554,14 @@ gtk_surface_destructor (struct wl_resource *resource)
}
static void
gtk_surface_set_dbus_properties (struct wl_client *client,
struct wl_resource *resource,
const char *application_id,
const char *app_menu_path,
const char *menubar_path,
const char *window_object_path,
const char *application_object_path,
const char *unique_bus_name)
set_dbus_properties (struct wl_client *client,
struct wl_resource *resource,
const char *application_id,
const char *app_menu_path,
const char *menubar_path,
const char *window_object_path,
const char *application_object_path,
const char *unique_bus_name)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
@@ -1596,36 +1581,8 @@ gtk_surface_set_dbus_properties (struct wl_client *client,
window_object_path);
}
static void
gtk_surface_set_modal (struct wl_client *client,
struct wl_resource *resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
if (surface->is_modal)
return;
surface->is_modal = TRUE;
meta_window_set_type (surface->window, META_WINDOW_MODAL_DIALOG);
}
static void
gtk_surface_unset_modal (struct wl_client *client,
struct wl_resource *resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
if (!surface->is_modal)
return;
surface->is_modal = FALSE;
meta_window_set_type (surface->window, META_WINDOW_NORMAL);
}
static const struct gtk_surface_interface meta_wayland_gtk_surface_interface = {
gtk_surface_set_dbus_properties,
gtk_surface_set_modal,
gtk_surface_unset_modal,
set_dbus_properties
};
static void
@@ -1662,17 +1619,6 @@ bind_gtk_shell (struct wl_client *client,
uint32_t capabilities = 0;
resource = wl_resource_create (client, &gtk_shell_interface, version, id);
if (version != META_GTK_SHELL_VERSION)
{
wl_resource_post_error (resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"Incompatible gtk-shell version "
"(supported version: %d)",
META_GTK_SHELL_VERSION);
return;
}
wl_resource_set_implementation (resource, &meta_wayland_gtk_shell_interface, data, NULL);
if (!meta_prefs_get_show_fallback_app_menu ())

View File

@@ -101,7 +101,6 @@ struct _MetaWaylandSurface
struct wl_resource *xdg_shell_resource;
MetaWaylandSerial acked_configure_serial;
gboolean has_set_geometry;
gboolean is_modal;
/* xdg_popup */
struct {

View File

@@ -42,7 +42,7 @@
#define META_WL_SEAT_VERSION 4
#define META_WL_OUTPUT_VERSION 2
#define META_XSERVER_VERSION 1
#define META_GTK_SHELL_VERSION 2
#define META_GTK_SHELL_VERSION 1
#define META_WL_SUBCOMPOSITOR_VERSION 1
#endif

View File

@@ -34,9 +34,4 @@ meta_xwayland_complete_init (void);
void
meta_xwayland_stop (MetaXWaylandManager *manager);
/* wl_data_device/X11 selection interoperation */
void meta_xwayland_init_selection (void);
void meta_xwayland_shutdown_selection (void);
gboolean meta_xwayland_selection_handle_event (XEvent *xevent);
#endif /* META_XWAYLAND_PRIVATE_H */

View File

@@ -1,943 +0,0 @@
/*
* Copyright © 2012 Intel Corporation
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of the copyright holders not be used in
* advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The copyright holders make
* no representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* The file is loosely based on xwayland/selection.c from Weston */
#include "config.h"
#define _GNU_SOURCE
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <glib-unix.h>
#include <gio/gunixoutputstream.h>
#include <gio/gunixinputstream.h>
#include <gdk/gdkx.h>
#include <X11/Xatom.h>
#include <meta/errors.h>
#include "meta-xwayland-private.h"
#include "meta-wayland-data-device.h"
#define INCR_CHUNK_SIZE (128 * 1024)
typedef struct {
MetaXWaylandSelection *selection_data;
GInputStream *stream;
GCancellable *cancellable;
MetaWindow *window;
XSelectionRequestEvent request_event;
guchar buffer[INCR_CHUNK_SIZE];
gsize buffer_len;
guint incr : 1;
} WaylandSelectionData;
typedef struct {
MetaXWaylandSelection *selection_data;
GOutputStream *stream;
GCancellable *cancellable;
gchar *mime_type;
guint incr : 1;
} X11SelectionData;
typedef struct {
Atom selection_atom;
Window window;
Window owner;
Time timestamp;
const MetaWaylandDataSource *source;
WaylandSelectionData *wayland_selection;
X11SelectionData *x11_selection;
struct wl_listener ownership_listener;
} MetaSelectionBridge;
struct _MetaXWaylandSelection {
MetaSelectionBridge clipboard;
};
static MetaSelectionBridge *
atom_to_selection_bridge (MetaWaylandCompositor *compositor,
Atom selection_atom)
{
MetaXWaylandSelection *selection_data = compositor->xwayland_manager.selection_data;
if (selection_atom == selection_data->clipboard.selection_atom)
return &selection_data->clipboard;
else
return NULL;
}
static X11SelectionData *
x11_selection_data_new (MetaXWaylandSelection *selection_data,
int fd,
const char *mime_type)
{
X11SelectionData *data;
data = g_slice_new0 (X11SelectionData);
data->selection_data = selection_data;
data->stream = g_unix_output_stream_new (fd, TRUE);
data->cancellable = g_cancellable_new ();
data->mime_type = g_strdup (mime_type);
return data;
}
static void
x11_selection_data_free (X11SelectionData *data)
{
g_cancellable_cancel (data->cancellable);
g_object_unref (data->cancellable);
g_object_unref (data->stream);
g_free (data->mime_type);
g_slice_free (X11SelectionData, data);
}
static void
x11_data_write_cb (GObject *object,
GAsyncResult *res,
gpointer user_data)
{
MetaSelectionBridge *selection = user_data;
X11SelectionData *data = selection->x11_selection;
GError *error = NULL;
g_output_stream_write_finish (G_OUTPUT_STREAM (object), res, &error);
if (data->incr)
{
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
XDeleteProperty (xdisplay, selection->window,
gdk_x11_get_xatom_by_name ("_META_SELECTION"));
}
if (error)
{
if (error->domain != G_IO_ERROR ||
error->code != G_IO_ERROR_CANCELLED)
g_warning ("Error writing from X11 selection: %s\n", error->message);
g_error_free (error);
}
if (!data->incr)
{
g_clear_pointer (&selection->x11_selection,
(GDestroyNotify) x11_selection_data_free);
}
}
static void
x11_selection_data_write (MetaSelectionBridge *selection,
guchar *buffer,
gulong len)
{
X11SelectionData *data = selection->x11_selection;
g_output_stream_write_async (data->stream, buffer, len,
G_PRIORITY_DEFAULT, data->cancellable,
x11_data_write_cb, selection);
}
static MetaWaylandDataSource *
data_device_get_active_source_for_atom (MetaWaylandDataDevice *data_device,
Atom selection_atom)
{
if (selection_atom == gdk_x11_get_xatom_by_name ("CLIPBOARD"))
return data_device->selection_data_source;
else
return NULL;
}
static WaylandSelectionData *
wayland_selection_data_new (XSelectionRequestEvent *request_event,
MetaWaylandCompositor *compositor)
{
MetaWaylandDataDevice *data_device;
MetaWaylandDataSource *wayland_source;
MetaSelectionBridge *selection;
WaylandSelectionData *data;
const gchar *mime_type;
GError *error = NULL;
int p[2];
selection = atom_to_selection_bridge (compositor, request_event->selection);
if (!selection)
return NULL;
if (!g_unix_open_pipe (p, FD_CLOEXEC, &error))
{
g_critical ("Failed to open pipe: %s\n", error->message);
g_error_free (error);
return NULL;
}
data_device = &compositor->seat->data_device;
mime_type = gdk_x11_get_xatom_name (request_event->target);
if (!g_unix_set_fd_nonblocking (p[0], TRUE, &error) ||
!g_unix_set_fd_nonblocking (p[1], TRUE, &error))
{
if (error)
{
g_critical ("Failed to make fds non-blocking: %s\n", error->message);
g_error_free (error);
}
close (p[0]);
close (p[1]);
return NULL;
}
wayland_source = data_device_get_active_source_for_atom (data_device,
selection->selection_atom),
meta_wayland_data_source_send (wayland_source, mime_type, p[1]);
data = g_slice_new0 (WaylandSelectionData);
data->request_event = *request_event;
data->cancellable = g_cancellable_new ();
data->stream = g_unix_input_stream_new (p[0], TRUE);
data->window = meta_display_lookup_x_window (meta_get_display (),
data->request_event.requestor);
if (!data->window)
{
/* Not a managed window, set the PropertyChangeMask
* for INCR deletion notifications.
*/
XSelectInput (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
data->request_event.requestor, PropertyChangeMask);
}
return data;
}
static void
reply_selection_request (XSelectionRequestEvent *request_event,
gboolean accepted)
{
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
XSelectionEvent event;
memset(&event, 0, sizeof (XSelectionEvent));
event.type = SelectionNotify;
event.time = request_event->time;
event.requestor = request_event->requestor;
event.selection = request_event->selection;
event.target = request_event->target;
event.property = accepted ? request_event->property : None;
XSendEvent (xdisplay, request_event->requestor,
False, NoEventMask, (XEvent *) &event);
}
static void
wayland_selection_data_free (WaylandSelectionData *data)
{
if (!data->window)
{
MetaDisplay *display = meta_get_display ();
meta_error_trap_push (display);
XSelectInput (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
data->request_event.requestor, NoEventMask);
meta_error_trap_pop (display);
}
g_cancellable_cancel (data->cancellable);
g_object_unref (data->cancellable);
g_object_unref (data->stream);
g_slice_free (WaylandSelectionData, data);
}
static void
wayland_selection_update_x11_property (WaylandSelectionData *data)
{
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
XChangeProperty (xdisplay,
data->request_event.requestor,
data->request_event.property,
data->request_event.target,
8, PropModeReplace,
data->buffer, data->buffer_len);
data->buffer_len = 0;
}
static void
wayland_data_read_cb (GObject *object,
GAsyncResult *res,
gpointer user_data)
{
MetaSelectionBridge *selection = user_data;
WaylandSelectionData *data = selection->wayland_selection;
GError *error = NULL;
gsize bytes_read;
bytes_read = g_input_stream_read_finish (G_INPUT_STREAM (object),
res, &error);
if (error)
{
g_warning ("Error transfering wayland clipboard to X11: %s\n",
error->message);
g_error_free (error);
if (data)
{
reply_selection_request (&data->request_event, FALSE);
g_clear_pointer (&selection->wayland_selection,
(GDestroyNotify) wayland_selection_data_free);
}
return;
}
data->buffer_len = bytes_read;
if (bytes_read == INCR_CHUNK_SIZE)
{
if (!data->incr)
{
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
guint32 incr_chunk_size = INCR_CHUNK_SIZE;
/* Not yet in incr */
data->incr = TRUE;
XChangeProperty (xdisplay,
data->request_event.requestor,
data->request_event.property,
gdk_x11_get_xatom_by_name ("INCR"),
32, PropModeReplace,
(guchar *) &incr_chunk_size, 1);
reply_selection_request (&data->request_event, TRUE);
}
else
wayland_selection_update_x11_property (data);
}
else
{
if (!data->incr)
{
/* Non-incr transfer finished */
wayland_selection_update_x11_property (data);
reply_selection_request (&data->request_event, TRUE);
}
else if (data->incr)
{
/* Incr transfer complete, setting a new property */
wayland_selection_update_x11_property (data);
if (bytes_read > 0)
return;
}
g_clear_pointer (&selection->wayland_selection,
(GDestroyNotify) wayland_selection_data_free);
}
}
static void
wayland_selection_data_read (MetaSelectionBridge *selection)
{
WaylandSelectionData *data = selection->wayland_selection;
g_input_stream_read_async (data->stream, data->buffer,
INCR_CHUNK_SIZE, G_PRIORITY_DEFAULT,
data->cancellable,
wayland_data_read_cb, selection);
}
static void
meta_xwayland_selection_get_incr_chunk (MetaWaylandCompositor *compositor,
MetaSelectionBridge *selection)
{
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
gulong nitems_ret, bytes_after_ret;
guchar *prop_ret;
int format_ret;
Atom type_ret;
XGetWindowProperty (xdisplay,
selection->window,
gdk_x11_get_xatom_by_name ("_META_SELECTION"),
0, /* offset */
0x1fffffff, /* length */
False, /* delete */
AnyPropertyType,
&type_ret,
&format_ret,
&nitems_ret,
&bytes_after_ret,
&prop_ret);
if (nitems_ret > 0)
{
x11_selection_data_write (selection, prop_ret, nitems_ret);
}
else
{
/* Transfer has completed */
g_clear_pointer (&selection->x11_selection,
(GDestroyNotify) x11_selection_data_free);
}
XFree (prop_ret);
}
static void
meta_x11_source_send (MetaWaylandDataSource *source,
const gchar *mime_type,
gint fd)
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
MetaSelectionBridge *selection = source->user_data;
Atom type_atom;
if (strcmp (mime_type, "text/plain;charset=utf-8") == 0)
type_atom = gdk_x11_get_xatom_by_name ("UTF8_STRING");
else
type_atom = gdk_x11_get_xatom_by_name (mime_type);
g_clear_pointer (&selection->x11_selection,
(GDestroyNotify) x11_selection_data_free);
/* Takes ownership of fd */
selection->x11_selection =
x11_selection_data_new (compositor->xwayland_manager.selection_data,
fd, mime_type);
XConvertSelection (xdisplay,
selection->selection_atom, type_atom,
gdk_x11_get_xatom_by_name ("_META_SELECTION"),
selection->window,
CurrentTime);
XFlush (xdisplay);
}
static void
meta_x11_source_target (MetaWaylandDataSource *source,
const gchar *mime_type)
{
}
static void
meta_x11_source_cancel (MetaWaylandDataSource *source)
{
MetaSelectionBridge *selection = source->user_data;
g_clear_pointer (&selection->x11_selection,
(GDestroyNotify) x11_selection_data_free);
}
static const MetaWaylandDataSourceFuncs meta_x11_source_funcs = {
meta_x11_source_send,
meta_x11_source_target,
meta_x11_source_cancel
};
static gboolean
meta_xwayland_data_source_fetch_mimetype_list (MetaWaylandDataSource *source,
Window window,
Atom prop)
{
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
gulong nitems_ret, bytes_after_ret, i;
Atom *atoms, type_ret, utf8_string;
int format_ret;
utf8_string = gdk_x11_get_xatom_by_name ("UTF8_STRING");
XGetWindowProperty (xdisplay, window, prop,
0, /* offset */
0x1fffffff, /* length */
True, /* delete */
AnyPropertyType,
&type_ret,
&format_ret,
&nitems_ret,
&bytes_after_ret,
(guchar **) &atoms);
if (nitems_ret == 0 || type_ret != XA_ATOM)
{
XFree (atoms);
return FALSE;
}
for (i = 0; i < nitems_ret; i++)
{
const gchar *mime_type;
if (atoms[i] == utf8_string)
mime_type = "text/plain;charset=utf-8";
else
mime_type = gdk_x11_get_xatom_name (atoms[i]);
meta_wayland_data_source_add_mime_type (source, mime_type);
}
XFree (atoms);
return TRUE;
}
static void
meta_xwayland_selection_get_x11_targets (MetaWaylandCompositor *compositor,
MetaSelectionBridge *selection)
{
MetaWaylandDataSource *data_source;
data_source = meta_wayland_data_source_new (&meta_x11_source_funcs,
NULL, selection);
if (meta_xwayland_data_source_fetch_mimetype_list (data_source,
selection->window,
gdk_x11_get_xatom_by_name ("_META_SELECTION")))
{
selection->source = data_source;
if (selection->selection_atom == gdk_x11_get_xatom_by_name ("CLIPBOARD"))
{
meta_wayland_data_device_set_selection (&compositor->seat->data_device, data_source,
wl_display_next_serial (compositor->wayland_display));
}
}
else
{
meta_wayland_data_source_free (data_source);
}
}
static void
meta_xwayland_selection_get_x11_data (MetaWaylandCompositor *compositor,
MetaSelectionBridge *selection)
{
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
gulong nitems_ret, bytes_after_ret;
guchar *prop_ret;
int format_ret;
Atom type_ret;
if (!selection->x11_selection)
return;
XGetWindowProperty (xdisplay,
selection->window,
gdk_x11_get_xatom_by_name ("_META_SELECTION"),
0, /* offset */
0x1fffffff, /* length */
True, /* delete */
AnyPropertyType,
&type_ret,
&format_ret,
&nitems_ret,
&bytes_after_ret,
&prop_ret);
selection->x11_selection->incr = (type_ret == gdk_x11_get_xatom_by_name ("INCR"));
if (selection->x11_selection->incr)
return;
if (type_ret == gdk_x11_get_xatom_by_name (selection->x11_selection->mime_type))
x11_selection_data_write (selection, prop_ret, nitems_ret);
XFree (prop_ret);
}
static gboolean
meta_xwayland_selection_handle_selection_notify (MetaWaylandCompositor *compositor,
XEvent *xevent)
{
XSelectionEvent *event = (XSelectionEvent *) xevent;
MetaSelectionBridge *selection;
selection = atom_to_selection_bridge (compositor, event->selection);
if (!selection)
return FALSE;
/* convert selection failed */
if (event->property == None)
{
g_clear_pointer (&selection->x11_selection,
(GDestroyNotify) x11_selection_data_free);
return FALSE;
}
if (event->target == gdk_x11_get_xatom_by_name ("TARGETS"))
meta_xwayland_selection_get_x11_targets (compositor, selection);
else
meta_xwayland_selection_get_x11_data (compositor, selection);
return TRUE;
}
static void
meta_xwayland_selection_send_targets (MetaWaylandCompositor *compositor,
const MetaWaylandDataSource *data_source,
Window requestor,
Atom property)
{
Atom *targets;
gchar **p;
int i = 0;
if (!data_source)
return;
if (data_source->mime_types.size == 0)
return;
/* Make extra room for TIMESTAMP/TARGETS */
targets = g_new (Atom, data_source->mime_types.size + 2);
wl_array_for_each (p, &data_source->mime_types)
{
targets[i++] = gdk_x11_get_xatom_by_name (*p);
}
targets[i++] = gdk_x11_get_xatom_by_name ("TIMESTAMP");
targets[i++] = gdk_x11_get_xatom_by_name ("TARGETS");
XChangeProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
requestor, property,
XA_ATOM, 32, PropModeReplace,
(guchar *) targets, i);
g_free (targets);
}
static void
meta_xwayland_selection_send_timestamp (MetaWaylandCompositor *compositor,
Window requestor,
Atom property,
Time timestamp)
{
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
XChangeProperty (xdisplay, requestor, property,
XA_INTEGER, 32,
PropModeReplace,
(guchar *) &timestamp, 1);
}
static void
meta_xwayland_selection_send_incr_chunk (MetaWaylandCompositor *compositor,
MetaSelectionBridge *selection)
{
if (!selection->wayland_selection)
return;
if (selection->wayland_selection->buffer_len > 0)
wayland_selection_update_x11_property (selection->wayland_selection);
else
wayland_selection_data_read (selection);
}
static gboolean
handle_incr_chunk (MetaWaylandCompositor *compositor,
MetaSelectionBridge *selection,
XPropertyEvent *event)
{
if (selection->x11_selection &&
selection->x11_selection->incr &&
event->window == selection->owner &&
event->state == PropertyNewValue &&
event->atom == gdk_x11_get_xatom_by_name ("_META_SELECTION"))
{
/* X11 to Wayland */
meta_xwayland_selection_get_incr_chunk (compositor, selection);
return TRUE;
}
else if (selection->wayland_selection &&
selection->wayland_selection->incr &&
event->window == selection->window &&
event->state == PropertyDelete &&
event->atom == selection->wayland_selection->request_event.property)
{
/* Wayland to X11 */
meta_xwayland_selection_send_incr_chunk (compositor, selection);
return TRUE;
}
return FALSE;
}
static gboolean
meta_xwayland_selection_handle_property_notify (MetaWaylandCompositor *compositor,
XEvent *xevent)
{
MetaXWaylandSelection *selection_data = compositor->xwayland_manager.selection_data;
XPropertyEvent *event = (XPropertyEvent *) xevent;
return handle_incr_chunk (compositor, &selection_data->clipboard, event);
}
static gboolean
meta_xwayland_selection_handle_selection_request (MetaWaylandCompositor *compositor,
XEvent *xevent)
{
XSelectionRequestEvent *event = (XSelectionRequestEvent *) xevent;
MetaWaylandDataSource *data_source;
MetaSelectionBridge *selection;
selection = atom_to_selection_bridge (compositor, event->selection);
if (!selection)
return FALSE;
/* We must fetch from the currently active source, not the Xwayland one */
data_source = data_device_get_active_source_for_atom (&compositor->seat->data_device,
selection->selection_atom);
if (!data_source)
return FALSE;
g_clear_pointer (&selection->wayland_selection,
(GDestroyNotify) wayland_selection_data_free);
if (event->target == gdk_x11_get_xatom_by_name ("TARGETS"))
{
meta_xwayland_selection_send_targets (compositor,
data_source,
event->requestor,
event->property);
reply_selection_request (event, TRUE);
}
else if (event->target == gdk_x11_get_xatom_by_name ("TIMESTAMP"))
{
meta_xwayland_selection_send_timestamp (compositor,
event->requestor, event->property,
selection->timestamp);
reply_selection_request (event, TRUE);
}
else
{
if (data_source &&
meta_wayland_data_source_has_mime_type (data_source,
gdk_x11_get_xatom_name (event->target)))
{
selection->wayland_selection = wayland_selection_data_new (event,
compositor);
if (selection->wayland_selection)
wayland_selection_data_read (selection);
}
if (!selection->wayland_selection)
reply_selection_request (event, FALSE);
}
return TRUE;
}
static gboolean
meta_xwayland_selection_handle_xfixes_selection_notify (MetaWaylandCompositor *compositor,
XEvent *xevent)
{
XFixesSelectionNotifyEvent *event = (XFixesSelectionNotifyEvent *) xevent;
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
MetaSelectionBridge *selection;
selection = atom_to_selection_bridge (compositor, event->selection);
if (!selection)
return FALSE;
if (event->owner == None)
{
if (selection->source && selection->owner != selection->window)
{
/* An X client went away, clear the selection */
if (selection->selection_atom == gdk_x11_get_xatom_by_name ("CLIPBOARD"))
{
meta_wayland_data_device_set_selection (&compositor->seat->data_device, NULL,
wl_display_next_serial (compositor->wayland_display));
}
selection->source = NULL;
}
selection->owner = None;
}
else
{
selection->owner = event->owner;
if (selection->owner == selection->window)
{
/* This our own selection window */
selection->timestamp = event->timestamp;
return TRUE;
}
g_clear_pointer (&selection->x11_selection,
(GDestroyNotify) x11_selection_data_free);
XConvertSelection (xdisplay,
event->selection,
gdk_x11_get_xatom_by_name ("TARGETS"),
gdk_x11_get_xatom_by_name ("_META_SELECTION"),
selection->window,
selection->timestamp);
XFlush (xdisplay);
}
return TRUE;
}
gboolean
meta_xwayland_selection_handle_event (XEvent *xevent)
{
MetaWaylandCompositor *compositor;
compositor = meta_wayland_compositor_get_default ();
if (!compositor->xwayland_manager.selection_data)
return FALSE;
switch (xevent->type)
{
case SelectionNotify:
return meta_xwayland_selection_handle_selection_notify (compositor, xevent);
case PropertyNotify:
return meta_xwayland_selection_handle_property_notify (compositor, xevent);
case SelectionRequest:
return meta_xwayland_selection_handle_selection_request (compositor, xevent);
default:
{
MetaDisplay *display = meta_get_display ();
if (xevent->type - display->xfixes_event_base == XFixesSelectionNotify)
return meta_xwayland_selection_handle_xfixes_selection_notify (compositor, xevent);
return FALSE;
}
}
}
static void
meta_selection_bridge_ownership_notify (struct wl_listener *listener,
void *data)
{
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
MetaSelectionBridge *selection =
wl_container_of (listener, selection, ownership_listener);
MetaWaylandDataSource *owner = data;
if (!owner && selection->window == selection->owner)
{
XSetSelectionOwner (xdisplay, selection->selection_atom,
None, selection->timestamp);
}
else if (owner && selection->source != owner)
{
XSetSelectionOwner (xdisplay,
selection->selection_atom,
selection->window,
CurrentTime);
}
}
static void
init_selection_bridge (MetaSelectionBridge *selection,
Atom selection_atom,
struct wl_signal *signal)
{
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
XSetWindowAttributes attributes;
guint mask;
attributes.event_mask = PropertyChangeMask;
selection->ownership_listener.notify = meta_selection_bridge_ownership_notify;
wl_signal_add (signal, &selection->ownership_listener);
selection->selection_atom = selection_atom;
selection->window =
XCreateWindow (xdisplay,
gdk_x11_window_get_xid (gdk_get_default_root_window ()),
-1, -1, 1, 1, /* position */
0, /* border width */
0, /* depth */
InputOnly, /* class */
CopyFromParent, /* visual */
CWEventMask,
&attributes);
mask = XFixesSetSelectionOwnerNotifyMask |
XFixesSelectionWindowDestroyNotifyMask |
XFixesSelectionClientCloseNotifyMask;
XFixesSelectSelectionInput (xdisplay, selection->window,
selection_atom, mask);
}
static void
shutdown_selection_bridge (MetaSelectionBridge *selection)
{
wl_list_remove (&selection->ownership_listener.link);
XDestroyWindow (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
selection->window);
g_clear_pointer (&selection->wayland_selection,
(GDestroyNotify) wayland_selection_data_free);
g_clear_pointer (&selection->x11_selection,
(GDestroyNotify) x11_selection_data_free);
}
void
meta_xwayland_init_selection (void)
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaXWaylandManager *manager = &compositor->xwayland_manager;
g_assert (manager->selection_data == NULL);
manager->selection_data = g_slice_new0 (MetaXWaylandSelection);
init_selection_bridge (&manager->selection_data->clipboard,
gdk_x11_get_xatom_by_name ("CLIPBOARD"),
&compositor->seat->data_device.selection_ownership_signal);
}
void
meta_xwayland_shutdown_selection (void)
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaXWaylandManager *manager = &compositor->xwayland_manager;
MetaXWaylandSelection *selection = manager->selection_data;
g_assert (selection != NULL);
if (selection->clipboard.source)
{
meta_wayland_data_device_set_selection (&compositor->seat->data_device, NULL,
wl_display_next_serial (compositor->wayland_display));
}
shutdown_selection_bridge (&selection->clipboard);
g_slice_free (MetaXWaylandSelection, selection);
manager->selection_data = NULL;
}

View File

@@ -182,7 +182,7 @@ try_display (int display,
if (kill (other, 0) < 0 && errno == ESRCH)
{
/* Process is dead. Try unlinking the lock file and trying again. */
/* Process is dead. Try unlinking the lockfile and trying again. */
if (unlink (filename) < 0)
{
g_warning ("failed to unlink stale lock file %s: %m", filename);
@@ -221,7 +221,7 @@ try_display (int display,
}
static char *
create_lock_file (int display, int *display_out)
create_lockfile (int display, int *display_out)
{
char *filename;
int fd;
@@ -354,7 +354,7 @@ static gboolean
choose_xdisplay (MetaXWaylandManager *manager)
{
int display = 0;
char *lock_file = NULL;
char *lockfile = NULL;
/* Hack to keep the unused Xwayland instance on
* the login screen from taking the prime :0 display
@@ -365,8 +365,8 @@ choose_xdisplay (MetaXWaylandManager *manager)
do
{
lock_file = create_lock_file (display, &display);
if (!lock_file)
lockfile = create_lockfile (display, &display);
if (!lockfile)
{
g_warning ("Failed to create an X lock file");
return FALSE;
@@ -375,7 +375,7 @@ choose_xdisplay (MetaXWaylandManager *manager)
manager->abstract_fd = bind_to_abstract_socket (display);
if (manager->abstract_fd < 0)
{
unlink (lock_file);
unlink (lockfile);
if (errno == EADDRINUSE)
{
@@ -389,7 +389,7 @@ choose_xdisplay (MetaXWaylandManager *manager)
manager->unix_fd = bind_to_unix_socket (display);
if (manager->abstract_fd < 0)
{
unlink (lock_file);
unlink (lockfile);
close (manager->abstract_fd);
return FALSE;
}
@@ -400,7 +400,7 @@ choose_xdisplay (MetaXWaylandManager *manager)
manager->display_index = display;
manager->display_name = g_strdup_printf (":%d", manager->display_index);
manager->lock_file = lock_file;
manager->lockfile = lockfile;
return TRUE;
}
@@ -438,27 +438,28 @@ meta_xwayland_start (MetaXWaylandManager *manager,
{
int xwayland_client_fd[2];
int displayfd[2];
gboolean started = FALSE;
g_autoptr(GSubprocessLauncher) launcher = NULL;
GSubprocessFlags flags;
GSubprocess *proc;
GError *error = NULL;
if (!choose_xdisplay (manager))
goto out;
return FALSE;
/* We want xwayland to be a wayland client so we make a socketpair to setup a
* wayland protocol connection. */
if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, xwayland_client_fd) < 0)
{
g_warning ("xwayland_client_fd socketpair failed\n");
goto out;
unlink (manager->lockfile);
return FALSE;
}
if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, displayfd) < 0)
{
g_warning ("displayfd socketpair failed\n");
goto out;
unlink (manager->lockfile);
return FALSE;
}
/* xwayland, please. */
@@ -488,7 +489,7 @@ meta_xwayland_start (MetaXWaylandManager *manager,
if (!proc)
{
g_error ("Failed to spawn Xwayland: %s", error->message);
goto out;
return FALSE;
}
g_subprocess_wait_async (proc, NULL, xserver_died, NULL);
@@ -501,15 +502,7 @@ meta_xwayland_start (MetaXWaylandManager *manager,
manager->init_loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (manager->init_loop);
started = TRUE;
out:
if (!started)
{
unlink (manager->lock_file);
g_clear_pointer (&manager->lock_file, g_free);
}
return started;
return TRUE;
}
/* To be called right after connecting */
@@ -522,8 +515,6 @@ meta_xwayland_complete_init (void)
we won't reset the tty).
*/
XSetIOErrorHandler (x_io_error);
meta_xwayland_init_selection ();
}
void
@@ -531,15 +522,10 @@ meta_xwayland_stop (MetaXWaylandManager *manager)
{
char path[256];
meta_xwayland_shutdown_selection ();
snprintf (path, sizeof path, "/tmp/.X%d-lock", manager->display_index);
unlink (path);
snprintf (path, sizeof path, "/tmp/.X11-unix/X%d", manager->display_index);
unlink (path);
g_clear_pointer (&manager->display_name, g_free);
if (manager->lock_file)
{
unlink (manager->lock_file);
g_clear_pointer (&manager->lock_file, g_free);
}
unlink (manager->lockfile);
}

View File

@@ -1,18 +1,9 @@
<protocol name="gtk">
<interface name="gtk_shell" version="2">
<description summary="gtk specific extensions">
gtk_shell is a protocol extension providing additional features for
clients implementing it. It is not backward compatible, and a client must
always only bind to the specific version it implements. If a client binds
to a version different from the version the server provides, an error will
be raised.
</description>
<interface name="gtk_shell" version="1">
<enum name="capability">
<entry name="global_app_menu" value="1"/>
<entry name="global_menu_bar" value="2"/>
<entry name="desktop_icons" value="3"/>
</enum>
<event name="capabilities">
@@ -25,7 +16,7 @@
</request>
</interface>
<interface name="gtk_surface" version="2">
<interface name="gtk_surface" version="1">
<request name="set_dbus_properties">
<arg name="application_id" type="string" allow-null="true"/>
<arg name="app_menu_path" type="string" allow-null="true"/>
@@ -34,9 +25,6 @@
<arg name="application_object_path" type="string" allow-null="true"/>
<arg name="unique_bus_name" type="string" allow-null="true"/>
</request>
<request name="set_modal"/>
<request name="unset_modal"/>
</interface>
</protocol>

View File

@@ -24,7 +24,7 @@
#include "config.h"
#include "meta-window-wayland.h"
#include "window-wayland.h"
#include <meta/errors.h>
#include "window-private.h"

View File

@@ -39,7 +39,6 @@
#ifdef HAVE_WAYLAND
#include "wayland/meta-xwayland.h"
#include "wayland/meta-wayland-private.h"
#include "wayland/meta-xwayland-private.h"
#endif
static XIEvent *
@@ -1677,15 +1676,6 @@ meta_display_handle_xevent (MetaDisplay *display,
}
#endif
#ifdef HAVE_WAYLAND
if (meta_is_wayland_compositor () &&
meta_xwayland_selection_handle_event (event))
{
bypass_gtk = bypass_compositor = TRUE;
goto out;
}
#endif
display->current_time = event_get_time (display, event);
display->monitor_cache_invalidated = TRUE;