Compare commits
36 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
8d51a9db5b | ||
![]() |
b39c00f344 | ||
![]() |
83ce71c3bf | ||
![]() |
f9d869a3dd | ||
![]() |
0b0ce4193f | ||
![]() |
719d8bd0c7 | ||
![]() |
4fc1811c15 | ||
![]() |
4b5f5abb4f | ||
![]() |
95ad52ba58 | ||
![]() |
dac30a222e | ||
![]() |
7d1b593fbd | ||
![]() |
d6a7559750 | ||
![]() |
cff5ef0ec2 | ||
![]() |
d478d8f143 | ||
![]() |
7eca43cec9 | ||
![]() |
9060190555 | ||
![]() |
0de3869656 | ||
![]() |
9f13033f15 | ||
![]() |
48bf807430 | ||
![]() |
c68e43a97f | ||
![]() |
cc53d48fa8 | ||
![]() |
ca6e799b97 | ||
![]() |
0f8e387dc0 | ||
![]() |
d62c595e51 | ||
![]() |
dd3cf94744 | ||
![]() |
eb56e0a3d7 | ||
![]() |
8937c32cd5 | ||
![]() |
a8a5da768a | ||
![]() |
33bfcf56ce | ||
![]() |
40cccb58a5 | ||
![]() |
eb6c70137b | ||
![]() |
df3b412a25 | ||
![]() |
cfba0a5dfc | ||
![]() |
3561b46fc6 | ||
![]() |
8dfb88b669 | ||
![]() |
2e3086e2aa |
22
NEWS
22
NEWS
@@ -1,3 +1,25 @@
|
||||
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]
|
||||
|
||||
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
|
||||
|
||||
3.16.1
|
||||
======
|
||||
* Add function to refresh all background instances [Rui; #739178]
|
||||
|
@@ -1,8 +1,8 @@
|
||||
AC_PREREQ(2.62)
|
||||
|
||||
m4_define([mutter_major_version], [3])
|
||||
m4_define([mutter_minor_version], [16])
|
||||
m4_define([mutter_micro_version], [1])
|
||||
m4_define([mutter_minor_version], [17])
|
||||
m4_define([mutter_micro_version], [2])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
|
@@ -210,10 +210,9 @@ 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 \
|
||||
@@ -221,6 +220,8 @@ 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 \
|
||||
@@ -242,6 +243,7 @@ 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 \
|
||||
@@ -265,8 +267,8 @@ libmutter_la_SOURCES += \
|
||||
wayland/meta-wayland-versions.h \
|
||||
wayland/meta-wayland-outputs.c \
|
||||
wayland/meta-wayland-outputs.h \
|
||||
wayland/window-wayland.c \
|
||||
wayland/window-wayland.h \
|
||||
wayland/meta-window-wayland.c \
|
||||
wayland/meta-window-wayland.h \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
@@ -338,16 +340,10 @@ 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_extra_headers)
|
||||
$(libmutterinclude_headers)
|
||||
|
||||
nodist_libmutterinclude_HEADERS = \
|
||||
$(libmutterinclude_built_headers)
|
||||
|
@@ -209,6 +209,10 @@ update_touchpad_left_handed (MetaInputSettings *input_settings,
|
||||
MetaInputSettingsPrivate *priv;
|
||||
gboolean enabled = FALSE;
|
||||
|
||||
if (device &&
|
||||
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
|
||||
return;
|
||||
|
||||
priv = meta_input_settings_get_instance_private (input_settings);
|
||||
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
||||
handedness = g_settings_get_enum (priv->touchpad_settings, "left-handed");
|
||||
@@ -230,7 +234,6 @@ update_touchpad_left_handed (MetaInputSettings *input_settings,
|
||||
|
||||
if (device)
|
||||
{
|
||||
g_assert (clutter_input_device_get_device_type (device) == CLUTTER_TOUCHPAD_DEVICE);
|
||||
settings_device_set_bool_setting (input_settings, device,
|
||||
input_settings_class->set_left_handed,
|
||||
enabled);
|
||||
@@ -251,13 +254,16 @@ update_mouse_left_handed (MetaInputSettings *input_settings,
|
||||
MetaInputSettingsPrivate *priv;
|
||||
gboolean enabled;
|
||||
|
||||
if (device &&
|
||||
clutter_input_device_get_device_type (device) != CLUTTER_POINTER_DEVICE)
|
||||
return;
|
||||
|
||||
priv = meta_input_settings_get_instance_private (input_settings);
|
||||
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
||||
enabled = g_settings_get_boolean (priv->mouse_settings, "left-handed");
|
||||
|
||||
if (device)
|
||||
{
|
||||
g_assert (clutter_input_device_get_device_type (device) == CLUTTER_POINTER_DEVICE);
|
||||
settings_device_set_bool_setting (input_settings, device,
|
||||
input_settings_class->set_left_handed,
|
||||
enabled);
|
||||
@@ -366,6 +372,10 @@ update_touchpad_tap_enabled (MetaInputSettings *input_settings,
|
||||
MetaInputSettingsPrivate *priv;
|
||||
gboolean enabled;
|
||||
|
||||
if (device &&
|
||||
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
|
||||
return;
|
||||
|
||||
priv = meta_input_settings_get_instance_private (input_settings);
|
||||
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
||||
enabled = g_settings_get_boolean (priv->touchpad_settings, "tap-to-click");
|
||||
@@ -392,6 +402,10 @@ update_touchpad_scroll_method (MetaInputSettings *input_settings,
|
||||
GDesktopTouchpadScrollMethod method;
|
||||
MetaInputSettingsPrivate *priv;
|
||||
|
||||
if (device &&
|
||||
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
|
||||
return;
|
||||
|
||||
priv = meta_input_settings_get_instance_private (input_settings);
|
||||
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
||||
method = g_settings_get_enum (priv->touchpad_settings, "scroll-method");
|
||||
@@ -418,6 +432,10 @@ update_touchpad_click_method (MetaInputSettings *input_settings,
|
||||
GDesktopTouchpadScrollMethod method;
|
||||
MetaInputSettingsPrivate *priv;
|
||||
|
||||
if (device &&
|
||||
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
|
||||
return;
|
||||
|
||||
priv = meta_input_settings_get_instance_private (input_settings);
|
||||
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
||||
method = g_settings_get_enum (priv->touchpad_settings, "click-method");
|
||||
@@ -444,6 +462,10 @@ update_touchpad_send_events (MetaInputSettings *input_settings,
|
||||
MetaInputSettingsPrivate *priv;
|
||||
GDesktopDeviceSendEvents mode;
|
||||
|
||||
if (device &&
|
||||
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
|
||||
return;
|
||||
|
||||
priv = meta_input_settings_get_instance_private (input_settings);
|
||||
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
||||
mode = g_settings_get_enum (priv->touchpad_settings, "send-events");
|
||||
@@ -486,13 +508,16 @@ update_trackball_scroll_button (MetaInputSettings *input_settings,
|
||||
MetaInputSettingsPrivate *priv;
|
||||
guint button;
|
||||
|
||||
if (device && !device_is_trackball (device))
|
||||
return;
|
||||
|
||||
priv = meta_input_settings_get_instance_private (input_settings);
|
||||
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
||||
/* This key is 'i' in the schema but it also specifies a minimum
|
||||
* range of 0 so the cast here is safe. */
|
||||
button = (guint) g_settings_get_int (priv->trackball_settings, "scroll-wheel-emulation-button");
|
||||
|
||||
if (device && device_is_trackball (device))
|
||||
if (device)
|
||||
{
|
||||
input_settings_class->set_scroll_button (input_settings, device, button);
|
||||
}
|
||||
|
@@ -65,6 +65,7 @@ typedef struct {
|
||||
|
||||
gboolean is_primary;
|
||||
gboolean is_presentation;
|
||||
gboolean is_underscanning;
|
||||
} MetaOutputConfig;
|
||||
|
||||
typedef struct {
|
||||
@@ -82,7 +83,8 @@ struct _MetaMonitorConfig {
|
||||
gboolean current_is_for_laptop_lid;
|
||||
MetaConfiguration *previous;
|
||||
|
||||
GFile *file;
|
||||
GFile *user_file;
|
||||
GFile *system_file;
|
||||
GCancellable *save_cancellable;
|
||||
|
||||
UpClient *up_client;
|
||||
@@ -238,6 +240,7 @@ 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);
|
||||
|
||||
@@ -246,9 +249,17 @@ meta_monitor_config_init (MetaMonitorConfig *self)
|
||||
filename = "monitors.xml";
|
||||
|
||||
path = g_build_filename (g_get_user_config_dir (), filename, NULL);
|
||||
self->file = g_file_new_for_path (path);
|
||||
self->user_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);
|
||||
|
||||
@@ -393,7 +404,8 @@ 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) && parser->unknown_count == 0)
|
||||
strcmp (element_name, "presentation") == 0 ||
|
||||
strcmp (element_name, "underscanning") == 0) && parser->unknown_count == 0)
|
||||
{
|
||||
parser->state = STATE_OUTPUT_FIELD;
|
||||
|
||||
@@ -700,6 +712,8 @@ 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;
|
||||
@@ -717,8 +731,8 @@ static const GMarkupParser config_parser = {
|
||||
.text = handle_text,
|
||||
};
|
||||
|
||||
static void
|
||||
meta_monitor_config_load (MetaMonitorConfig *self)
|
||||
static gboolean
|
||||
load_config_file (MetaMonitorConfig *self, GFile *file)
|
||||
{
|
||||
char *contents;
|
||||
gsize size;
|
||||
@@ -736,14 +750,12 @@ meta_monitor_config_load (MetaMonitorConfig *self)
|
||||
*/
|
||||
|
||||
error = NULL;
|
||||
ok = g_file_load_contents (self->file, NULL, &contents, &size, NULL, &error);
|
||||
ok = g_file_load_contents (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;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memset (&parser, 0, sizeof (ConfigParser));
|
||||
@@ -772,6 +784,17 @@ meta_monitor_config_load (MetaMonitorConfig *self)
|
||||
|
||||
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 *
|
||||
@@ -1408,6 +1431,7 @@ 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
|
||||
@@ -1598,7 +1622,8 @@ 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",
|
||||
" <presentation>%s</presentation>\n"
|
||||
" <underscanning>%s</underscanning>\n",
|
||||
output->rect.width,
|
||||
output->rect.height,
|
||||
refresh_rate,
|
||||
@@ -1607,7 +1632,8 @@ 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_presentation ? "yes" : "no",
|
||||
output->is_underscanning ? "yes" : "no");
|
||||
}
|
||||
|
||||
g_string_append (buffer, " </output>\n");
|
||||
@@ -1622,7 +1648,7 @@ meta_monitor_config_save (MetaMonitorConfig *self)
|
||||
closure->config = g_object_ref (self);
|
||||
closure->buffer = buffer;
|
||||
|
||||
g_file_replace_contents_async (self->file,
|
||||
g_file_replace_contents_async (self->user_file,
|
||||
buffer->str, buffer->len,
|
||||
NULL, /* etag */
|
||||
TRUE,
|
||||
@@ -1941,6 +1967,7 @@ 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);
|
||||
}
|
||||
|
@@ -132,6 +132,7 @@ struct _MetaOutput
|
||||
*/
|
||||
gboolean is_primary;
|
||||
gboolean is_presentation;
|
||||
gboolean is_underscanning;
|
||||
|
||||
gpointer driver_private;
|
||||
GDestroyNotify driver_notify;
|
||||
@@ -159,6 +160,9 @@ struct _MetaCRTC
|
||||
gboolean is_dirty;
|
||||
|
||||
MetaCursorReference *cursor;
|
||||
|
||||
gpointer driver_private;
|
||||
GDestroyNotify driver_notify;
|
||||
};
|
||||
|
||||
struct _MetaMonitorMode
|
||||
@@ -230,6 +234,7 @@ struct _MetaOutputInfo {
|
||||
MetaOutput *output;
|
||||
gboolean is_primary;
|
||||
gboolean is_presentation;
|
||||
gboolean is_underscanning;
|
||||
};
|
||||
|
||||
#define META_TYPE_MONITOR_MANAGER (meta_monitor_manager_get_type ())
|
||||
|
@@ -264,6 +264,21 @@ 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)
|
||||
{
|
||||
@@ -271,8 +286,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);
|
||||
}
|
||||
@@ -520,6 +535,8 @@ 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)
|
||||
@@ -808,7 +825,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;
|
||||
gboolean primary, presentation, underscanning;
|
||||
|
||||
if (output_index >= manager->n_outputs)
|
||||
{
|
||||
@@ -827,6 +844,9 @@ 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);
|
||||
}
|
||||
|
||||
@@ -1194,23 +1214,24 @@ meta_monitor_manager_read_current_config (MetaMonitorManager *manager)
|
||||
MetaOutput *old_outputs;
|
||||
MetaCRTC *old_crtcs;
|
||||
MetaMonitorMode *old_modes;
|
||||
unsigned int n_old_outputs, n_old_modes;
|
||||
unsigned int n_old_outputs, n_old_crtcs, 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);
|
||||
g_free (old_crtcs);
|
||||
meta_monitor_manager_free_crtc_array (old_crtcs, n_old_crtcs);
|
||||
}
|
||||
|
||||
void
|
||||
|
@@ -29,6 +29,7 @@
|
||||
|
||||
#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"
|
||||
@@ -39,10 +40,8 @@
|
||||
struct _MetaBackendNativePrivate
|
||||
{
|
||||
MetaLauncher *launcher;
|
||||
|
||||
MetaBarrierManagerNative *barrier_manager;
|
||||
|
||||
GSettings *keyboard_settings;
|
||||
UpClient *up_client;
|
||||
};
|
||||
typedef struct _MetaBackendNativePrivate MetaBackendNativePrivate;
|
||||
|
||||
@@ -56,9 +55,22 @@ 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,
|
||||
@@ -270,6 +282,10 @@ 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
|
||||
|
@@ -57,6 +57,12 @@ 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;
|
||||
@@ -137,6 +143,12 @@ 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)
|
||||
@@ -181,29 +193,57 @@ drm_mode_hash (gconstpointer ptr)
|
||||
}
|
||||
|
||||
static void
|
||||
find_properties (MetaMonitorManagerKms *manager_kms,
|
||||
MetaOutputKms *output_kms)
|
||||
find_connector_properties (MetaMonitorManagerKms *manager_kms,
|
||||
MetaOutputKms *output_kms)
|
||||
{
|
||||
drmModePropertyPtr prop;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < output_kms->connector->count_props; i++)
|
||||
{
|
||||
prop = drmModeGetProperty (manager_kms->fd, output_kms->connector->props[i]);
|
||||
drmModePropertyPtr 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)
|
||||
@@ -442,6 +482,10 @@ 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);
|
||||
}
|
||||
|
||||
@@ -567,7 +611,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
|
||||
meta_output->is_presentation = FALSE;
|
||||
}
|
||||
|
||||
find_properties (manager_kms, output_kms);
|
||||
find_connector_properties (manager_kms, output_kms);
|
||||
|
||||
edid = read_output_edid (manager_kms, meta_output);
|
||||
meta_output_parse_edid (meta_output, edid);
|
||||
@@ -723,8 +767,9 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
|
||||
|
||||
if (output_kms->dpms_prop_id != 0)
|
||||
{
|
||||
int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->winsys_id,
|
||||
output_kms->dpms_prop_id, state);
|
||||
int ok = drmModeObjectSetProperty (manager_kms->fd, meta_output->winsys_id,
|
||||
DRM_MODE_OBJECT_CONNECTOR,
|
||||
output_kms->dpms_prop_id, state);
|
||||
|
||||
if (ok < 0)
|
||||
meta_warning ("Failed to set power save mode for output %s: %s\n",
|
||||
@@ -748,6 +793,48 @@ 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,
|
||||
@@ -755,6 +842,7 @@ 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;
|
||||
@@ -900,6 +988,9 @@ 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 */
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#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>
|
||||
@@ -35,6 +36,38 @@
|
||||
|
||||
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,
|
||||
@@ -45,23 +78,20 @@ change_property (ClutterInputDevice *device,
|
||||
{
|
||||
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;
|
||||
int device_id;
|
||||
Atom property_atom;
|
||||
guchar *data_ret;
|
||||
|
||||
property_atom = XInternAtom (xdisplay, property, False);
|
||||
device_id = clutter_input_device_get_device_id (device);
|
||||
|
||||
rc = XIGetProperty (xdisplay, device_id, property_atom,
|
||||
0, 0, False, type, &type_ret, &format_ret,
|
||||
&nitems_ret, &bytes_after_ret, &data_ret);
|
||||
data_ret = get_property (device, property, type, format, nitems);
|
||||
if (!data_ret)
|
||||
return;
|
||||
|
||||
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
|
||||
@@ -180,7 +210,7 @@ meta_input_settings_x11_set_scroll_button (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
guint button)
|
||||
{
|
||||
change_property (device, "libinput Scroll Method Enabled",
|
||||
change_property (device, "libinput Button Scrolling Button",
|
||||
XA_INTEGER, 32, &button, 1);
|
||||
}
|
||||
|
||||
@@ -190,16 +220,23 @@ 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;
|
||||
|
@@ -225,6 +225,38 @@ 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)
|
||||
@@ -506,7 +538,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_VGA;
|
||||
return META_CONNECTOR_TYPE_Composite;
|
||||
if (g_str_has_prefix (name, "S-video"))
|
||||
return META_CONNECTOR_TYPE_SVIDEO;
|
||||
if (g_str_has_prefix (name, "TV"))
|
||||
@@ -756,6 +788,7 @@ 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))
|
||||
@@ -876,6 +909,49 @@ 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,
|
||||
@@ -1071,8 +1147,13 @@ 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 */
|
||||
|
@@ -217,19 +217,6 @@ 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,
|
||||
|
@@ -47,9 +47,6 @@ 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,
|
||||
|
@@ -160,12 +160,7 @@ void
|
||||
meta_window_set_alive (MetaWindow *window,
|
||||
gboolean is_alive)
|
||||
{
|
||||
if (window->is_alive == is_alive)
|
||||
return;
|
||||
|
||||
window->is_alive = is_alive;
|
||||
|
||||
if (window->is_alive)
|
||||
if (is_alive)
|
||||
kill_delete_dialog (window);
|
||||
else
|
||||
show_delete_dialog (window, CurrentTime);
|
||||
|
@@ -121,7 +121,7 @@ struct _MetaDisplay
|
||||
* class is constructed.
|
||||
*/
|
||||
#define item(x) Atom atom_##x;
|
||||
#include <meta/atomnames.h>
|
||||
#include <x11/atomnames.h>
|
||||
#undef item
|
||||
|
||||
/* The window and serial of the most recent FocusIn event. */
|
||||
|
@@ -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 <meta/atomnames.h>
|
||||
#include <x11/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 <meta/atomnames.h>
|
||||
#include <x11/atomnames.h>
|
||||
#undef item
|
||||
}
|
||||
|
||||
|
@@ -93,6 +93,15 @@ 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 ();
|
||||
@@ -192,6 +201,7 @@ 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);
|
||||
|
@@ -41,14 +41,6 @@
|
||||
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
|
||||
|
@@ -294,7 +294,7 @@ set_supported_hint (MetaScreen *screen)
|
||||
Atom atoms[] = {
|
||||
#define EWMH_ATOMS_ONLY
|
||||
#define item(x) screen->display->atom_##x,
|
||||
#include <meta/atomnames.h>
|
||||
#include <x11/atomnames.h>
|
||||
#undef item
|
||||
#undef EWMH_ATOMS_ONLY
|
||||
|
||||
@@ -1490,6 +1490,16 @@ 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,
|
||||
|
@@ -434,7 +434,6 @@ struct _MetaWindow
|
||||
|
||||
/* Managed by delete.c */
|
||||
int dialog_pid;
|
||||
guint is_alive : 1;
|
||||
|
||||
/* maintained by group.c */
|
||||
MetaGroup *group;
|
||||
|
@@ -57,7 +57,7 @@
|
||||
#include "x11/xprops.h"
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
#include "wayland/window-wayland.h"
|
||||
#include "wayland/meta-window-wayland.h"
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
#endif
|
||||
|
||||
|
@@ -66,6 +66,21 @@ 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);
|
||||
@@ -82,6 +97,10 @@ 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);
|
||||
|
||||
|
@@ -43,13 +43,6 @@ 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)
|
||||
{
|
||||
@@ -70,7 +63,7 @@ data_offer_accept (struct wl_client *client,
|
||||
|
||||
if (offer->source)
|
||||
{
|
||||
wl_data_source_send_target (offer->source->resource, mime_type);
|
||||
offer->source->funcs.target (offer->source, mime_type);
|
||||
offer->source->has_target = mime_type != NULL;
|
||||
}
|
||||
}
|
||||
@@ -82,9 +75,9 @@ data_offer_receive (struct wl_client *client, struct wl_resource *resource,
|
||||
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
|
||||
|
||||
if (offer->source)
|
||||
wl_data_source_send_send (offer->source->resource, mime_type, fd);
|
||||
|
||||
close (fd);
|
||||
meta_wayland_data_source_send (offer->source, mime_type, fd);
|
||||
else
|
||||
close (fd);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -104,7 +97,7 @@ destroy_data_offer (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
|
||||
|
||||
if (offer->source)
|
||||
if (offer->source && offer->source->resource)
|
||||
wl_list_remove (&offer->source_destroy_listener.link);
|
||||
|
||||
g_slice_free (MetaWaylandDataOffer, offer);
|
||||
@@ -116,7 +109,6 @@ destroy_offer_data_source (struct wl_listener *listener, void *data)
|
||||
MetaWaylandDataOffer *offer;
|
||||
|
||||
offer = wl_container_of (listener, offer, source_destroy_listener);
|
||||
|
||||
offer->source = NULL;
|
||||
}
|
||||
|
||||
@@ -128,11 +120,14 @@ 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);
|
||||
wl_resource_add_destroy_listener (source->resource, &offer->source_destroy_listener);
|
||||
|
||||
if (source->resource)
|
||||
{
|
||||
offer->source_destroy_listener.notify = destroy_offer_data_source;
|
||||
wl_resource_add_destroy_listener (source->resource, &offer->source_destroy_listener);
|
||||
}
|
||||
|
||||
wl_data_device_send_data_offer (target, offer->resource);
|
||||
|
||||
@@ -147,12 +142,8 @@ data_source_offer (struct wl_client *client,
|
||||
struct wl_resource *resource, const char *type)
|
||||
{
|
||||
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
|
||||
char **p;
|
||||
|
||||
p = wl_array_add (&source->mime_types, sizeof *p);
|
||||
if (p)
|
||||
*p = strdup (type);
|
||||
if (!p || !*p)
|
||||
if (!meta_wayland_data_source_add_mime_type (source, type))
|
||||
wl_resource_post_no_memory (resource);
|
||||
}
|
||||
|
||||
@@ -291,10 +282,7 @@ data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
|
||||
}
|
||||
|
||||
if (drag_grab->drag_data_source)
|
||||
{
|
||||
drag_grab->drag_data_source->has_target = FALSE;
|
||||
wl_list_remove (&drag_grab->drag_data_source_listener.link);
|
||||
}
|
||||
wl_list_remove (&drag_grab->drag_data_source_listener.link);
|
||||
|
||||
if (drag_grab->feedback_actor)
|
||||
{
|
||||
@@ -355,6 +343,7 @@ 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
|
||||
@@ -365,13 +354,14 @@ 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_data_source_listener);
|
||||
wl_container_of (listener, drag_grab, drag_icon_listener);
|
||||
|
||||
drag_grab->drag_surface = NULL;
|
||||
|
||||
@@ -442,6 +432,9 @@ 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)
|
||||
@@ -489,6 +482,48 @@ 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)
|
||||
@@ -503,8 +538,15 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
|
||||
|
||||
if (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->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);
|
||||
data_device->selection_data_source = NULL;
|
||||
}
|
||||
|
||||
@@ -531,8 +573,13 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
|
||||
|
||||
if (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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,25 +617,23 @@ static void
|
||||
destroy_data_source (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
|
||||
char **p;
|
||||
|
||||
wl_array_for_each (p, &source->mime_types) free (*p);
|
||||
|
||||
wl_array_release (&source->mime_types);
|
||||
|
||||
g_slice_free (MetaWaylandDataSource, source);
|
||||
source->resource = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
create_data_source (struct wl_client *client,
|
||||
struct wl_resource *resource, guint32 id)
|
||||
{
|
||||
MetaWaylandDataSource *source = g_slice_new0 (MetaWaylandDataSource);
|
||||
MetaWaylandDataSource *source;
|
||||
struct wl_resource *source_resource;
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -632,6 +677,8 @@ 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
|
||||
@@ -683,3 +730,75 @@ 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;
|
||||
}
|
||||
|
@@ -28,14 +28,38 @@
|
||||
#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);
|
||||
@@ -48,4 +72,25 @@ 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 */
|
||||
|
@@ -33,6 +33,8 @@
|
||||
#include "meta-wayland-surface.h"
|
||||
#include "meta-wayland-seat.h"
|
||||
|
||||
typedef struct _MetaXWaylandSelection MetaXWaylandSelection;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct wl_list link;
|
||||
@@ -43,7 +45,7 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
int display_index;
|
||||
char *lockfile;
|
||||
char *lock_file;
|
||||
int abstract_fd;
|
||||
int unix_fd;
|
||||
pid_t pid;
|
||||
@@ -52,6 +54,8 @@ typedef struct
|
||||
char *display_name;
|
||||
|
||||
GMainLoop *init_loop;
|
||||
|
||||
MetaXWaylandSelection *selection_data;
|
||||
} MetaXWaylandManager;
|
||||
|
||||
struct _MetaWaylandCompositor
|
||||
|
@@ -46,7 +46,7 @@
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "display-private.h"
|
||||
#include "window-private.h"
|
||||
#include "window-wayland.h"
|
||||
#include "meta-window-wayland.h"
|
||||
|
||||
#include "compositor/region-utils.h"
|
||||
|
||||
@@ -215,19 +215,52 @@ 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;
|
||||
|
||||
/* Sanity check. */
|
||||
if (surface->buffer == NULL)
|
||||
if (surface->role == META_WAYLAND_SURFACE_ROLE_WL_SHELL_SURFACE)
|
||||
{
|
||||
wl_resource_post_error (surface->resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
"Cannot commit a NULL buffer to an xdg_surface");
|
||||
return;
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* We resize X based surfaces according to X events */
|
||||
@@ -723,20 +756,6 @@ 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)
|
||||
{
|
||||
@@ -1506,7 +1525,6 @@ 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)
|
||||
{
|
||||
@@ -1524,9 +1542,6 @@ 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 = {
|
||||
@@ -1554,14 +1569,14 @@ gtk_surface_destructor (struct wl_resource *resource)
|
||||
}
|
||||
|
||||
static void
|
||||
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)
|
||||
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)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
@@ -1581,8 +1596,36 @@ 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 = {
|
||||
set_dbus_properties
|
||||
gtk_surface_set_dbus_properties,
|
||||
gtk_surface_set_modal,
|
||||
gtk_surface_unset_modal,
|
||||
};
|
||||
|
||||
static void
|
||||
@@ -1619,6 +1662,17 @@ bind_gtk_shell (struct wl_client *client,
|
||||
uint32_t capabilities = 0;
|
||||
|
||||
resource = wl_resource_create (client, >k_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 ())
|
||||
|
@@ -101,6 +101,7 @@ struct _MetaWaylandSurface
|
||||
struct wl_resource *xdg_shell_resource;
|
||||
MetaWaylandSerial acked_configure_serial;
|
||||
gboolean has_set_geometry;
|
||||
gboolean is_modal;
|
||||
|
||||
/* xdg_popup */
|
||||
struct {
|
||||
|
@@ -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 1
|
||||
#define META_GTK_SHELL_VERSION 2
|
||||
#define META_WL_SUBCOMPOSITOR_VERSION 1
|
||||
|
||||
#endif
|
||||
|
@@ -24,7 +24,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "window-wayland.h"
|
||||
#include "meta-window-wayland.h"
|
||||
|
||||
#include <meta/errors.h>
|
||||
#include "window-private.h"
|
@@ -34,4 +34,9 @@ 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 */
|
||||
|
943
src/wayland/meta-xwayland-selection.c
Normal file
943
src/wayland/meta-xwayland-selection.c
Normal file
@@ -0,0 +1,943 @@
|
||||
/*
|
||||
* 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 *) ×tamp, 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;
|
||||
}
|
@@ -182,7 +182,7 @@ try_display (int display,
|
||||
|
||||
if (kill (other, 0) < 0 && errno == ESRCH)
|
||||
{
|
||||
/* Process is dead. Try unlinking the lockfile and trying again. */
|
||||
/* Process is dead. Try unlinking the lock file 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_lockfile (int display, int *display_out)
|
||||
create_lock_file (int display, int *display_out)
|
||||
{
|
||||
char *filename;
|
||||
int fd;
|
||||
@@ -354,7 +354,7 @@ static gboolean
|
||||
choose_xdisplay (MetaXWaylandManager *manager)
|
||||
{
|
||||
int display = 0;
|
||||
char *lockfile = NULL;
|
||||
char *lock_file = 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
|
||||
{
|
||||
lockfile = create_lockfile (display, &display);
|
||||
if (!lockfile)
|
||||
lock_file = create_lock_file (display, &display);
|
||||
if (!lock_file)
|
||||
{
|
||||
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 (lockfile);
|
||||
unlink (lock_file);
|
||||
|
||||
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 (lockfile);
|
||||
unlink (lock_file);
|
||||
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->lockfile = lockfile;
|
||||
manager->lock_file = lock_file;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -438,28 +438,27 @@ 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))
|
||||
return FALSE;
|
||||
goto out;
|
||||
|
||||
/* 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");
|
||||
unlink (manager->lockfile);
|
||||
return FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, displayfd) < 0)
|
||||
{
|
||||
g_warning ("displayfd socketpair failed\n");
|
||||
unlink (manager->lockfile);
|
||||
return FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* xwayland, please. */
|
||||
@@ -489,7 +488,7 @@ meta_xwayland_start (MetaXWaylandManager *manager,
|
||||
if (!proc)
|
||||
{
|
||||
g_error ("Failed to spawn Xwayland: %s", error->message);
|
||||
return FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_subprocess_wait_async (proc, NULL, xserver_died, NULL);
|
||||
@@ -502,7 +501,15 @@ meta_xwayland_start (MetaXWaylandManager *manager,
|
||||
manager->init_loop = g_main_loop_new (NULL, FALSE);
|
||||
g_main_loop_run (manager->init_loop);
|
||||
|
||||
return TRUE;
|
||||
started = TRUE;
|
||||
|
||||
out:
|
||||
if (!started)
|
||||
{
|
||||
unlink (manager->lock_file);
|
||||
g_clear_pointer (&manager->lock_file, g_free);
|
||||
}
|
||||
return started;
|
||||
}
|
||||
|
||||
/* To be called right after connecting */
|
||||
@@ -515,6 +522,8 @@ meta_xwayland_complete_init (void)
|
||||
we won't reset the tty).
|
||||
*/
|
||||
XSetIOErrorHandler (x_io_error);
|
||||
|
||||
meta_xwayland_init_selection ();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -522,10 +531,15 @@ meta_xwayland_stop (MetaXWaylandManager *manager)
|
||||
{
|
||||
char path[256];
|
||||
|
||||
snprintf (path, sizeof path, "/tmp/.X%d-lock", manager->display_index);
|
||||
unlink (path);
|
||||
meta_xwayland_shutdown_selection ();
|
||||
|
||||
snprintf (path, sizeof path, "/tmp/.X11-unix/X%d", manager->display_index);
|
||||
unlink (path);
|
||||
|
||||
unlink (manager->lockfile);
|
||||
g_clear_pointer (&manager->display_name, g_free);
|
||||
if (manager->lock_file)
|
||||
{
|
||||
unlink (manager->lock_file);
|
||||
g_clear_pointer (&manager->lock_file, g_free);
|
||||
}
|
||||
}
|
||||
|
@@ -1,9 +1,18 @@
|
||||
<protocol name="gtk">
|
||||
|
||||
<interface name="gtk_shell" version="1">
|
||||
<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>
|
||||
|
||||
<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">
|
||||
@@ -16,7 +25,7 @@
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="gtk_surface" version="1">
|
||||
<interface name="gtk_surface" version="2">
|
||||
<request name="set_dbus_properties">
|
||||
<arg name="application_id" type="string" allow-null="true"/>
|
||||
<arg name="app_menu_path" type="string" allow-null="true"/>
|
||||
@@ -25,6 +34,9 @@
|
||||
<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>
|
||||
|
@@ -39,6 +39,7 @@
|
||||
#ifdef HAVE_WAYLAND
|
||||
#include "wayland/meta-xwayland.h"
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
#include "wayland/meta-xwayland-private.h"
|
||||
#endif
|
||||
|
||||
static XIEvent *
|
||||
@@ -1676,6 +1677,15 @@ 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;
|
||||
|
||||
|
Reference in New Issue
Block a user