Compare commits

...

36 Commits

Author SHA1 Message Date
Florian Müllner
8d51a9db5b Bump version to 3.17.2
Update NEWS.
2015-05-27 10:28:44 +02:00
Rui Matos
b39c00f344 window: Fix meta_window_set_alive() not working if first ping fails
window->is_alive isn't initialized explicitly so it defaults to FALSE
meaning that if the first ping fails we'd short circuit and not show
the delete dialog as we should.

We could initialize the variable to TRUE but in fact we don't even
need the variable at all since our dialog management is enough to
manage all the state we need, i.e. we're only interested in knowing
whether we're already displaying a delete dialog.

This does change our behavior here since previously we wouldn't
display the dialog again if the next ping failed after the dialog is
dismissed but this was arguably a bug too since in that case there
wouldn't be a way to kill the window after waiting for a while and the
window kept being unresponsive.

https://bugzilla.gnome.org/show_bug.cgi?id=749711
2015-05-22 16:53:42 +02:00
Rui Matos
83ce71c3bf backend-native: Reset idle time on lid open events
This makes gnome-settings-daemon turn on the backlight and
gnome-shell's screen shield animate.

Note that on X sessions, gnome-settings-daemon uses the same upower
property to force an innocuous key event into the X server so that the
idle time gets reset since Xorg doesn't do this itself on lid events.

https://bugzilla.gnome.org/show_bug.cgi?id=749076
2015-05-22 16:53:42 +02:00
Rui Matos
f9d869a3dd backend-native: Remove unused variable
https://bugzilla.gnome.org/show_bug.cgi?id=749076
2015-05-22 16:43:44 +02:00
Carlos Garnacho
0b0ce4193f xwayland: Ensure we've got an owner when setting the X selection owner
Otherwise we may end up claiming the X selection when there's no wayland
selection owner.
2015-05-18 20:59:07 +02:00
Carlos Garnacho
719d8bd0c7 xwayland: remove unused struct field 2015-05-18 20:58:57 +02:00
Carlos Garnacho
4fc1811c15 wayland: Add X11/wayland selection interoperation
This piece of code hooks in both wl_data_device and the relevant X
selection events, an X11 Window is set up so it can act as the clipboard
owner when any wayland client owns the selection, reacting to
SelectionRequest events, and returning the data from the wayland client
FD to any X11 requestor through X properties.

In the opposite direction, SelectionNotify messages are received,
which results in the property contents being converted then written
into the wayland requestor's FD.

This code also takes care of the handling incremental transfers through
the INCR property type, reading/writing data chunk by chunk.

https://bugzilla.gnome.org/show_bug.cgi?id=738312
2015-05-15 17:43:53 +02:00
Carlos Garnacho
4b5f5abb4f wayland: refactor MetaWaylandDataSource
Expose it partly (in internal headers anyway), and pass a vtable for the
data source functions, the wayland vfuncs just delegate operations on the
wl_data_source resource. The resource has been also made optional, although
it'll be present on all data sources from wayland clients.

The ownership/lifetime of the DnD data source has also changed a bit,
belonging now to the MetaWaylandDataDevice like the selection one does, as
we can't guarantee how long it will be needed after the grab is finished,
it will be left inert and replaced the next time DnD is started at worst.

This allows the creation of custom/proxy data sources, which will turn out
useful for X11 selection interoperation.

https://bugzilla.gnome.org/show_bug.cgi?id=738312
2015-05-15 17:43:46 +02:00
Jasper St. Pierre
95ad52ba58 xrandr: Fix copy/paste typo in connector type heuristics 2015-05-12 18:17:16 -07:00
Rui Matos
dac30a222e input-settings-x11: Honor default value for click method setting
Now that xf86-input-libinput exposes default values we can honor the
gsettings value.

https://bugzilla.gnome.org/show_bug.cgi?id=746290
2015-05-08 17:44:59 +02:00
Rui Matos
7d1b593fbd input-settings-x11: Factor out a get_property() helper
We'll need to get the value of some properties. Fail if the number of
items returned is less than we expect and warn if it exceeds it so
that we can easily find out if items are added to a property later and
fix it.
2015-05-08 17:44:57 +02:00
Carlos Garnacho
d6a7559750 wayland: Fix c&p typo in wl_listener notify callback
The corresponding wl_notify field for destroy_data_device_icon()
is drag_grab->drag_icon_listener, otherwise we're fetching a pointer
that's slightly off where we want.
2015-05-01 18:50:06 +02:00
Florian Müllner
cff5ef0ec2 Bump version to 3.17.1
Update NEWS.
2015-04-30 17:35:43 +02:00
Rui Matos
d478d8f143 core/events: Invalidate monitor cache when we're a wayland compositor
When running as an X11 compositor we do this for every event we see on
the X event stream. As a wayland compositor we don't go through that
code path but since we see all events we can easily do this on motion
events.

In fact, we don't even need this caching when we're a wayland
compositor since we can always find where the pointer is without a
round trip but we're sharing the current monitor logic with the X
path so let's keep it as is for now.

https://bugzilla.gnome.org/show_bug.cgi?id=748478
2015-04-30 14:01:23 +02:00
Rui Matos
7eca43cec9 monitor-manager-kms: Avoid a couple of potential crashes
The drm API can return NULL and we could end up using uninitialized
memory if the driver private struct isn't cleared.
2015-04-28 18:00:45 +02:00
Rui Matos
9060190555 monitor-manager-kms: Read crtc props after determining the crtc ID
Otherwise we can't read the properties.
2015-04-28 18:00:44 +02:00
Jasper St. Pierre
0de3869656 core: Remove unused function 2015-04-27 18:14:15 -07:00
Jasper St. Pierre
9f13033f15 window-wayland.[ch] => meta-window-wayland.[ch]
This finishes off the meta- prefix for wayland/.
2015-04-27 18:09:16 -07:00
Jasper St. Pierre
48bf807430 monitor-manager-kms: Add support for underscan 2015-04-27 17:58:38 -07:00
Jasper St. Pierre
c68e43a97f monitor-manager-xrandr: Set the underscan border properties, too 2015-04-27 17:23:56 -07:00
Tomeu Vizoso
cc53d48fa8 MonitorManager: Add support for overscan compensation
Some DRM drivers have added a consistent set of properties that
allow compensating for the overscan that some TVs do, without the
user being able to disable.
2015-04-27 17:17:15 -07:00
Jasper St. Pierre
ca6e799b97 Move atomnames.h to x11/
This should *not* be part of the public API.
2015-04-27 16:36:56 -07:00
Jasper St. Pierre
0f8e387dc0 monitor-config: Allow loading from a system file 2015-04-27 16:31:11 -07:00
Rui Matos
d62c595e51 events: Ignore some event types when reseting idle time
These events don't result from actual hardware events so we shouldn't
use them to reset idle time.

https://bugzilla.gnome.org/show_bug.cgi?id=748541
2015-04-27 19:44:58 +02:00
Jasper St. Pierre
dd3cf94744 Properly implement wl_shell_surface's poor surface commit semantics 2015-04-25 11:19:25 -07:00
Ray Strode
eb56e0a3d7 xwayland: plug some leaks in stop function
This commit makes sure the lockfile and display
name are freed in meta_xwayland_stop.

https://bugzilla.gnome.org/show_bug.cgi?id=748380
2015-04-23 13:51:11 -04:00
Ray Strode
8937c32cd5 xwayland: rename lockfile to lock_file
The missing underscore is inconsistent with the
coding style of the surrounding code.

https://bugzilla.gnome.org/show_bug.cgi?id=748380
2015-04-23 13:51:11 -04:00
Ray Strode
a8a5da768a xwayland: don't unlink lock file twice in stop function
The stop function currently manually constructs the lock
filename from the display number and also calls unlink
on the same, already known lock filename from the manager
struct.

This commit gets rid fo the manual construction in favor
of the saved lock filename.

https://bugzilla.gnome.org/show_bug.cgi?id=748380
2015-04-23 13:51:11 -04:00
Ray Strode
33bfcf56ce xwayland: free lockfile in start function on error
Right now we just leak the lockfile.

https://bugzilla.gnome.org/show_bug.cgi?id=748380
2015-04-23 13:51:11 -04:00
Ray Strode
40cccb58a5 xwayland: use out label for cleanup in start function
The start function has a few exit paths that need to
perform clean up of the lock file.

This commit consolidates those exit paths at the end
using an out label and gotos.

https://bugzilla.gnome.org/show_bug.cgi?id=748380
2015-04-23 13:51:11 -04:00
Jonas Ådahl
eb6c70137b wayland: Add and implement set/unset_modal for the gtk_surface interface
Add set_modal ond unset_modal to the gtk_surface interface. When a
surface is modal, the compositor can treat it differently from non-modal
dialogs, for example attach it to the parent window if any. There is
currently no changes to input device focus; it is up to the client to
ignore events to the parent surface that is wanted.

This bumps the gtk_shell version to 2.

https://bugzilla.gnome.org/show_bug.cgi?id=745720
2015-04-23 16:02:37 +08:00
Jonas Ådahl
df3b412a25 wayland: Kill clients who try to bind an incompatible gtk_shell version
gtk_shell is not backward compatible, and clients binding to it should
check whether the advertised version is the same as the client supports.

https://bugzilla.gnome.org/show_bug.cgi?id=745720
2015-04-23 16:02:37 +08:00
Jonas Ådahl
cfba0a5dfc wayland: Sync protocol/gtk-shell.xml from GTK+
Had added a new capability enum value.

https://bugzilla.gnome.org/show_bug.cgi?id=745720
2015-04-23 16:02:37 +08:00
Ondrej Holy
3561b46fc6 backends/x11: Fix set_scroll_button
There is copy&pasted code in set_scroll_button, which is apparently
wrong, because it is trying to set scroll method instead of the scroll
button...

https://bugzilla.gnome.org/show_bug.cgi?id=747967
2015-04-17 10:50:33 +02:00
Carlos Garnacho
8dfb88b669 backend: Apply the right settings to the right input devices
Since 8769b3d55, the checks performed on which update_* function was
called for each device got quite more lax, leading to failed asserts
on code that assumed the previous behavior.

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

https://bugzilla.gnome.org/show_bug.cgi?id=747886
2015-04-15 13:33:12 +02:00
Florian Müllner
2e3086e2aa screen: Add public method to get neighboring monitor
The existing private get_monitor_neighbor() function returns a
MetaMonitorInfo, which is private as well. Add a public wrapper
that returns a monitor index instead, as we do for other public
monitor-related methods.

https://bugzilla.gnome.org/show_bug.cgi?id=633994
2015-04-14 23:13:19 +02:00
36 changed files with 1732 additions and 195 deletions

22
NEWS
View File

@@ -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]

View File

@@ -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])

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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 ())

View File

@@ -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

View File

@@ -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

View File

@@ -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 */

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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,

View File

@@ -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,

View File

@@ -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);

View File

@@ -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. */

View File

@@ -549,7 +549,7 @@ meta_display_open (void)
/* A list of all atom names, so that we can intern them in one go. */
char *atom_names[] = {
#define item(x) #x,
#include <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
}

View File

@@ -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);

View File

@@ -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

View File

@@ -294,7 +294,7 @@ set_supported_hint (MetaScreen *screen)
Atom atoms[] = {
#define EWMH_ATOMS_ONLY
#define item(x) screen->display->atom_##x,
#include <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,

View File

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

View File

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

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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

View File

@@ -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, &gtk_shell_interface, version, id);
if (version != META_GTK_SHELL_VERSION)
{
wl_resource_post_error (resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"Incompatible gtk-shell version "
"(supported version: %d)",
META_GTK_SHELL_VERSION);
return;
}
wl_resource_set_implementation (resource, &meta_wayland_gtk_shell_interface, data, NULL);
if (!meta_prefs_get_show_fallback_app_menu ())

View File

@@ -101,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 {

View File

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

View File

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

View File

@@ -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 */

View 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 *) &timestamp, 1);
}
static void
meta_xwayland_selection_send_incr_chunk (MetaWaylandCompositor *compositor,
MetaSelectionBridge *selection)
{
if (!selection->wayland_selection)
return;
if (selection->wayland_selection->buffer_len > 0)
wayland_selection_update_x11_property (selection->wayland_selection);
else
wayland_selection_data_read (selection);
}
static gboolean
handle_incr_chunk (MetaWaylandCompositor *compositor,
MetaSelectionBridge *selection,
XPropertyEvent *event)
{
if (selection->x11_selection &&
selection->x11_selection->incr &&
event->window == selection->owner &&
event->state == PropertyNewValue &&
event->atom == gdk_x11_get_xatom_by_name ("_META_SELECTION"))
{
/* X11 to Wayland */
meta_xwayland_selection_get_incr_chunk (compositor, selection);
return TRUE;
}
else if (selection->wayland_selection &&
selection->wayland_selection->incr &&
event->window == selection->window &&
event->state == PropertyDelete &&
event->atom == selection->wayland_selection->request_event.property)
{
/* Wayland to X11 */
meta_xwayland_selection_send_incr_chunk (compositor, selection);
return TRUE;
}
return FALSE;
}
static gboolean
meta_xwayland_selection_handle_property_notify (MetaWaylandCompositor *compositor,
XEvent *xevent)
{
MetaXWaylandSelection *selection_data = compositor->xwayland_manager.selection_data;
XPropertyEvent *event = (XPropertyEvent *) xevent;
return handle_incr_chunk (compositor, &selection_data->clipboard, event);
}
static gboolean
meta_xwayland_selection_handle_selection_request (MetaWaylandCompositor *compositor,
XEvent *xevent)
{
XSelectionRequestEvent *event = (XSelectionRequestEvent *) xevent;
MetaWaylandDataSource *data_source;
MetaSelectionBridge *selection;
selection = atom_to_selection_bridge (compositor, event->selection);
if (!selection)
return FALSE;
/* We must fetch from the currently active source, not the Xwayland one */
data_source = data_device_get_active_source_for_atom (&compositor->seat->data_device,
selection->selection_atom);
if (!data_source)
return FALSE;
g_clear_pointer (&selection->wayland_selection,
(GDestroyNotify) wayland_selection_data_free);
if (event->target == gdk_x11_get_xatom_by_name ("TARGETS"))
{
meta_xwayland_selection_send_targets (compositor,
data_source,
event->requestor,
event->property);
reply_selection_request (event, TRUE);
}
else if (event->target == gdk_x11_get_xatom_by_name ("TIMESTAMP"))
{
meta_xwayland_selection_send_timestamp (compositor,
event->requestor, event->property,
selection->timestamp);
reply_selection_request (event, TRUE);
}
else
{
if (data_source &&
meta_wayland_data_source_has_mime_type (data_source,
gdk_x11_get_xatom_name (event->target)))
{
selection->wayland_selection = wayland_selection_data_new (event,
compositor);
if (selection->wayland_selection)
wayland_selection_data_read (selection);
}
if (!selection->wayland_selection)
reply_selection_request (event, FALSE);
}
return TRUE;
}
static gboolean
meta_xwayland_selection_handle_xfixes_selection_notify (MetaWaylandCompositor *compositor,
XEvent *xevent)
{
XFixesSelectionNotifyEvent *event = (XFixesSelectionNotifyEvent *) xevent;
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
MetaSelectionBridge *selection;
selection = atom_to_selection_bridge (compositor, event->selection);
if (!selection)
return FALSE;
if (event->owner == None)
{
if (selection->source && selection->owner != selection->window)
{
/* An X client went away, clear the selection */
if (selection->selection_atom == gdk_x11_get_xatom_by_name ("CLIPBOARD"))
{
meta_wayland_data_device_set_selection (&compositor->seat->data_device, NULL,
wl_display_next_serial (compositor->wayland_display));
}
selection->source = NULL;
}
selection->owner = None;
}
else
{
selection->owner = event->owner;
if (selection->owner == selection->window)
{
/* This our own selection window */
selection->timestamp = event->timestamp;
return TRUE;
}
g_clear_pointer (&selection->x11_selection,
(GDestroyNotify) x11_selection_data_free);
XConvertSelection (xdisplay,
event->selection,
gdk_x11_get_xatom_by_name ("TARGETS"),
gdk_x11_get_xatom_by_name ("_META_SELECTION"),
selection->window,
selection->timestamp);
XFlush (xdisplay);
}
return TRUE;
}
gboolean
meta_xwayland_selection_handle_event (XEvent *xevent)
{
MetaWaylandCompositor *compositor;
compositor = meta_wayland_compositor_get_default ();
if (!compositor->xwayland_manager.selection_data)
return FALSE;
switch (xevent->type)
{
case SelectionNotify:
return meta_xwayland_selection_handle_selection_notify (compositor, xevent);
case PropertyNotify:
return meta_xwayland_selection_handle_property_notify (compositor, xevent);
case SelectionRequest:
return meta_xwayland_selection_handle_selection_request (compositor, xevent);
default:
{
MetaDisplay *display = meta_get_display ();
if (xevent->type - display->xfixes_event_base == XFixesSelectionNotify)
return meta_xwayland_selection_handle_xfixes_selection_notify (compositor, xevent);
return FALSE;
}
}
}
static void
meta_selection_bridge_ownership_notify (struct wl_listener *listener,
void *data)
{
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
MetaSelectionBridge *selection =
wl_container_of (listener, selection, ownership_listener);
MetaWaylandDataSource *owner = data;
if (!owner && selection->window == selection->owner)
{
XSetSelectionOwner (xdisplay, selection->selection_atom,
None, selection->timestamp);
}
else if (owner && selection->source != owner)
{
XSetSelectionOwner (xdisplay,
selection->selection_atom,
selection->window,
CurrentTime);
}
}
static void
init_selection_bridge (MetaSelectionBridge *selection,
Atom selection_atom,
struct wl_signal *signal)
{
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
XSetWindowAttributes attributes;
guint mask;
attributes.event_mask = PropertyChangeMask;
selection->ownership_listener.notify = meta_selection_bridge_ownership_notify;
wl_signal_add (signal, &selection->ownership_listener);
selection->selection_atom = selection_atom;
selection->window =
XCreateWindow (xdisplay,
gdk_x11_window_get_xid (gdk_get_default_root_window ()),
-1, -1, 1, 1, /* position */
0, /* border width */
0, /* depth */
InputOnly, /* class */
CopyFromParent, /* visual */
CWEventMask,
&attributes);
mask = XFixesSetSelectionOwnerNotifyMask |
XFixesSelectionWindowDestroyNotifyMask |
XFixesSelectionClientCloseNotifyMask;
XFixesSelectSelectionInput (xdisplay, selection->window,
selection_atom, mask);
}
static void
shutdown_selection_bridge (MetaSelectionBridge *selection)
{
wl_list_remove (&selection->ownership_listener.link);
XDestroyWindow (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
selection->window);
g_clear_pointer (&selection->wayland_selection,
(GDestroyNotify) wayland_selection_data_free);
g_clear_pointer (&selection->x11_selection,
(GDestroyNotify) x11_selection_data_free);
}
void
meta_xwayland_init_selection (void)
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaXWaylandManager *manager = &compositor->xwayland_manager;
g_assert (manager->selection_data == NULL);
manager->selection_data = g_slice_new0 (MetaXWaylandSelection);
init_selection_bridge (&manager->selection_data->clipboard,
gdk_x11_get_xatom_by_name ("CLIPBOARD"),
&compositor->seat->data_device.selection_ownership_signal);
}
void
meta_xwayland_shutdown_selection (void)
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaXWaylandManager *manager = &compositor->xwayland_manager;
MetaXWaylandSelection *selection = manager->selection_data;
g_assert (selection != NULL);
if (selection->clipboard.source)
{
meta_wayland_data_device_set_selection (&compositor->seat->data_device, NULL,
wl_display_next_serial (compositor->wayland_display));
}
shutdown_selection_bridge (&selection->clipboard);
g_slice_free (MetaXWaylandSelection, selection);
manager->selection_data = NULL;
}

View File

@@ -182,7 +182,7 @@ try_display (int display,
if (kill (other, 0) < 0 && errno == ESRCH)
{
/* Process is dead. Try unlinking the 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);
}
}

View File

@@ -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>

View File

@@ -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;