Compare commits

..

3 Commits

Author SHA1 Message Date
e947d2f544 Bump version to 3.12.1
Update NEWS.
2014-04-15 22:46:38 +02:00
12e8d04c16 po: Update POTFILES after file got renamed 2014-04-15 22:46:37 +02:00
783dbf9390 build: Complete rename of header file
Fallout from commit d5552cc372.
2014-04-15 22:31:11 +02:00
31 changed files with 833 additions and 886 deletions

7
NEWS
View File

@ -1,3 +1,10 @@
3.12.1
======
* Fix crash when running as X11 compositor [Adel; #727115]
Contributors:
Matthias Clasen, Adel Gadllah, Florian Müllner, Jasper St. Pierre
3.12.0
======
* Fix grab issue with SSD xwayland windows [Rui; #726123]

View File

@ -3,7 +3,7 @@ AC_CONFIG_MACRO_DIR([m4])
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [12])
m4_define([mutter_micro_version], [0])
m4_define([mutter_micro_version], [1])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@ -133,7 +133,7 @@ AC_ARG_WITH([wayland-protocols],
AC_ARG_WITH([xwayland-path],
[AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])],
[XWAYLAND_PATH="$withval"],
[XWAYLAND_PATH="$bindir/Xwayland"])
[XWAYLAND_PATH="$bindir/Xorg"])
AM_GLIB_GNU_GETTEXT

View File

@ -3,6 +3,7 @@
src/50-mutter-navigation.xml.in
src/50-mutter-system.xml.in
src/50-mutter-windows.xml.in
src/backends/meta-monitor-manager.c
src/compositor/compositor.c
src/compositor/meta-background.c
src/core/bell.c
@ -12,7 +13,6 @@ src/core/display.c
src/core/errors.c
src/core/keybindings.c
src/core/main.c
src/core/monitor.c
src/core/mutter.c
src/core/prefs.c
src/core/screen.c

View File

@ -41,11 +41,14 @@ mutter_built_sources = \
gtk-shell-protocol.c \
gtk-shell-server-protocol.h \
xdg-shell-protocol.c \
xdg-shell-server-protocol.h
xdg-shell-server-protocol.h \
xserver-protocol.c \
xserver-server-protocol.h
wayland_protocols = \
wayland/protocol/gtk-shell.xml \
wayland/protocol/xdg-shell.xml
wayland/protocol/xdg-shell.xml \
wayland/protocol/xserver.xml
libmutter_wayland_la_SOURCES = \
backends/meta-backend.c \
@ -55,6 +58,7 @@ libmutter_wayland_la_SOURCES = \
backends/meta-cursor-private.h \
backends/meta-cursor-tracker.c \
backends/meta-cursor-tracker-private.h \
backends/meta-display-config-shared.h \
backends/meta-idle-monitor.c \
backends/meta-idle-monitor-private.h \
backends/meta-idle-monitor-dbus.c \
@ -77,7 +81,6 @@ libmutter_wayland_la_SOURCES = \
backends/x11/meta-idle-monitor-xsync.h \
backends/x11/meta-monitor-manager-xrandr.c \
backends/x11/meta-monitor-manager-xrandr.h \
backends/x11/meta-xrandr-shared.h \
core/above-tab-keycode.c \
core/barrier.c \
meta/barrier.h \
@ -211,9 +214,8 @@ libmutter_wayland_la_SOURCES = \
wayland/meta-wayland.c \
wayland/meta-wayland.h \
wayland/meta-wayland-private.h \
wayland/meta-xwayland.c \
wayland/meta-xwayland.h \
wayland/meta-xwayland-private.h \
wayland/meta-xwayland.c \
wayland/meta-wayland-data-device.c \
wayland/meta-wayland-data-device.h \
wayland/meta-wayland-keyboard.c \

View File

@ -491,7 +491,7 @@ redirect_windows (MetaScreen *screen)
*/
while (TRUE)
{
meta_error_trap_push (display);
meta_error_trap_push_with_return (display);
XCompositeRedirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
XSync (xdisplay, FALSE);

View File

@ -26,6 +26,8 @@
#include <config.h>
#include <cogl/cogl-texture-pixmap-x11.h>
#include <clutter/clutter.h>
#include "cogl-utils.h"
@ -753,6 +755,88 @@ set_filename (MetaBackground *self,
priv->filename = g_strdup (filename);
}
static Pixmap
get_still_frame_for_monitor (MetaScreen *screen,
int monitor)
{
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdisplay = meta_display_get_xdisplay (display);
Window xroot = meta_screen_get_xroot (screen);
Pixmap pixmap;
GC gc;
XGCValues values;
MetaRectangle geometry;
int depth;
meta_screen_get_monitor_geometry (screen, monitor, &geometry);
depth = DefaultDepth (xdisplay, meta_screen_get_screen_number (screen));
pixmap = XCreatePixmap (xdisplay,
xroot,
geometry.width, geometry.height, depth);
values.function = GXcopy;
values.plane_mask = AllPlanes;
values.fill_style = FillSolid;
values.subwindow_mode = IncludeInferiors;
gc = XCreateGC (xdisplay,
xroot,
GCFunction | GCPlaneMask | GCFillStyle | GCSubwindowMode,
&values);
XCopyArea (xdisplay,
xroot, pixmap, gc,
geometry.x, geometry.y,
geometry.width, geometry.height,
0, 0);
XFreeGC (xdisplay, gc);
return pixmap;
}
/**
* meta_background_load_still_frame:
* @self: the #MetaBackground
*
* Takes a screenshot of the desktop and uses it as the background
* source.
*/
void
meta_background_load_still_frame (MetaBackground *self)
{
MetaBackgroundPrivate *priv = self->priv;
MetaDisplay *display = meta_screen_get_display (priv->screen);
Pixmap still_frame;
CoglTexture *texture;
CoglContext *context = clutter_backend_get_cogl_context (clutter_get_default_backend ());
GError *error = NULL;
ensure_pipeline (self);
unset_texture (self);
set_style (self, G_DESKTOP_BACKGROUND_STYLE_STRETCHED);
still_frame = get_still_frame_for_monitor (priv->screen, priv->monitor);
XSync (meta_display_get_xdisplay (display), False);
meta_error_trap_push (display);
texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (context, still_frame, FALSE, &error));
meta_error_trap_pop (display);
if (error != NULL)
{
g_warning ("Failed to create background texture from pixmap: %s",
error->message);
g_error_free (error);
return;
}
set_texture (self, texture);
}
/**
* meta_background_load_gradient:
* @self: the #MetaBackground

View File

@ -702,6 +702,7 @@ static gboolean
meta_window_actor_has_shadow (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
MetaWindowType window_type = meta_window_get_window_type (priv->window);
if (priv->no_shadow)
return FALSE;
@ -740,6 +741,25 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
if (priv->window->override_redirect)
return TRUE;
/*
* Don't put shadow around DND icon windows
*/
if (window_type == META_WINDOW_DND ||
window_type == META_WINDOW_DESKTOP)
return FALSE;
if (window_type == META_WINDOW_MENU
#if 0
|| window_type == META_WINDOW_DROPDOWN_MENU
#endif
)
return TRUE;
#if 0
if (window_type == META_WINDOW_TOOLTIP)
return TRUE;
#endif
return FALSE;
}

View File

@ -92,7 +92,6 @@ struct _MetaDisplay
Display *xdisplay;
int clutter_event_filter;
GSource *x11_event_source;
Window leader_window;
Window timestamp_pinging_window;
@ -148,10 +147,13 @@ struct _MetaDisplay
guint focused_by_us : 1;
/*< private-ish >*/
guint error_trap_synced_at_last_pop : 1;
MetaScreen *screen;
GHashTable *xids;
GHashTable *wayland_windows;
int error_traps;
int (* error_trap_handler) (Display *display,
XErrorEvent *error);
int server_grab_count;
/* serials of leave/unmap events that may
@ -254,8 +256,6 @@ struct _MetaDisplay
/* Closing down the display */
int closing;
GSList *error_traps;
/* Managed by group.c */
GHashTable *groups_by_leader;

View File

@ -446,7 +446,7 @@ meta_display_open (void)
meta_verbose ("Opening display '%s'\n", XDisplayName (NULL));
xdisplay = XOpenDisplay (NULL);
xdisplay = meta_ui_get_display ();
if (xdisplay == NULL)
{
@ -472,6 +472,9 @@ meta_display_open (void)
*/
the_display->name = g_strdup (XDisplayName (NULL));
the_display->xdisplay = xdisplay;
the_display->error_trap_synced_at_last_pop = TRUE;
the_display->error_traps = 0;
the_display->error_trap_handler = NULL;
the_display->server_grab_count = 0;
the_display->display_opening = TRUE;
@ -832,7 +835,7 @@ meta_display_open (void)
* now it always manages exactly one screen as specified by the DISPLAY
* environment variable.
*/
i = DefaultScreen (the_display->xdisplay);
i = meta_ui_get_screen_number ();
screen = meta_screen_new (the_display, i, timestamp);
if (!screen)
@ -1013,6 +1016,9 @@ meta_display_close (MetaDisplay *display,
return;
}
if (display->error_traps > 0)
meta_bug ("Display closed with error traps pending\n");
display->closing += 1;
meta_prefs_remove_listener (prefs_changed_callback, display);
@ -2206,7 +2212,7 @@ meta_change_button_grab (MetaDisplay *display,
mods = (XIGrabModifiers) { modmask | ignored_mask, 0 };
if (meta_is_debugging ())
meta_error_trap_push (display);
meta_error_trap_push_with_return (display);
/* GrabModeSync means freeze until XAllowEvents */

View File

@ -1,8 +1,9 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
/*
* Copyright (C) 2001 Havoc Pennington, error trapping inspired by GDK
* code copyrighted by the GTK team.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
@ -12,11 +13,9 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/**
@ -28,250 +27,42 @@
#include <config.h>
#include <meta/errors.h>
#include "display-private.h"
#include <errno.h>
#include <stdlib.h>
#include <gdk/gdk.h>
/* This is a copy-paste of the error handling code in GDK, modified
* so that it works with mutter's internal structures, since we don't
* have a GDK display open. */
/* compare X sequence numbers handling wraparound */
#define SEQUENCE_COMPARE(a,op,b) (((long) (a) - (long) (b)) op 0)
typedef struct _GdkErrorTrap GdkErrorTrap;
struct _GdkErrorTrap
{
/* Next sequence when trap was pushed, i.e. first sequence to
* ignore
*/
gulong start_sequence;
/* Next sequence when trap was popped, i.e. first sequence
* to not ignore. 0 if trap is still active.
*/
gulong end_sequence;
/* Most recent error code within the sequence */
int error_code;
};
/* delivers an error event from the error handler in gdkmain-x11.c */
static void
meta_display_error_event (MetaDisplay *display,
XErrorEvent *error)
{
GSList *tmp_list;
gboolean ignore;
ignore = FALSE;
for (tmp_list = display->error_traps;
tmp_list != NULL;
tmp_list = tmp_list->next)
{
GdkErrorTrap *trap;
trap = tmp_list->data;
if (SEQUENCE_COMPARE (trap->start_sequence, <=, error->serial) &&
(trap->end_sequence == 0 ||
SEQUENCE_COMPARE (trap->end_sequence, >, error->serial)))
{
ignore = TRUE;
trap->error_code = error->error_code;
break; /* only innermost trap gets the error code */
}
}
if (!ignore)
{
gchar buf[64];
gchar *msg;
XGetErrorText (display->xdisplay, error->error_code, buf, 63);
msg =
g_strdup_printf ("mutter received an X Window System error: %s\n"
" (Details: serial %ld error_code %d request_code %d minor_code %d)\n",
buf,
error->serial,
error->error_code,
error->request_code,
error->minor_code);
g_error ("%s", msg);
}
}
static int
gdk_x_error (Display *xdisplay,
XErrorEvent *error)
{
MetaDisplay *display = meta_display_for_x_display (xdisplay);
meta_display_error_event (display, error);
return 0;
}
/* non-GDK previous error handler */
typedef int (*GdkXErrorHandler) (Display *, XErrorEvent *);
static GdkXErrorHandler _gdk_old_error_handler;
/* number of times we've pushed the GDK error handler */
static int _gdk_error_handler_push_count = 0;
static void
_gdk_x11_error_handler_push (void)
{
GdkXErrorHandler previous;
previous = XSetErrorHandler (gdk_x_error);
if (_gdk_error_handler_push_count > 0)
{
if (previous != gdk_x_error)
g_warning ("XSetErrorHandler() called with a GDK error trap pushed. Don't do that.");
}
else
{
_gdk_old_error_handler = previous;
}
_gdk_error_handler_push_count += 1;
}
static void
_gdk_x11_error_handler_pop (void)
{
g_return_if_fail (_gdk_error_handler_push_count > 0);
_gdk_error_handler_push_count -= 1;
if (_gdk_error_handler_push_count == 0)
{
XSetErrorHandler (_gdk_old_error_handler);
_gdk_old_error_handler = NULL;
}
}
static void
delete_outdated_error_traps (MetaDisplay *display)
{
GSList *tmp_list;
gulong processed_sequence;
processed_sequence = XLastKnownRequestProcessed (display->xdisplay);
tmp_list = display->error_traps;
while (tmp_list != NULL)
{
GdkErrorTrap *trap = tmp_list->data;
if (trap->end_sequence != 0 &&
SEQUENCE_COMPARE (trap->end_sequence, <=, processed_sequence))
{
GSList *free_me = tmp_list;
tmp_list = tmp_list->next;
display->error_traps = g_slist_delete_link (display->error_traps, free_me);
g_slice_free (GdkErrorTrap, trap);
}
else
{
tmp_list = tmp_list->next;
}
}
}
/* In GTK+-3.0, the error trapping code was significantly rewritten. The new code
* has some neat features (like knowing automatically if a sync is needed or not
* and handling errors asynchronously when the error code isn't needed immediately),
* but it's basically incompatible with the hacks we played with GTK+-2.0 to
* use a custom error handler along with gdk_error_trap_push().
*
* Since the main point of our custom error trap was to get the error logged
* to the right place, with GTK+-3.0 we simply omit our own error handler and
* use the GTK+ handling straight-up.
* (See https://bugzilla.gnome.org/show_bug.cgi?id=630216 for restoring logging.)
*/
void
meta_error_trap_push (MetaDisplay *display)
{
GdkErrorTrap *trap;
delete_outdated_error_traps (display);
/* set up the Xlib callback to tell us about errors */
_gdk_x11_error_handler_push ();
trap = g_slice_new0 (GdkErrorTrap);
trap->start_sequence = XNextRequest (display->xdisplay);
trap->error_code = Success;
display->error_traps =
g_slist_prepend (display->error_traps, trap);
}
static gint
meta_error_trap_pop_internal (MetaDisplay *display,
gboolean need_code)
{
GdkErrorTrap *trap;
GSList *tmp_list;
int result;
g_return_val_if_fail (display->error_traps != NULL, Success);
/* Find the first trap that hasn't been popped already */
trap = NULL; /* quiet gcc */
for (tmp_list = display->error_traps;
tmp_list != NULL;
tmp_list = tmp_list->next)
{
trap = tmp_list->data;
if (trap->end_sequence == 0)
break;
}
g_return_val_if_fail (trap != NULL, Success);
g_assert (trap->end_sequence == 0);
/* May need to sync to fill in trap->error_code if we care about
* getting an error code.
*/
if (need_code)
{
gulong processed_sequence;
gulong next_sequence;
next_sequence = XNextRequest (display->xdisplay);
processed_sequence = XLastKnownRequestProcessed (display->xdisplay);
/* If our last request was already processed, there is no point
* in syncing. i.e. if last request was a round trip (or even if
* we got an event with the serial of a non-round-trip)
*/
if ((next_sequence - 1) != processed_sequence)
{
XSync (display->xdisplay, False);
}
result = trap->error_code;
}
else
{
result = Success;
}
/* record end of trap, giving us a range of
* error sequences we'll ignore.
*/
trap->end_sequence = XNextRequest (display->xdisplay);
/* remove the Xlib callback */
_gdk_x11_error_handler_pop ();
/* we may already be outdated */
delete_outdated_error_traps (display);
return result;
gdk_error_trap_push ();
}
void
meta_error_trap_pop (MetaDisplay *display)
{
meta_error_trap_pop_internal (display, FALSE);
gdk_error_trap_pop_ignored ();
}
void
meta_error_trap_push_with_return (MetaDisplay *display)
{
gdk_error_trap_push ();
}
int
meta_error_trap_pop_with_return (MetaDisplay *display)
{
return meta_error_trap_pop_internal (display, TRUE);
return gdk_error_trap_pop ();
}

View File

@ -39,7 +39,6 @@
#include "x11/window-x11.h"
#include "x11/xprops.h"
#include "wayland/meta-xwayland.h"
#include "wayland/meta-wayland-private.h"
#include "meta-surface-actor-wayland.h"
@ -78,8 +77,9 @@ get_input_event (MetaDisplay *display,
{
XIEvent *input_event;
XGetEventData (display->xdisplay, &event->xcookie);
/* NB: GDK event filters already have generic events
* allocated, so no need to do XGetEventData() on our own
*/
input_event = (XIEvent *) event->xcookie.data;
switch (input_event->evtype)
@ -859,17 +859,6 @@ handle_input_xevent (MetaDisplay *display,
if (input_event == NULL)
return FALSE;
switch (input_event->evtype)
{
case XI_Enter:
case XI_Leave:
case XI_FocusIn:
case XI_FocusOut:
break;
default:
return FALSE;
}
modified = xievent_get_modified_window (display, input_event);
window = modified != None ? meta_display_lookup_x_window (display, modified) : NULL;
@ -944,11 +933,12 @@ handle_input_xevent (MetaDisplay *display,
}
}
break;
/* Don't send FocusIn / FocusOut to Clutter */
return TRUE;
}
/* Don't pass these events through to Clutter / GTK+ */
return TRUE;
return FALSE;
}
static void
@ -1050,7 +1040,7 @@ convert_property (MetaDisplay *display,
conversion_targets[2] = display->atom_TIMESTAMP;
conversion_targets[3] = display->atom_VERSION;
meta_error_trap_push (display);
meta_error_trap_push_with_return (display);
if (target == display->atom_TARGETS)
XChangeProperty (display->xdisplay, w, property,
XA_ATOM, 32, PropModeReplace,
@ -1125,7 +1115,7 @@ process_selection_request (MetaDisplay *display,
unsigned long num, rest;
unsigned char *data;
meta_error_trap_push (display);
meta_error_trap_push_with_return (display);
if (XGetWindowProperty (display->xdisplay,
event->xselectionrequest.requestor,
event->xselectionrequest.property, 0, 256, False,
@ -1546,12 +1536,7 @@ handle_other_xevent (MetaDisplay *display,
case ClientMessage:
if (window)
{
if (event->xclient.message_type == display->atom_WL_SURFACE_ID)
{
guint32 surface_id = event->xclient.data.l[0];
meta_xwayland_handle_wl_surface_id (window, surface_id);
}
else if (!frame_was_receiver)
if (!frame_was_receiver)
meta_window_x11_client_message (window, event);
}
else
@ -1749,12 +1734,12 @@ window_has_xwindow (MetaWindow *window,
* busy around here. Most of this function is a ginormous switch statement
* dealing with all the kinds of events that might turn up.
*/
static void
static gboolean
meta_display_handle_xevent (MetaDisplay *display,
XEvent *event)
{
Window modified;
gboolean bypass_compositor = FALSE;
gboolean bypass_compositor = FALSE, bypass_gtk = FALSE;
XIEvent *input_event;
MetaMonitorManager *monitor;
@ -1763,13 +1748,13 @@ meta_display_handle_xevent (MetaDisplay *display,
#endif
#ifdef HAVE_STARTUP_NOTIFICATION
if (sn_display_process_event (display->sn_display, event))
{
bypass_compositor = TRUE;
goto out;
}
sn_display_process_event (display->sn_display, event);
#endif
/* Intercept XRandR events early and don't attempt any
processing for them. We still let them through to Gdk though,
so it can update its own internal state.
*/
monitor = meta_monitor_manager_get ();
if (meta_monitor_manager_handle_xevent (monitor, event))
{
@ -1798,7 +1783,7 @@ meta_display_handle_xevent (MetaDisplay *display,
{
if (meta_screen_handle_xevent (display->screen, event))
{
bypass_compositor = TRUE;
bypass_gtk = bypass_compositor = TRUE;
goto out;
}
}
@ -1809,9 +1794,8 @@ meta_display_handle_xevent (MetaDisplay *display,
if (event->type == UnmapNotify)
{
MetaUI *ui = display->screen->ui;
if (meta_ui_window_should_not_cause_focus (ui, modified))
if (meta_ui_window_should_not_cause_focus (display->xdisplay,
modified))
{
meta_display_add_ignored_crossing_serial (display, event->xany.serial);
meta_topic (META_DEBUG_FOCUS,
@ -1833,7 +1817,7 @@ meta_display_handle_xevent (MetaDisplay *display,
#ifdef HAVE_XI23
if (meta_display_process_barrier_event (display, input_event))
{
bypass_compositor = TRUE;
bypass_gtk = bypass_compositor = TRUE;
goto out;
}
#endif /* HAVE_XI23 */
@ -1844,20 +1828,27 @@ meta_display_handle_xevent (MetaDisplay *display,
*/
if (handle_input_xevent (display, input_event, event->xany.serial))
{
bypass_compositor = TRUE;
bypass_gtk = bypass_compositor = TRUE;
goto out;
}
if (handle_other_xevent (display, event))
goto out;
{
bypass_gtk = TRUE;
goto out;
}
out:
if (!bypass_compositor)
{
MetaWindow *window = modified != None ? meta_display_lookup_x_window (display, modified) : NULL;
meta_compositor_process_event (display->compositor, event, window);
if (meta_compositor_process_event (display->compositor, event, window))
bypass_gtk = TRUE;
}
display->current_time = CurrentTime;
return bypass_gtk;
}
static void
@ -2168,6 +2159,19 @@ meta_display_handle_event (MetaDisplay *display,
return bypass_clutter;
}
static GdkFilterReturn
xevent_filter (GdkXEvent *xevent,
GdkEvent *event,
gpointer data)
{
MetaDisplay *display = data;
if (meta_display_handle_xevent (display, xevent))
return GDK_FILTER_REMOVE;
else
return GDK_FILTER_CONTINUE;
}
static gboolean
event_callback (const ClutterEvent *event,
gpointer data)
@ -2177,90 +2181,20 @@ event_callback (const ClutterEvent *event,
return meta_display_handle_event (display, event);
}
typedef struct {
GSource source;
MetaDisplay *display;
GPollFD event_poll_fd;
} X11EventSource;
static gboolean
x11_event_source_prepare (GSource *source,
gint *timeout)
{
X11EventSource *source_x11 = (X11EventSource *) source;
MetaDisplay *display = source_x11->display;
*timeout = -1;
return XPending (display->xdisplay);
}
static gboolean
x11_event_source_check (GSource *source)
{
X11EventSource *source_x11 = (X11EventSource *) source;
MetaDisplay *display = source_x11->display;
if (source_x11->event_poll_fd.revents & G_IO_IN)
return XPending (display->xdisplay);
else
return FALSE;
}
static gboolean
x11_event_source_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
X11EventSource *source_x11 = (X11EventSource *) source;
MetaDisplay *display = source_x11->display;
XEvent event;
XNextEvent (display->xdisplay, &event);
meta_display_handle_xevent (display, &event);
return TRUE;
}
static GSourceFuncs x11_event_source_funcs = {
x11_event_source_prepare,
x11_event_source_check,
x11_event_source_dispatch,
};
static GSource *
x11_event_source_new (MetaDisplay *display)
{
GSource *source = g_source_new (&x11_event_source_funcs, sizeof (X11EventSource));
X11EventSource *source_x11 = (X11EventSource *) source;
source_x11->display = display;
source_x11->event_poll_fd.fd = ConnectionNumber (display->xdisplay);
source_x11->event_poll_fd.events = G_IO_IN;
g_source_add_poll (source, &source_x11->event_poll_fd);
return source;
}
void
meta_display_init_events (MetaDisplay *display)
{
gdk_window_add_filter (NULL, xevent_filter, display);
display->clutter_event_filter = clutter_event_add_filter (NULL,
event_callback,
NULL,
display);
display->x11_event_source = x11_event_source_new (display);
g_source_attach (display->x11_event_source, NULL);
}
void
meta_display_free_events (MetaDisplay *display)
{
gdk_window_remove_filter (NULL, xevent_filter, display);
clutter_event_remove_filter (display->clutter_event_filter);
display->clutter_event_filter = 0;
g_source_unref (display->x11_event_source);
display->x11_event_source = NULL;
}

View File

@ -92,6 +92,7 @@ meta_window_ensure_frame (MetaWindow *window)
visual = NULL;
frame->xwindow = meta_ui_create_frame_window (window->screen->ui,
window->display->xdisplay,
visual,
frame->rect.x,
frame->rect.y,

View File

@ -1065,7 +1065,7 @@ meta_change_keygrab (MetaDisplay *display,
mods = (XIGrabModifiers) { modmask | ignored_mask, 0 };
if (meta_is_debugging ())
meta_error_trap_push (display);
meta_error_trap_push_with_return (display);
if (grab)
XIGrabKeycode (display->xdisplay,
META_VIRTUAL_CORE_KEYBOARD_ID,
@ -1410,7 +1410,7 @@ grab_keyboard (MetaDisplay *display,
/* Grab the keyboard, so we get key releases and all key
* presses
*/
meta_error_trap_push (display);
meta_error_trap_push_with_return (display);
/* Strictly, we only need to set grab_mode on the keyboard device
* while the pointer should always be XIGrabModeAsync. Unfortunately

View File

@ -560,7 +560,7 @@ meta_screen_new (MetaDisplay *display,
}
/* We want to find out when the current selection owner dies */
meta_error_trap_push (display);
meta_error_trap_push_with_return (display);
attrs.event_mask = StructureNotifyMask;
XChangeWindowAttributes (xdisplay,
current_wm_sn_owner, CWEventMask, &attrs);
@ -619,7 +619,7 @@ meta_screen_new (MetaDisplay *display,
}
/* select our root window events */
meta_error_trap_push (display);
meta_error_trap_push_with_return (display);
/* We need to or with the existing event mask since
* gtk+ may be interested in other events.
@ -757,7 +757,8 @@ meta_screen_new (MetaDisplay *display,
screen->keys_grabbed = FALSE;
meta_screen_grab_keys (screen);
screen->ui = meta_ui_new ();
screen->ui = meta_ui_new (screen->display->xdisplay,
screen->xscreen);
screen->tile_preview_timeout_id = 0;
@ -837,7 +838,7 @@ meta_screen_free (MetaScreen *screen,
meta_stack_free (screen->stack);
meta_stack_tracker_free (screen->stack_tracker);
meta_error_trap_push (screen->display);
meta_error_trap_push_with_return (screen->display);
XSelectInput (screen->display->xdisplay, screen->xroot, 0);
if (meta_error_trap_pop_with_return (screen->display) != Success)
meta_warning ("Could not release screen %d on display \"%s\"\n",

View File

@ -1468,7 +1468,7 @@ meta_window_unmanage (MetaWindow *window,
/* This needs to happen for both Wayland and XWayland clients,
* so it can't be in MetaWindowWayland. */
if (window->surface)
meta_wayland_surface_set_window (window->surface, NULL);
meta_wayland_surface_window_unmanaged (window->surface);
if (window->visible_to_compositor)
{
@ -3953,7 +3953,7 @@ meta_window_create_sync_request_alarm (MetaWindow *window)
window->sync_request_alarm != None)
return;
meta_error_trap_push (window->display);
meta_error_trap_push_with_return (window->display);
/* In the new (extended style), the counter value is initialized by
* the client before mapping the window. In the old style, we're
@ -8038,7 +8038,7 @@ warp_grab_pointer (MetaWindow *window,
*x = CLAMP (*x, 0, window->screen->rect.width-1);
*y = CLAMP (*y, 0, window->screen->rect.height-1);
meta_error_trap_push (display);
meta_error_trap_push_with_return (display);
meta_topic (META_DEBUG_WINDOW_OPS,
"Warping pointer to %d,%d with window at %d,%d\n",

View File

@ -81,7 +81,6 @@ item(ATOM_PAIR)
item(BACKLIGHT)
item(_XKB_RULES_NAMES)
item(hotplug_mode_update)
item(WL_SURFACE_ID)
/* Oddities: These are used, and we need atoms for them,
* but when we need all _NET_WM hints (i.e. when we're making

View File

@ -30,6 +30,7 @@
void meta_error_trap_push (MetaDisplay *display);
void meta_error_trap_pop (MetaDisplay *display);
void meta_error_trap_push_with_return (MetaDisplay *display);
/* returns X error code, or 0 for no error */
int meta_error_trap_pop_with_return (MetaDisplay *display);

View File

@ -91,6 +91,7 @@ void meta_background_load_gradient (MetaBackground *self,
ClutterColor *second_color);
void meta_background_load_color (MetaBackground *self,
ClutterColor *color);
void meta_background_load_still_frame (MetaBackground *self);
void meta_background_load_file_async (MetaBackground *self,
const char *filename,
GDesktopBackgroundStyle style,

View File

@ -39,9 +39,8 @@ static void meta_ui_accelerator_parse (const char *accel,
struct _MetaUI
{
GdkDisplay *display;
GdkScreen *screen;
Display *xdisplay;
Screen *xscreen;
MetaFrames *frames;
/* For double-click tracking */
@ -61,17 +60,202 @@ meta_ui_init (void)
meta_fatal ("Unable to open X display %s\n", XDisplayName (NULL));
}
MetaUI*
meta_ui_new (void)
Display*
meta_ui_get_display (void)
{
return GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
}
gint
meta_ui_get_screen_number (void)
{
return gdk_screen_get_number (gdk_screen_get_default ());
}
/* For XInput2 */
#include "display-private.h"
static gboolean
is_input_event (XEvent *event)
{
MetaDisplay *display = meta_get_display ();
return (event->type == GenericEvent &&
event->xcookie.extension == display->xinput_opcode);
}
/* We do some of our event handling in frames.c, which expects
* GDK events delivered by GTK+. However, since the transition to
* client side windows, we can't let GDK see button events, since the
* client-side tracking of implicit and explicit grabs it does will
* get confused by our direct use of X grabs in the core code.
*
* So we do a very minimal GDK => GTK event conversion here and send on the
* events we care about, and then filter them out so they don't go
* through the normal GDK event handling.
*
* To reduce the amount of code, the only events fields filled out
* below are the ones that frames.c uses. If frames.c is modified to
* use more fields, more fields need to be filled out below.
*/
static gboolean
maybe_redirect_mouse_event (XEvent *xevent)
{
GdkDisplay *gdisplay;
GdkDeviceManager *gmanager;
GdkDevice *gdevice;
MetaUI *ui;
GdkEvent *gevent;
GdkWindow *gdk_window;
Window window;
XIEvent *xev;
XIDeviceEvent *xev_d = NULL;
XIEnterEvent *xev_e = NULL;
if (!is_input_event (xevent))
return FALSE;
xev = (XIEvent *) xevent->xcookie.data;
switch (xev->evtype)
{
case XI_ButtonPress:
case XI_ButtonRelease:
case XI_Motion:
xev_d = (XIDeviceEvent *) xev;
window = xev_d->event;
break;
case XI_Enter:
case XI_Leave:
xev_e = (XIEnterEvent *) xev;
window = xev_e->event;
break;
default:
return FALSE;
}
gdisplay = gdk_x11_lookup_xdisplay (xev->display);
ui = g_object_get_data (G_OBJECT (gdisplay), "meta-ui");
if (!ui)
return FALSE;
gdk_window = gdk_x11_window_lookup_for_display (gdisplay, window);
if (gdk_window == NULL)
return FALSE;
gmanager = gdk_display_get_device_manager (gdisplay);
gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID);
/* If GDK already thinks it has a grab, we better let it see events; this
* is the menu-navigation case and events need to get sent to the appropriate
* (client-side) subwindow for individual menu items.
*/
if (gdk_display_device_is_grabbed (gdisplay, gdevice))
return FALSE;
switch (xev->evtype)
{
case XI_ButtonPress:
case XI_ButtonRelease:
if (xev_d->evtype == XI_ButtonPress)
{
GtkSettings *settings = gtk_settings_get_default ();
int double_click_time;
int double_click_distance;
g_object_get (settings,
"gtk-double-click-time", &double_click_time,
"gtk-double-click-distance", &double_click_distance,
NULL);
if (xev_d->detail == ui->button_click_number &&
xev_d->event == ui->button_click_window &&
xev_d->time < ui->button_click_time + double_click_time &&
ABS (xev_d->event_x - ui->button_click_x) <= double_click_distance &&
ABS (xev_d->event_y - ui->button_click_y) <= double_click_distance)
{
gevent = gdk_event_new (GDK_2BUTTON_PRESS);
ui->button_click_number = 0;
}
else
{
gevent = gdk_event_new (GDK_BUTTON_PRESS);
ui->button_click_number = xev_d->detail;
ui->button_click_window = xev_d->event;
ui->button_click_time = xev_d->time;
ui->button_click_x = xev_d->event_x;
ui->button_click_y = xev_d->event_y;
}
}
else
{
gevent = gdk_event_new (GDK_BUTTON_RELEASE);
}
gevent->button.window = g_object_ref (gdk_window);
gevent->button.button = xev_d->detail;
gevent->button.time = xev_d->time;
gevent->button.x = xev_d->event_x;
gevent->button.y = xev_d->event_y;
gevent->button.x_root = xev_d->root_x;
gevent->button.y_root = xev_d->root_y;
break;
case XI_Motion:
gevent = gdk_event_new (GDK_MOTION_NOTIFY);
gevent->motion.type = GDK_MOTION_NOTIFY;
gevent->motion.window = g_object_ref (gdk_window);
break;
case XI_Enter:
case XI_Leave:
gevent = gdk_event_new (xev_e->evtype == XI_Enter ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY);
gevent->crossing.window = g_object_ref (gdk_window);
gevent->crossing.x = xev_e->event_x;
gevent->crossing.y = xev_e->event_y;
break;
default:
g_assert_not_reached ();
break;
}
/* If we've gotten here, we've created the gdk_event and should send it on */
gdk_event_set_device (gevent, gdevice);
gtk_main_do_event (gevent);
gdk_event_free (gevent);
return TRUE;
}
static GdkFilterReturn
ui_filter_func (GdkXEvent *xevent,
GdkEvent *event,
gpointer data)
{
if (maybe_redirect_mouse_event (xevent))
return GDK_FILTER_REMOVE;
else
return GDK_FILTER_CONTINUE;
}
MetaUI*
meta_ui_new (Display *xdisplay,
Screen *screen)
{
GdkDisplay *gdisplay;
MetaUI *ui;
ui = g_new0 (MetaUI, 1);
ui->display = gdk_display_get_default ();
ui->screen = gdk_screen_get_default ();
ui->xdisplay = xdisplay;
ui->xscreen = screen;
ui->frames = meta_frames_new (gdk_screen_get_number (ui->screen));
gdisplay = gdk_x11_lookup_xdisplay (xdisplay);
g_assert (gdisplay == gdk_display_get_default ());
gdk_window_add_filter (NULL, ui_filter_func, NULL);
ui->frames = meta_frames_new (XScreenNumberOfScreen (screen));
/* GTK+ needs the frame-sync protocol to work in order to properly
* handle style changes. This means that the dummy widget we create
* to get the style for title bars actually needs to be mapped
@ -80,14 +264,25 @@ meta_ui_new (void)
*/
gtk_widget_show (GTK_WIDGET (ui->frames));
gdk_window_add_filter (NULL, ui_filter_func, NULL);
g_object_set_data (G_OBJECT (gdisplay), "meta-ui", ui);
return ui;
}
void
meta_ui_free (MetaUI *ui)
{
GdkDisplay *gdisplay;
gtk_widget_destroy (GTK_WIDGET (ui->frames));
gdisplay = gdk_x11_lookup_xdisplay (ui->xdisplay);
g_object_set_data (G_OBJECT (gdisplay), "meta-ui", NULL);
gdk_window_remove_filter (NULL, ui_filter_func, NULL);
g_free (ui);
}
@ -112,6 +307,7 @@ meta_ui_get_frame_borders (MetaUI *ui,
Window
meta_ui_create_frame_window (MetaUI *ui,
Display *xdisplay,
Visual *xvisual,
gint x,
gint y,
@ -120,7 +316,7 @@ meta_ui_create_frame_window (MetaUI *ui,
gint screen_no,
gulong *create_serial)
{
GdkDisplay *display = ui->display;
GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
GdkScreen *screen = gdk_display_get_screen (display, screen_no);
GdkWindowAttr attrs;
gint attributes_mask;
@ -169,7 +365,7 @@ meta_ui_create_frame_window (MetaUI *ui,
* as long as you pass in a colormap.
*/
if (create_serial)
*create_serial = XNextRequest (GDK_DISPLAY_XDISPLAY (display));
*create_serial = XNextRequest (xdisplay);
window =
gdk_window_new (gdk_screen_get_root_window(screen),
&attrs, attributes_mask);
@ -203,9 +399,10 @@ void
meta_ui_map_frame (MetaUI *ui,
Window xwindow)
{
GdkDisplay *display = ui->display;
GdkWindow *window;
GdkDisplay *display;
display = gdk_x11_lookup_xdisplay (ui->xdisplay);
window = gdk_x11_window_lookup_for_display (display, xwindow);
if (window)
@ -216,9 +413,10 @@ void
meta_ui_unmap_frame (MetaUI *ui,
Window xwindow)
{
GdkDisplay *display = ui->display;
GdkWindow *window;
GdkDisplay *display;
display = gdk_x11_lookup_xdisplay (ui->xdisplay);
window = gdk_x11_window_lookup_for_display (display, xwindow);
if (window)
@ -436,13 +634,13 @@ meta_ui_get_default_mini_icon (MetaUI *ui)
}
gboolean
meta_ui_window_should_not_cause_focus (MetaUI *ui,
Window xwindow)
meta_ui_window_should_not_cause_focus (Display *xdisplay,
Window xwindow)
{
GdkWindow *window;
GdkDisplay *display;
display = ui->display;
display = gdk_x11_lookup_xdisplay (xdisplay);
window = gdk_x11_window_lookup_for_display (display, xwindow);
/* we shouldn't cause focus if we're an override redirect
@ -454,6 +652,38 @@ meta_ui_window_should_not_cause_focus (MetaUI *ui,
return FALSE;
}
char*
meta_text_property_to_utf8 (Display *xdisplay,
const XTextProperty *prop)
{
GdkDisplay *display;
char **list;
int count;
char *retval;
list = NULL;
display = gdk_x11_lookup_xdisplay (xdisplay);
count = gdk_text_property_to_utf8_list_for_display (display,
gdk_x11_xatom_to_atom_for_display (display, prop->encoding),
prop->format,
prop->value,
prop->nitems,
&list);
if (count == 0)
retval = NULL;
else
{
retval = list[0];
list[0] = g_strdup (""); /* something to free */
}
g_strfreev (list);
return retval;
}
void
meta_ui_theme_get_frame_borders (MetaUI *ui,
MetaFrameType type,
@ -473,7 +703,8 @@ meta_ui_theme_get_frame_borders (MetaUI *ui,
if (!font_desc)
{
GdkScreen *screen = ui->screen;
GdkDisplay *display = gdk_x11_lookup_xdisplay (ui->xdisplay);
GdkScreen *screen = gdk_display_get_screen (display, XScreenNumberOfScreen (ui->xscreen));
GtkWidgetPath *widget_path;
style = gtk_style_context_new ();
@ -712,9 +943,10 @@ gboolean
meta_ui_window_is_widget (MetaUI *ui,
Window xwindow)
{
GdkDisplay *display = ui->display;
GdkDisplay *display;
GdkWindow *window;
display = gdk_x11_lookup_xdisplay (ui->xdisplay);
window = gdk_x11_window_lookup_for_display (display, xwindow);
if (window)

View File

@ -42,7 +42,12 @@ typedef enum
void meta_ui_init (void);
MetaUI* meta_ui_new (void);
Display* meta_ui_get_display (void);
gint meta_ui_get_screen_number (void);
MetaUI* meta_ui_new (Display *xdisplay,
Screen *screen);
void meta_ui_free (MetaUI *ui);
void meta_ui_theme_get_frame_borders (MetaUI *ui,
@ -60,6 +65,7 @@ void meta_ui_get_frame_mask (MetaUI *ui,
cairo_t *cr);
Window meta_ui_create_frame_window (MetaUI *ui,
Display *xdisplay,
Visual *xvisual,
gint x,
gint y,
@ -133,8 +139,11 @@ GdkPixbuf* meta_gdk_pixbuf_get_from_pixmap (Pixmap xpixmap,
GdkPixbuf* meta_ui_get_default_window_icon (MetaUI *ui);
GdkPixbuf* meta_ui_get_default_mini_icon (MetaUI *ui);
gboolean meta_ui_window_should_not_cause_focus (MetaUI *ui,
Window xwindow);
gboolean meta_ui_window_should_not_cause_focus (Display *xdisplay,
Window xwindow);
char* meta_text_property_to_utf8 (Display *xdisplay,
const XTextProperty *prop);
void meta_ui_set_current_theme (const char *name);
gboolean meta_ui_have_a_theme (void);

View File

@ -115,16 +115,8 @@ pointer_set_cursor (struct wl_client *client,
meta_wayland_seat_update_cursor_surface (seat);
}
static void
pointer_release (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static const struct wl_pointer_interface pointer_interface = {
pointer_set_cursor,
pointer_release,
pointer_set_cursor
};
static void
@ -145,17 +137,6 @@ seat_get_pointer (struct wl_client *client,
meta_wayland_pointer_set_focus (&seat->pointer, seat->pointer.focus_surface);
}
static void
keyboard_release (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static const struct wl_keyboard_interface keyboard_interface = {
keyboard_release,
};
static void
seat_get_keyboard (struct wl_client *client,
struct wl_resource *resource,

View File

@ -1,32 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef META_WAYLAND_SURFACE_PRIVATE_H
#define META_WAYLAND_SURFACE_PRIVATE_H
#include "meta-wayland-types.h"
void meta_wayland_surface_commit (MetaWaylandSurface *surface);
#endif /* META_WAYLAND_SURFACE_PRIVATE_H */

View File

@ -48,7 +48,6 @@
#include "meta-wayland-keyboard.h"
#include "meta-wayland-pointer.h"
#include "meta-wayland-data-device.h"
#include "meta-wayland-surface-private.h"
#include "meta-cursor-tracker-private.h"
#include "display-private.h"
@ -118,6 +117,132 @@ surface_process_damage (MetaWaylandSurface *surface,
}
}
static void
meta_wayland_surface_destroy (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static void
meta_wayland_surface_attach (struct wl_client *client,
struct wl_resource *surface_resource,
struct wl_resource *buffer_resource,
gint32 dx, gint32 dy)
{
MetaWaylandSurface *surface =
wl_resource_get_user_data (surface_resource);
MetaWaylandBuffer *buffer;
/* X11 unmanaged window */
if (!surface)
return;
if (buffer_resource)
buffer = meta_wayland_buffer_from_resource (buffer_resource);
else
buffer = NULL;
/* Attach without commit in between does not send wl_buffer.release */
if (surface->pending.buffer)
wl_list_remove (&surface->pending.buffer_destroy_listener.link);
surface->pending.dx = dx;
surface->pending.dy = dy;
surface->pending.buffer = buffer;
surface->pending.newly_attached = TRUE;
if (buffer)
wl_signal_add (&buffer->destroy_signal,
&surface->pending.buffer_destroy_listener);
}
static void
meta_wayland_surface_damage (struct wl_client *client,
struct wl_resource *surface_resource,
gint32 x,
gint32 y,
gint32 width,
gint32 height)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
cairo_rectangle_int_t rectangle = { x, y, width, height };
/* X11 unmanaged window */
if (!surface)
return;
cairo_region_union_rectangle (surface->pending.damage, &rectangle);
}
static void
destroy_frame_callback (struct wl_resource *callback_resource)
{
MetaWaylandFrameCallback *callback =
wl_resource_get_user_data (callback_resource);
wl_list_remove (&callback->link);
g_slice_free (MetaWaylandFrameCallback, callback);
}
static void
meta_wayland_surface_frame (struct wl_client *client,
struct wl_resource *surface_resource,
guint32 callback_id)
{
MetaWaylandFrameCallback *callback;
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
/* X11 unmanaged window */
if (!surface)
return;
callback = g_slice_new0 (MetaWaylandFrameCallback);
callback->compositor = surface->compositor;
callback->resource = wl_resource_create (client, &wl_callback_interface, META_WL_CALLBACK_VERSION, callback_id);
wl_resource_set_implementation (callback->resource, NULL, callback, destroy_frame_callback);
wl_list_insert (surface->pending.frame_callback_list.prev, &callback->link);
}
static void
meta_wayland_surface_set_opaque_region (struct wl_client *client,
struct wl_resource *surface_resource,
struct wl_resource *region_resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
/* X11 unmanaged window */
if (!surface)
return;
g_clear_pointer (&surface->pending.opaque_region, cairo_region_destroy);
if (region_resource)
{
MetaWaylandRegion *region = wl_resource_get_user_data (region_resource);
surface->pending.opaque_region = cairo_region_copy (region->region);
}
}
static void
meta_wayland_surface_set_input_region (struct wl_client *client,
struct wl_resource *surface_resource,
struct wl_resource *region_resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
/* X11 unmanaged window */
if (!surface)
return;
g_clear_pointer (&surface->pending.input_region, cairo_region_destroy);
if (region_resource)
{
MetaWaylandRegion *region = wl_resource_get_user_data (region_resource);
surface->pending.input_region = cairo_region_copy (region->region);
}
}
static void
empty_region (cairo_region_t *region)
{
@ -145,37 +270,22 @@ ensure_buffer_texture (MetaWaylandBuffer *buffer)
buffer->texture = texture;
}
static gboolean
commit_attached_surface (MetaWaylandSurface *surface,
MetaWaylandDoubleBufferedState *pending)
{
/* wl_surface.attach */
if (pending->newly_attached && surface->buffer != pending->buffer)
{
surface_set_buffer (surface, pending->buffer);
return TRUE;
}
else
return FALSE;
}
static void
cursor_surface_commit (MetaWaylandSurface *surface,
MetaWaylandDoubleBufferedState *pending)
MetaWaylandDoubleBufferedState *pending,
gboolean buffer_changed)
{
if (commit_attached_surface (surface, pending))
if (buffer_changed)
meta_wayland_seat_update_cursor_surface (surface->compositor->seat);
}
static gboolean
static void
actor_surface_commit (MetaWaylandSurface *surface,
MetaWaylandDoubleBufferedState *pending)
MetaWaylandDoubleBufferedState *pending,
gboolean buffer_changed)
{
MetaSurfaceActor *surface_actor = surface->surface_actor;
MetaWaylandBuffer *buffer = pending->buffer;
gboolean buffer_changed;
buffer_changed = commit_attached_surface (surface, pending);
if (buffer_changed && buffer)
{
@ -189,15 +299,16 @@ actor_surface_commit (MetaWaylandSurface *surface,
meta_surface_actor_set_opaque_region (surface_actor, pending->opaque_region);
if (pending->input_region)
meta_surface_actor_set_input_region (surface_actor, pending->input_region);
return buffer_changed;
}
static void
toplevel_surface_commit (MetaWaylandSurface *surface,
MetaWaylandDoubleBufferedState *pending)
MetaWaylandDoubleBufferedState *pending,
gboolean buffer_changed)
{
if (actor_surface_commit (surface, pending))
actor_surface_commit (surface, pending, buffer_changed);
if (buffer_changed)
{
MetaWindow *window = surface->window;
MetaWaylandBuffer *buffer = pending->buffer;
@ -306,7 +417,8 @@ move_double_buffered_state (MetaWaylandDoubleBufferedState *from,
static void
subsurface_surface_commit (MetaWaylandSurface *surface,
MetaWaylandDoubleBufferedState *pending)
MetaWaylandDoubleBufferedState *pending,
gboolean buffer_changed)
{
/*
* If the sub-surface is in synchronous mode, post-pone the commit of its
@ -326,7 +438,9 @@ subsurface_surface_commit (MetaWaylandSurface *surface,
}
else
{
if (actor_surface_commit (surface, pending))
actor_surface_commit (surface, pending, buffer_changed);
if (buffer_changed)
{
MetaSurfaceActor *surface_actor = surface->surface_actor;
MetaWaylandBuffer *buffer = pending->buffer;
@ -359,21 +473,21 @@ commit_double_buffered_state (MetaWaylandSurface *surface,
MetaWaylandDoubleBufferedState *pending)
{
MetaWaylandCompositor *compositor = surface->compositor;
gboolean buffer_changed = FALSE;
/* wl_surface.attach */
if (pending->newly_attached && surface->buffer != pending->buffer)
{
surface_set_buffer (surface, pending->buffer);
buffer_changed = TRUE;
}
if (surface == compositor->seat->cursor_surface)
cursor_surface_commit (surface, pending);
cursor_surface_commit (surface, pending, buffer_changed);
else if (surface->window)
toplevel_surface_commit (surface, pending);
toplevel_surface_commit (surface, pending, buffer_changed);
else if (surface->subsurface.resource)
subsurface_surface_commit (surface, pending);
else
{
/* Unknown surface type. In this case, it's most likely a XWayland
* surface that we haven't gotten the ClientMessage for yet. Make
* sure *not* to reset the double-buffered state or do anything too
* fancy. */
return;
}
subsurface_surface_commit (surface, pending, buffer_changed);
g_list_foreach (surface->subsurfaces,
parent_surface_committed,
@ -392,141 +506,9 @@ commit_double_buffered_state (MetaWaylandSurface *surface,
double_buffered_state_reset (pending);
}
void
meta_wayland_surface_commit (MetaWaylandSurface *surface)
{
commit_double_buffered_state (surface, &surface->pending);
}
static void
wl_surface_destroy (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static void
wl_surface_attach (struct wl_client *client,
struct wl_resource *surface_resource,
struct wl_resource *buffer_resource,
gint32 dx, gint32 dy)
{
MetaWaylandSurface *surface =
wl_resource_get_user_data (surface_resource);
MetaWaylandBuffer *buffer;
/* X11 unmanaged window */
if (!surface)
return;
if (buffer_resource)
buffer = meta_wayland_buffer_from_resource (buffer_resource);
else
buffer = NULL;
/* Attach without commit in between does not send wl_buffer.release */
if (surface->pending.buffer)
wl_list_remove (&surface->pending.buffer_destroy_listener.link);
surface->pending.dx = dx;
surface->pending.dy = dy;
surface->pending.buffer = buffer;
surface->pending.newly_attached = TRUE;
if (buffer)
wl_signal_add (&buffer->destroy_signal,
&surface->pending.buffer_destroy_listener);
}
static void
wl_surface_damage (struct wl_client *client,
struct wl_resource *surface_resource,
gint32 x,
gint32 y,
gint32 width,
gint32 height)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
cairo_rectangle_int_t rectangle = { x, y, width, height };
/* X11 unmanaged window */
if (!surface)
return;
cairo_region_union_rectangle (surface->pending.damage, &rectangle);
}
static void
destroy_frame_callback (struct wl_resource *callback_resource)
{
MetaWaylandFrameCallback *callback =
wl_resource_get_user_data (callback_resource);
wl_list_remove (&callback->link);
g_slice_free (MetaWaylandFrameCallback, callback);
}
static void
wl_surface_frame (struct wl_client *client,
struct wl_resource *surface_resource,
guint32 callback_id)
{
MetaWaylandFrameCallback *callback;
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
/* X11 unmanaged window */
if (!surface)
return;
callback = g_slice_new0 (MetaWaylandFrameCallback);
callback->compositor = surface->compositor;
callback->resource = wl_resource_create (client, &wl_callback_interface, META_WL_CALLBACK_VERSION, callback_id);
wl_resource_set_implementation (callback->resource, NULL, callback, destroy_frame_callback);
wl_list_insert (surface->pending.frame_callback_list.prev, &callback->link);
}
static void
wl_surface_set_opaque_region (struct wl_client *client,
struct wl_resource *surface_resource,
struct wl_resource *region_resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
/* X11 unmanaged window */
if (!surface)
return;
g_clear_pointer (&surface->pending.opaque_region, cairo_region_destroy);
if (region_resource)
{
MetaWaylandRegion *region = wl_resource_get_user_data (region_resource);
surface->pending.opaque_region = cairo_region_copy (region->region);
}
}
static void
wl_surface_set_input_region (struct wl_client *client,
struct wl_resource *surface_resource,
struct wl_resource *region_resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
/* X11 unmanaged window */
if (!surface)
return;
g_clear_pointer (&surface->pending.input_region, cairo_region_destroy);
if (region_resource)
{
MetaWaylandRegion *region = wl_resource_get_user_data (region_resource);
surface->pending.input_region = cairo_region_copy (region->region);
}
}
static void
wl_surface_commit (struct wl_client *client,
struct wl_resource *resource)
meta_wayland_surface_commit (struct wl_client *client,
struct wl_resource *resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
@ -534,46 +516,49 @@ wl_surface_commit (struct wl_client *client,
if (!surface)
return;
meta_wayland_surface_commit (surface);
commit_double_buffered_state (surface, &surface->pending);
}
static void
wl_surface_set_buffer_transform (struct wl_client *client,
struct wl_resource *resource,
int32_t transform)
meta_wayland_surface_set_buffer_transform (struct wl_client *client,
struct wl_resource *resource,
int32_t transform)
{
g_warning ("TODO: support set_buffer_transform request");
}
static void
wl_surface_set_buffer_scale (struct wl_client *client,
struct wl_resource *resource,
int scale)
meta_wayland_surface_set_buffer_scale (struct wl_client *client,
struct wl_resource *resource,
int scale)
{
if (scale != 1)
g_warning ("TODO: support set_buffer_scale request");
}
const struct wl_surface_interface meta_wayland_wl_surface_interface = {
wl_surface_destroy,
wl_surface_attach,
wl_surface_damage,
wl_surface_frame,
wl_surface_set_opaque_region,
wl_surface_set_input_region,
wl_surface_commit,
wl_surface_set_buffer_transform,
wl_surface_set_buffer_scale
const struct wl_surface_interface meta_wayland_surface_interface = {
meta_wayland_surface_destroy,
meta_wayland_surface_attach,
meta_wayland_surface_damage,
meta_wayland_surface_frame,
meta_wayland_surface_set_opaque_region,
meta_wayland_surface_set_input_region,
meta_wayland_surface_commit,
meta_wayland_surface_set_buffer_transform,
meta_wayland_surface_set_buffer_scale
};
void
meta_wayland_surface_set_window (MetaWaylandSurface *surface,
MetaWindow *window)
meta_wayland_surface_make_toplevel (MetaWaylandSurface *surface)
{
gboolean has_window = (window != NULL);
clutter_actor_set_reactive (CLUTTER_ACTOR (surface->surface_actor), TRUE);
}
clutter_actor_set_reactive (CLUTTER_ACTOR (surface->surface_actor), has_window);
surface->window = window;
void
meta_wayland_surface_window_unmanaged (MetaWaylandSurface *surface)
{
clutter_actor_set_reactive (CLUTTER_ACTOR (surface->surface_actor), FALSE);
surface->window = NULL;
}
static void
@ -627,7 +612,7 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
surface->compositor = compositor;
surface->resource = wl_resource_create (client, &wl_surface_interface, version, id);
wl_resource_set_implementation (surface->resource, &meta_wayland_wl_surface_interface, surface, wl_surface_destructor);
wl_resource_set_implementation (surface->resource, &meta_wayland_surface_interface, surface, wl_surface_destructor);
surface->buffer_destroy_listener.notify = surface_handle_buffer_destroy;
surface->surface_actor = g_object_ref_sink (meta_surface_actor_wayland_new (surface));
@ -924,7 +909,6 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
struct wl_resource *surface_resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWindow *window;
if (!create_surface_extension (&surface->xdg_surface,
META_XDG_SURFACE_VERSION,
@ -939,8 +923,8 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
return;
}
window = meta_window_wayland_new (meta_get_display (), surface);
meta_wayland_surface_set_window (surface, window);
meta_wayland_surface_make_toplevel (surface);
surface->window = meta_window_wayland_new (meta_get_display (), surface);
}
static void
@ -978,7 +962,6 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource);
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
MetaWindow *window;
if (parent_surf == NULL || parent_surf->window == NULL)
return;
@ -996,15 +979,15 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
return;
}
window = meta_window_wayland_new (meta_get_display (), surface);
window->rect.x = parent_surf->window->rect.x + x;
window->rect.y = parent_surf->window->rect.y + y;
window->showing_for_first_time = FALSE;
window->placed = TRUE;
meta_window_set_transient_for (window, parent_surf->window);
meta_window_set_type (window, META_WINDOW_DROPDOWN_MENU);
meta_wayland_surface_make_toplevel (surface);
surface->window = meta_window_wayland_new (meta_get_display (), surface);
surface->window->rect.x = parent_surf->window->rect.x + x;
surface->window->rect.y = parent_surf->window->rect.y + y;
surface->window->showing_for_first_time = FALSE;
surface->window->placed = TRUE;
meta_window_set_transient_for (surface->window, parent_surf->window);
meta_wayland_surface_set_window (surface, window);
meta_window_set_type (surface->window, META_WINDOW_DROPDOWN_MENU);
meta_wayland_pointer_start_popup_grab (&seat->pointer, surface);
}
@ -1287,7 +1270,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 (!create_surface_extension (&surface->wl_shell_surface,
META_WL_SHELL_SURFACE_VERSION,
@ -1302,8 +1284,8 @@ wl_shell_get_shell_surface (struct wl_client *client,
return;
}
window = meta_window_wayland_new (meta_get_display (), surface);
meta_wayland_surface_set_window (surface, window);
meta_wayland_surface_make_toplevel (surface);
surface->window = meta_window_wayland_new (meta_get_display (), surface);
}
static const struct wl_shell_interface meta_wayland_wl_shell_interface = {

View File

@ -111,8 +111,8 @@ MetaWaylandSurface *meta_wayland_surface_create (MetaWaylandCompositor *composit
guint32 id,
guint32 version);
void meta_wayland_surface_set_window (MetaWaylandSurface *surface,
MetaWindow *window);
void meta_wayland_surface_make_toplevel (MetaWaylandSurface *surface);
void meta_wayland_surface_window_unmanaged (MetaWaylandSurface *surface);
void meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
int width,

View File

@ -38,7 +38,7 @@
#define META_WL_COMPOSITOR_VERSION 3
#define META_WL_DATA_DEVICE_MANAGER_VERSION 1
#define META_WL_SHELL_VERSION 1
#define META_WL_SEAT_VERSION 3
#define META_WL_SEAT_VERSION 2 /* 3 not implemented yet */
#define META_WL_OUTPUT_VERSION 2
#define META_XSERVER_VERSION 1
#define META_GTK_SHELL_VERSION 1
@ -49,8 +49,8 @@
#define META_WL_DATA_SOURCE_VERSION 1 /* from wl_data_device */
#define META_WL_DATA_DEVICE_VERSION 1 /* from wl_data_device_manager */
#define META_WL_SURFACE_VERSION 3 /* from wl_compositor */
#define META_WL_POINTER_VERSION 3 /* from wl_seat */
#define META_WL_KEYBOARD_VERSION 3 /* from wl_seat */
#define META_WL_POINTER_VERSION 2 /* from wl_seat; 3 not implemented yet */
#define META_WL_KEYBOARD_VERSION 2 /* from wl_seat; 3 not implemented yet */
#define META_WL_TOUCH_VERSION 0 /* from wl_seat; wl_touch not supported */
#define META_WL_REGION_VERSION 1 /* from wl_compositor */
#define META_XDG_SURFACE_VERSION 1 /* from xdg_shell */

View File

@ -1,5 +1,3 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* X Wayland Support
*
@ -21,29 +19,33 @@
* 02111-1307, USA.
*/
#include "config.h"
#include "meta-xwayland.h"
#include "meta-xwayland-private.h"
#include "meta-wayland-surface-private.h"
#include <glib.h>
#include <glib-unix.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <stdlib.h>
#include "meta-xwayland-private.h"
#include "meta-window-actor-private.h"
#include "xserver-server-protocol.h"
static void
associate_window_with_surface (MetaWindow *window,
MetaWaylandSurface *surface)
xserver_set_window_id (struct wl_client *client,
struct wl_resource *compositor_resource,
struct wl_resource *surface_resource,
guint32 xid)
{
MetaDisplay *display = window->display;
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaDisplay *display = meta_get_display ();
MetaWindow *window;
window = meta_display_lookup_x_window (display, xid);
if (!window)
return;
/* If the window has an existing surface, like if we're
* undecorating or decorating the window, then we need
@ -52,75 +54,51 @@ associate_window_with_surface (MetaWindow *window,
if (window->surface)
window->surface->window = NULL;
meta_wayland_surface_set_window (surface, window);
meta_wayland_surface_make_toplevel (surface);
surface->window = window;
window->surface = surface;
meta_compositor_window_surface_changed (display->compositor, window);
/* Since the association comes in the form of a ClientMessage,
* we have no way to know when the surface was set up. Since
* commit just breaks if we don't have a window associated with
* it, we need to do a commit *again* here. */
meta_wayland_surface_commit (surface);
}
static gboolean
associate_window_with_surface_id (MetaXWaylandManager *manager,
MetaWindow *window,
guint32 surface_id)
static const struct xserver_interface xserver_implementation = {
xserver_set_window_id
};
static void
bind_xserver (struct wl_client *client,
void *data,
guint32 version,
guint32 id)
{
struct wl_resource *resource;
MetaXWaylandManager *manager = data;
resource = wl_client_get_object (manager->client, surface_id);
if (resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
associate_window_with_surface (window, surface);
return TRUE;
}
else
return FALSE;
}
/* If it's a different client than the xserver we launched,
* just freeze up... */
if (client != manager->client)
return;
typedef struct {
MetaXWaylandManager *manager;
MetaWindow *window;
guint32 surface_id;
} AssociateWindowWithSurfaceOp;
manager->xserver_resource = wl_resource_create (client, &xserver_interface,
MIN (META_XSERVER_VERSION, version), id);
wl_resource_set_implementation (manager->xserver_resource,
&xserver_implementation, manager, NULL);
static gboolean
associate_window_with_surface_idle (gpointer user_data)
{
AssociateWindowWithSurfaceOp *op = user_data;
if (!associate_window_with_surface_id (op->manager, op->window, op->surface_id))
{
/* Not here? Oh well... nothing we can do */
g_warning ("Unknown surface ID %d (from window %s)", op->surface_id, op->window->desc);
}
g_free (op);
xserver_send_listen_socket (manager->xserver_resource, manager->abstract_fd);
xserver_send_listen_socket (manager->xserver_resource, manager->unix_fd);
return G_SOURCE_REMOVE;
}
/* Make sure xwayland will recieve the above sockets in a finite
* time before unblocking the initialization mainloop since we are
* then going to immediately try and connect to those as the window
* manager. */
wl_client_flush (client);
void
meta_xwayland_handle_wl_surface_id (MetaWindow *window,
guint32 surface_id)
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaXWaylandManager *manager = &compositor->xwayland_manager;
if (!associate_window_with_surface_id (manager, window, surface_id))
{
/* No surface ID yet... it should arrive after the next
* iteration through the loop, so queue an idle and see
* what happens.
*/
AssociateWindowWithSurfaceOp *op = g_new0 (AssociateWindowWithSurfaceOp, 1);
op->manager = manager;
op->window = window;
op->surface_id = surface_id;
g_idle_add (associate_window_with_surface_idle, op);
}
/* At this point xwayland is all setup to start accepting
* connections so we can quit the transient initialization mainloop
* and unblock meta_wayland_init() to continue initializing mutter.
* */
g_main_loop_quit (manager->init_loop);
g_clear_pointer (&manager->init_loop, g_main_loop_unref);
}
static char *
@ -228,7 +206,8 @@ bind_to_abstract_socket (int display)
size = offsetof (struct sockaddr_un, sun_path) + name_size;
if (bind (fd, (struct sockaddr *) &addr, size) < 0)
{
g_warning ("failed to bind to @%s: %m", addr.sun_path + 1);
g_warning ("failed to bind to @%s: %s\n",
addr.sun_path + 1, strerror (errno));
close (fd);
return -1;
}
@ -260,7 +239,8 @@ bind_to_unix_socket (int display)
unlink (addr.sun_path);
if (bind (fd, (struct sockaddr *) &addr, size) < 0)
{
g_warning ("failed to bind to %s: %m\n", addr.sun_path);
char *msg = strerror (errno);
g_warning ("failed to bind to %s (%s)\n", addr.sun_path, msg);
close (fd);
return -1;
}
@ -275,6 +255,18 @@ bind_to_unix_socket (int display)
return fd;
}
static void
uncloexec (gpointer user_data)
{
int fd = GPOINTER_TO_INT (user_data);
/* Make sure the client end of the socket pair doesn't get closed
* when we exec xwayland. */
int flags = fcntl (fd, F_GETFD);
if (flags != -1)
fcntl (fd, F_SETFD, flags & ~FD_CLOEXEC);
}
static void
xserver_died (GPid pid,
gint status,
@ -300,11 +292,20 @@ x_io_error (Display *display)
return 0;
}
static gboolean
choose_xdisplay (MetaXWaylandManager *manager)
gboolean
meta_xwayland_start (MetaXWaylandManager *manager,
struct wl_display *wl_display)
{
int display = 0;
char *lockfile = NULL;
int sp[2];
pid_t pid;
char **env;
char *fd_string;
wl_global_create (wl_display, &xserver_interface,
META_XSERVER_VERSION,
manager, bind_xserver);
do
{
@ -342,102 +343,68 @@ choose_xdisplay (MetaXWaylandManager *manager)
while (1);
manager->display_index = display;
manager->display_name = g_strdup_printf (":%d", manager->display_index);
manager->lockfile = lockfile;
return TRUE;
}
static void
xserver_finished_init (MetaXWaylandManager *manager)
{
/* At this point xwayland is all setup to start accepting
* connections so we can quit the transient initialization mainloop
* and unblock meta_wayland_init() to continue initializing mutter.
* */
g_main_loop_quit (manager->init_loop);
g_clear_pointer (&manager->init_loop, g_main_loop_unref);
}
static gboolean
got_sigusr1 (gpointer user_data)
{
MetaXWaylandManager *manager = user_data;
xserver_finished_init (manager);
return G_SOURCE_REMOVE;
}
gboolean
meta_xwayland_start (MetaXWaylandManager *manager,
struct wl_display *wl_display)
{
int sp[2];
int fd;
if (!choose_xdisplay (manager))
return FALSE;
/* We want xwayland to be a wayland client so we make a socketpair to setup a
* wayland protocol connection. */
if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sp) < 0)
{
g_warning ("socketpair failed\n");
unlink (manager->lockfile);
unlink (lockfile);
return 1;
}
manager->pid = fork ();
if (manager->pid == 0)
{
char socket_fd[8], unix_fd[8], abstract_fd[8];
env = g_get_environ ();
fd_string = g_strdup_printf ("%d", sp[1]);
env = g_environ_setenv (env, "WAYLAND_SOCKET", fd_string, TRUE);
g_free (fd_string);
/* We passed SOCK_CLOEXEC, so dup the FD so it isn't
* closed on exec.. */
fd = dup (sp[1]);
snprintf (socket_fd, sizeof (socket_fd), "%d", fd);
setenv ("WAYLAND_SOCKET", socket_fd, TRUE);
manager->display_name = g_strdup_printf (":%d", manager->display_index);
fd = dup (manager->abstract_fd);
snprintf (abstract_fd, sizeof (abstract_fd), "%d", fd);
{
GError *error = NULL;
gchar *args[] = { XWAYLAND_PATH,
manager->display_name,
"-wayland",
"-rootless",
"-noreset",
"-nolisten",
"all",
NULL };
int flags = 0;
fd = dup (manager->unix_fd);
snprintf (unix_fd, sizeof (unix_fd), "%d", fd);
flags |= G_SPAWN_LEAVE_DESCRIPTORS_OPEN;
flags |= G_SPAWN_DO_NOT_REAP_CHILD;
/* xwayland, please. */
if (getenv ("XWAYLAND_STFU"))
{
int dev_null;
dev_null = open ("/dev/null", O_WRONLY);
/* xwayland, please. */
if (getenv ("XWAYLAND_STFU"))
{
flags |= G_SPAWN_STDOUT_TO_DEV_NULL;
flags |= G_SPAWN_STDERR_TO_DEV_NULL;
}
dup2 (dev_null, STDOUT_FILENO);
dup2 (dev_null, STDERR_FILENO);
}
if (g_spawn_async (NULL, /* cwd */
args,
env,
flags,
uncloexec,
GINT_TO_POINTER (sp[1]),
&pid,
&error))
{
close (sp[1]);
manager->client = wl_client_create (wl_display, sp[0]);
/* We have to ignore SIGUSR1 in the child to make sure
* that the server will send it to mutter-wayland. */
signal(SIGUSR1, SIG_IGN);
manager->pid = pid;
g_child_watch_add (pid, xserver_died, NULL);
}
else
{
g_error ("Failed to fork for xwayland server: %s", error->message);
}
}
if (execl (XWAYLAND_PATH, XWAYLAND_PATH,
manager->display_name,
"-rootless",
"-noreset",
"-listen", abstract_fd,
"-listen", unix_fd,
NULL) < 0)
{
g_error ("Failed to spawn XWayland: %m");
}
}
else if (manager->pid == -1)
{
g_error ("Failed to fork: %m");
}
g_child_watch_add (manager->pid, xserver_died, NULL);
g_unix_signal_add (SIGUSR1, got_sigusr1, manager);
manager->client = wl_client_create (wl_display, sp[0]);
g_strfreev (env);
/* We need to run a mainloop until we know xwayland has a binding
* for our xserver interface at which point we can assume it's

View File

@ -1,35 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef META_XWAYLAND_H
#define META_XWAYLAND_H
#include <glib.h>
#include <meta/types.h>
void
meta_xwayland_handle_wl_surface_id (MetaWindow *window,
guint32 surface_id);
#endif /* META_XWAYLAND_H */

View File

@ -0,0 +1,18 @@
<protocol name="xserver">
<interface name="xserver" version="1">
<request name="set_window_id">
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="id" type="uint"/>
</request>
<event name="client">
<arg name="fd" type="fd"/>
</event>
<event name="listen_socket">
<arg name="fd" type="fd"/>
</event>
</interface>
</protocol>

View File

@ -230,7 +230,7 @@ read_rgb_icon (MetaDisplay *display,
int mini_w, mini_h;
gulong *data_as_long;
meta_error_trap_push (display);
meta_error_trap_push_with_return (display);
type = None;
data = NULL;
result = XGetWindowProperty (display->xdisplay,
@ -504,7 +504,7 @@ get_kwm_win_icon (MetaDisplay *display,
*pixmap = None;
*mask = None;
meta_error_trap_push (display);
meta_error_trap_push_with_return (display);
icons = NULL;
result = XGetWindowProperty (display->xdisplay, xwindow,
display->atom__KWM_WIN_ICON,

View File

@ -1665,12 +1665,12 @@ meta_window_x11_client_message (MetaWindow *window,
char *str1;
char *str2;
meta_error_trap_push (display);
meta_error_trap_push_with_return (display);
str1 = XGetAtomName (display->xdisplay, first);
if (meta_error_trap_pop_with_return (display) != Success)
str1 = NULL;
meta_error_trap_push (display);
meta_error_trap_push_with_return (display);
str2 = XGetAtomName (display->xdisplay, second);
if (meta_error_trap_pop_with_return (display) != Success)
str2 = NULL;
@ -2298,7 +2298,7 @@ meta_window_x11_new (MetaDisplay *display,
wm_state_to_string (existing_wm_state));
}
meta_error_trap_push (display);
meta_error_trap_push_with_return (display);
/*
* XAddToSaveSet can only be called on windows created by a different
@ -2309,7 +2309,7 @@ meta_window_x11_new (MetaDisplay *display,
*/
XAddToSaveSet (display->xdisplay, xwindow);
meta_error_trap_push (display);
meta_error_trap_push_with_return (display);
event_mask = PropertyChangeMask;
if (attrs.override_redirect)

View File

@ -191,7 +191,7 @@ get_property (MetaDisplay *display,
results->bytes_after = 0;
results->format = 0;
meta_error_trap_push (display);
meta_error_trap_push_with_return (display);
if (XGetWindowProperty (display->xdisplay, xwindow, xatom,
0, G_MAXLONG,
False, req_type, &results->type, &results->format,
@ -736,29 +736,6 @@ meta_prop_get_cardinal_with_atom_type (MetaDisplay *display,
return cardinal_with_atom_type_from_results (&results, prop_type, cardinal_p);
}
static char *
text_property_to_utf8 (Display *xdisplay,
const XTextProperty *prop)
{
char *ret = NULL;
char **local_list = NULL;
int count = 0;
int res;
res = XmbTextPropertyToTextList (xdisplay, prop, &local_list, &count);
if (res == XNoMemory || res == XLocaleNotSupported || res == XConverterNotFound)
goto out;
if (count == 0)
goto out;
ret = g_strdup (local_list[0]);
out:
meta_XFree (local_list);
return ret;
}
static gboolean
text_property_from_results (GetPropertyResults *results,
char **utf8_str_p)
@ -766,14 +743,15 @@ text_property_from_results (GetPropertyResults *results,
XTextProperty tp;
*utf8_str_p = NULL;
tp.value = results->prop;
results->prop = NULL;
tp.encoding = results->type;
tp.format = results->format;
tp.nitems = results->n_items;
*utf8_str_p = text_property_to_utf8 (results->display->xdisplay, &tp);
*utf8_str_p = meta_text_property_to_utf8 (results->display->xdisplay,
&tp);
if (tp.value != NULL)
XFree (tp.value);