Compare commits

...

34 Commits

Author SHA1 Message Date
5bc7ae4095 ff 2014-04-06 17:43:43 -04:00
1a78515606 ui: Use the default GdkDisplay / GdkScreen
These are the values we always use anyway, and it allows us to
seal off MetaUI further and have them on their own X connection.
2014-04-06 17:43:43 -04:00
4122257bce ui: Store the GdkDisplay / GdkScreen internally
We're going to get the defaults instead of passing them through soon.
2014-04-06 17:43:43 -04:00
29f6e3bda5 ui: Remove Display from the UI API
We already store it in the MetaUI struct, so add that where it's
missing and remove Display.
2014-04-06 17:43:43 -04:00
bbcbf5820f ui: Don't hang the MetaUI pointer off the GdkDisplay
Instead, use the user_data in the filter to pass a MetaUI through.
2014-04-06 17:22:55 -04:00
ee7c58984a ui: Kill off meta_ui_get_screen_number
GTK+ always opens the DefaultScreen now, so we can do the same.
2014-04-06 17:06:12 -04:00
03e5bbf59f xprop: Don't use GDK for reading text properties 2014-04-06 17:06:12 -04:00
cc6becb163 errors: Copy error trap code from GDK into mutter
In order to kill off using GDK for event handling in X11, we're going
to need to stop using GDK primitives.
2014-04-06 16:16:33 -04:00
e3b855a583 errors: Kill off meta_error_trap_push_with_return
It isn't special; it's just an alias for meta_error_trap_push.
2014-04-06 16:16:31 -04:00
5d8dd0653e display: Remove vestigals of old error trap implementation 2014-04-06 15:54:47 -04:00
abe94827f5 events: Don't pass any X input events on to Clutter / GTK+ 2014-04-06 15:32:30 -04:00
72b88c929e events: Early exit when we get a SN notification event
Nothing else needs to see this.
2014-04-06 15:23:20 -04:00
4752776ebf ui: Don't add our filter function twice 2014-04-06 15:19:04 -04:00
c40868b239 xwayland: Fix rendering
Since we get the ClientMessage after the surface is created, there's
no good way to synchronize the two streams. In this case, what we
need to do is delay the surface commit until after we get the
ClientMessage. Ideally, we'd be using a better surface system overall
where committing the surface didn't depend on what type it is, but
oh well, this is a good short-term hack for now.
2014-04-02 13:24:58 -04:00
a21e7a2188 wayland: Move surface_set_buffer back into the commits
For XWayland support, we need to delay the buffer set until after
we do the typechecking, as we need to bail out early in that case.
2014-04-02 13:24:58 -04:00
371fba6843 wayland: Move the commit implementation to the top
We're going to need to expose commit as a public method for XWayland
support, so decouple it from the handler implementation.
2014-04-02 13:24:57 -04:00
be02fa1120 xwayland: Switch to the new Xwayland DDX 2014-04-02 13:24:57 -04:00
43730f1660 xwayland: Switch to SIGUSR1 to know when the X server has finished init
This is effectively the same, but since we lose the xserver.xml protocol
in the new XWayland DDX, we have to use SIGUSR1 anyway, so might as well
switch over now.
2014-04-02 13:16:10 -04:00
4f609dbf5e xwayland: Don't use glib after forking
glib doesn't have any guarantee about working after forking.
We can get away with it, but we're better off just not using it.
2014-04-02 13:04:31 -04:00
2a7d12ba14 xwayland: Make failing to exec a fatal error 2014-04-02 13:03:29 -04:00
c4c0b5f0ab xwayland: Detect a fail to fork 2014-04-02 13:03:17 -04:00
8373c90cd8 background: Remove load_still_frame
Nothing uses it, and it's incompatible with XWayland anyway.
2014-04-02 12:35:24 -04:00
eb5b54dd8b xwayland: Split another part of the initialization sequence out
This will be used from a SIGUSR1 handler.
2014-04-02 11:41:28 -04:00
9653b79a35 xwayland: Split a helper out
This will make the next commit, which ports to the new ClientMessage
API, more understandable.
2014-04-02 11:41:28 -04:00
e07bd15fc2 xwayland: Make file cosmetically modern
Put a modeline, include "config.h", and shift around the include ordering
2014-04-02 11:41:27 -04:00
5cf0740b4e xwayland: Fork the X server ourselves
gspawn just isn't us the fine-grained control we need for starting
processes and leaking file descriptors in.
2014-04-02 11:41:27 -04:00
c540ddf59b xwayland: Move display_name into choose_xdisplay 2014-04-02 11:41:27 -04:00
a44295599c xwayland: Split out the code that creates the XWayland sockets 2014-04-02 11:41:26 -04:00
af272f2685 xwayland: Move global initialization down 2014-04-02 11:41:26 -04:00
81d033ec73 xwayland: Use %m instead of manual strerror(errno) 2014-04-02 11:41:26 -04:00
e9ee984921 wayland: Rename the wl_surface interface handlers
We usually name the method handlers after the direct name
of the interface methods. Do that for wl_surface as well.
2014-04-02 11:41:26 -04:00
3c404c5db3 wayland: Replace make_toplevel / window_unmanaging with set_window
The make_toplevel / window_unmanaging interface has never made
a lot of sense to me. Replace it with set_window, which does
effectively the same thing.

It's still not perfect in the case of XWayland, but I don't think
XWayland will ever make me happy.
2014-04-02 11:41:07 -04:00
e4cd000cef wayland: Implement wl_seat v3
The new XWayland DDX flat out requires seat v3.
2014-04-02 11:40:40 -04:00
6296fefea6 window-actor: Clean up has_shadow
This has some particularly picky #if 0'd code. Since the history for
it isn't illuminating in the slightest, I'm just going to kill it.
2014-04-02 11:40:04 -04:00
29 changed files with 884 additions and 824 deletions

View File

@ -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/Xorg"])
[XWAYLAND_PATH="$bindir/Xwayland"])
AM_GLIB_GNU_GETTEXT

View File

@ -41,14 +41,11 @@ mutter_built_sources = \
gtk-shell-protocol.c \
gtk-shell-server-protocol.h \
xdg-shell-protocol.c \
xdg-shell-server-protocol.h \
xserver-protocol.c \
xserver-server-protocol.h
xdg-shell-server-protocol.h
wayland_protocols = \
wayland/protocol/gtk-shell.xml \
wayland/protocol/xdg-shell.xml \
wayland/protocol/xserver.xml
wayland/protocol/xdg-shell.xml
libmutter_wayland_la_SOURCES = \
backends/meta-backend.c \
@ -214,8 +211,9 @@ libmutter_wayland_la_SOURCES = \
wayland/meta-wayland.c \
wayland/meta-wayland.h \
wayland/meta-wayland-private.h \
wayland/meta-xwayland-private.h \
wayland/meta-xwayland.c \
wayland/meta-xwayland.h \
wayland/meta-xwayland-private.h \
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_with_return (display);
meta_error_trap_push (display);
XCompositeRedirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
XSync (xdisplay, FALSE);

View File

@ -26,8 +26,6 @@
#include <config.h>
#include <cogl/cogl-texture-pixmap-x11.h>
#include <clutter/clutter.h>
#include "cogl-utils.h"
@ -755,88 +753,6 @@ 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,7 +702,6 @@ 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;
@ -741,25 +740,6 @@ 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,6 +92,7 @@ struct _MetaDisplay
Display *xdisplay;
int clutter_event_filter;
GSource *x11_event_source;
Window leader_window;
Window timestamp_pinging_window;
@ -147,13 +148,10 @@ 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
@ -256,6 +254,8 @@ 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 = meta_ui_get_display ();
xdisplay = XOpenDisplay (NULL);
if (xdisplay == NULL)
{
@ -472,9 +472,6 @@ 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;
@ -835,7 +832,7 @@ meta_display_open (void)
* now it always manages exactly one screen as specified by the DISPLAY
* environment variable.
*/
i = meta_ui_get_screen_number ();
i = DefaultScreen (the_display->xdisplay);
screen = meta_screen_new (the_display, i, timestamp);
if (!screen)
@ -1016,9 +1013,6 @@ 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);
@ -2212,7 +2206,7 @@ meta_change_button_grab (MetaDisplay *display,
mods = (XIGrabModifiers) { modmask | ignored_mask, 0 };
if (meta_is_debugging ())
meta_error_trap_push_with_return (display);
meta_error_trap_push (display);
/* GrabModeSync means freeze until XAllowEvents */

View File

@ -1,9 +1,8 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2001 Havoc Pennington, error trapping inspired by GDK
* code copyrighted by the GTK team.
*
/*
* 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
@ -13,9 +12,11 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
/**
@ -27,42 +28,250 @@
#include <config.h>
#include <meta/errors.h>
#include "display-private.h"
#include <errno.h>
#include <stdlib.h>
#include <gdk/gdk.h>
/* 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.)
*/
/* 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;
}
}
}
void
meta_error_trap_push (MetaDisplay *display)
{
gdk_error_trap_push ();
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;
}
void
meta_error_trap_pop (MetaDisplay *display)
{
gdk_error_trap_pop_ignored ();
}
void
meta_error_trap_push_with_return (MetaDisplay *display)
{
gdk_error_trap_push ();
meta_error_trap_pop_internal (display, FALSE);
}
int
meta_error_trap_pop_with_return (MetaDisplay *display)
{
return gdk_error_trap_pop ();
return meta_error_trap_pop_internal (display, TRUE);
}

View File

@ -39,6 +39,7 @@
#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"
@ -77,9 +78,8 @@ get_input_event (MetaDisplay *display,
{
XIEvent *input_event;
/* NB: GDK event filters already have generic events
* allocated, so no need to do XGetEventData() on our own
*/
XGetEventData (display->xdisplay, &event->xcookie);
input_event = (XIEvent *) event->xcookie.data;
switch (input_event->evtype)
@ -859,6 +859,17 @@ 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;
@ -933,12 +944,11 @@ handle_input_xevent (MetaDisplay *display,
}
}
/* Don't send FocusIn / FocusOut to Clutter */
return TRUE;
break;
}
return FALSE;
/* Don't pass these events through to Clutter / GTK+ */
return TRUE;
}
static void
@ -1040,7 +1050,7 @@ convert_property (MetaDisplay *display,
conversion_targets[2] = display->atom_TIMESTAMP;
conversion_targets[3] = display->atom_VERSION;
meta_error_trap_push_with_return (display);
meta_error_trap_push (display);
if (target == display->atom_TARGETS)
XChangeProperty (display->xdisplay, w, property,
XA_ATOM, 32, PropModeReplace,
@ -1115,7 +1125,7 @@ process_selection_request (MetaDisplay *display,
unsigned long num, rest;
unsigned char *data;
meta_error_trap_push_with_return (display);
meta_error_trap_push (display);
if (XGetWindowProperty (display->xdisplay,
event->xselectionrequest.requestor,
event->xselectionrequest.property, 0, 256, False,
@ -1536,7 +1546,12 @@ handle_other_xevent (MetaDisplay *display,
case ClientMessage:
if (window)
{
if (!frame_was_receiver)
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)
meta_window_x11_client_message (window, event);
}
else
@ -1734,12 +1749,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 gboolean
static void
meta_display_handle_xevent (MetaDisplay *display,
XEvent *event)
{
Window modified;
gboolean bypass_compositor = FALSE, bypass_gtk = FALSE;
gboolean bypass_compositor = FALSE;
XIEvent *input_event;
MetaMonitorManager *monitor;
@ -1748,13 +1763,13 @@ meta_display_handle_xevent (MetaDisplay *display,
#endif
#ifdef HAVE_STARTUP_NOTIFICATION
sn_display_process_event (display->sn_display, event);
if (sn_display_process_event (display->sn_display, event))
{
bypass_compositor = TRUE;
goto out;
}
#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))
{
@ -1783,7 +1798,7 @@ meta_display_handle_xevent (MetaDisplay *display,
{
if (meta_screen_handle_xevent (display->screen, event))
{
bypass_gtk = bypass_compositor = TRUE;
bypass_compositor = TRUE;
goto out;
}
}
@ -1794,8 +1809,9 @@ meta_display_handle_xevent (MetaDisplay *display,
if (event->type == UnmapNotify)
{
if (meta_ui_window_should_not_cause_focus (display->xdisplay,
modified))
MetaUI *ui = display->screen->ui;
if (meta_ui_window_should_not_cause_focus (ui, modified))
{
meta_display_add_ignored_crossing_serial (display, event->xany.serial);
meta_topic (META_DEBUG_FOCUS,
@ -1817,7 +1833,7 @@ meta_display_handle_xevent (MetaDisplay *display,
#ifdef HAVE_XI23
if (meta_display_process_barrier_event (display, input_event))
{
bypass_gtk = bypass_compositor = TRUE;
bypass_compositor = TRUE;
goto out;
}
#endif /* HAVE_XI23 */
@ -1828,27 +1844,20 @@ meta_display_handle_xevent (MetaDisplay *display,
*/
if (handle_input_xevent (display, input_event, event->xany.serial))
{
bypass_gtk = bypass_compositor = TRUE;
bypass_compositor = TRUE;
goto out;
}
if (handle_other_xevent (display, event))
{
bypass_gtk = TRUE;
goto out;
}
goto out;
out:
if (!bypass_compositor)
{
MetaWindow *window = modified != None ? meta_display_lookup_x_window (display, modified) : NULL;
if (meta_compositor_process_event (display->compositor, event, window))
bypass_gtk = TRUE;
meta_compositor_process_event (display->compositor, event, window);
}
display->current_time = CurrentTime;
return bypass_gtk;
}
static void
@ -2159,19 +2168,6 @@ 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)
@ -2181,20 +2177,90 @@ 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,7 +92,6 @@ 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_with_return (display);
meta_error_trap_push (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_with_return (display);
meta_error_trap_push (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_with_return (display);
meta_error_trap_push (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_with_return (display);
meta_error_trap_push (display);
/* We need to or with the existing event mask since
* gtk+ may be interested in other events.
@ -757,8 +757,7 @@ meta_screen_new (MetaDisplay *display,
screen->keys_grabbed = FALSE;
meta_screen_grab_keys (screen);
screen->ui = meta_ui_new (screen->display->xdisplay,
screen->xscreen);
screen->ui = meta_ui_new ();
screen->tile_preview_timeout_id = 0;
@ -838,7 +837,7 @@ meta_screen_free (MetaScreen *screen,
meta_stack_free (screen->stack);
meta_stack_tracker_free (screen->stack_tracker);
meta_error_trap_push_with_return (screen->display);
meta_error_trap_push (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_window_unmanaged (window->surface);
meta_wayland_surface_set_window (window->surface, NULL);
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_with_return (window->display);
meta_error_trap_push (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_with_return (display);
meta_error_trap_push (display);
meta_topic (META_DEBUG_WINDOW_OPS,
"Warping pointer to %d,%d with window at %d,%d\n",

View File

@ -81,6 +81,7 @@ 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,7 +30,6 @@
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,7 +91,6 @@ 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,8 +39,9 @@ static void meta_ui_accelerator_parse (const char *accel,
struct _MetaUI
{
Display *xdisplay;
Screen *xscreen;
GdkDisplay *display;
GdkScreen *screen;
MetaFrames *frames;
/* For double-click tracking */
@ -60,202 +61,17 @@ meta_ui_init (void)
meta_fatal ("Unable to open X display %s\n", XDisplayName (NULL));
}
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)
meta_ui_new (void)
{
GdkDisplay *gdisplay;
MetaUI *ui;
ui = g_new0 (MetaUI, 1);
ui->xdisplay = xdisplay;
ui->xscreen = screen;
ui->display = gdk_display_get_default ();
ui->screen = gdk_screen_get_default ();
gdisplay = gdk_x11_lookup_xdisplay (xdisplay);
g_assert (gdisplay == gdk_display_get_default ());
ui->frames = meta_frames_new (gdk_screen_get_number (ui->screen));
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
@ -264,25 +80,14 @@ meta_ui_new (Display *xdisplay,
*/
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);
}
@ -307,7 +112,6 @@ meta_ui_get_frame_borders (MetaUI *ui,
Window
meta_ui_create_frame_window (MetaUI *ui,
Display *xdisplay,
Visual *xvisual,
gint x,
gint y,
@ -316,7 +120,7 @@ meta_ui_create_frame_window (MetaUI *ui,
gint screen_no,
gulong *create_serial)
{
GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
GdkDisplay *display = ui->display;
GdkScreen *screen = gdk_display_get_screen (display, screen_no);
GdkWindowAttr attrs;
gint attributes_mask;
@ -365,7 +169,7 @@ meta_ui_create_frame_window (MetaUI *ui,
* as long as you pass in a colormap.
*/
if (create_serial)
*create_serial = XNextRequest (xdisplay);
*create_serial = XNextRequest (GDK_DISPLAY_XDISPLAY (display));
window =
gdk_window_new (gdk_screen_get_root_window(screen),
&attrs, attributes_mask);
@ -399,10 +203,9 @@ 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)
@ -413,10 +216,9 @@ 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)
@ -634,13 +436,13 @@ meta_ui_get_default_mini_icon (MetaUI *ui)
}
gboolean
meta_ui_window_should_not_cause_focus (Display *xdisplay,
Window xwindow)
meta_ui_window_should_not_cause_focus (MetaUI *ui,
Window xwindow)
{
GdkWindow *window;
GdkDisplay *display;
display = gdk_x11_lookup_xdisplay (xdisplay);
display = ui->display;
window = gdk_x11_window_lookup_for_display (display, xwindow);
/* we shouldn't cause focus if we're an override redirect
@ -652,38 +454,6 @@ meta_ui_window_should_not_cause_focus (Display *xdisplay,
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,
@ -703,8 +473,7 @@ meta_ui_theme_get_frame_borders (MetaUI *ui,
if (!font_desc)
{
GdkDisplay *display = gdk_x11_lookup_xdisplay (ui->xdisplay);
GdkScreen *screen = gdk_display_get_screen (display, XScreenNumberOfScreen (ui->xscreen));
GdkScreen *screen = ui->screen;
GtkWidgetPath *widget_path;
style = gtk_style_context_new ();
@ -943,10 +712,9 @@ gboolean
meta_ui_window_is_widget (MetaUI *ui,
Window xwindow)
{
GdkDisplay *display;
GdkDisplay *display = ui->display;
GdkWindow *window;
display = gdk_x11_lookup_xdisplay (ui->xdisplay);
window = gdk_x11_window_lookup_for_display (display, xwindow);
if (window)

View File

@ -42,12 +42,7 @@ typedef enum
void meta_ui_init (void);
Display* meta_ui_get_display (void);
gint meta_ui_get_screen_number (void);
MetaUI* meta_ui_new (Display *xdisplay,
Screen *screen);
MetaUI* meta_ui_new (void);
void meta_ui_free (MetaUI *ui);
void meta_ui_theme_get_frame_borders (MetaUI *ui,
@ -65,7 +60,6 @@ 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,
@ -139,11 +133,8 @@ 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 (Display *xdisplay,
Window xwindow);
char* meta_text_property_to_utf8 (Display *xdisplay,
const XTextProperty *prop);
gboolean meta_ui_window_should_not_cause_focus (MetaUI *ui,
Window xwindow);
void meta_ui_set_current_theme (const char *name);
gboolean meta_ui_have_a_theme (void);

View File

@ -115,8 +115,16 @@ 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_set_cursor,
pointer_release,
};
static void
@ -137,6 +145,17 @@ 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

@ -0,0 +1,32 @@
/* -*- 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,6 +48,7 @@
#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"
@ -117,132 +118,6 @@ 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)
{
@ -270,22 +145,37 @@ ensure_buffer_texture (MetaWaylandBuffer *buffer)
buffer->texture = texture;
}
static void
cursor_surface_commit (MetaWaylandSurface *surface,
MetaWaylandDoubleBufferedState *pending,
gboolean buffer_changed)
static gboolean
commit_attached_surface (MetaWaylandSurface *surface,
MetaWaylandDoubleBufferedState *pending)
{
if (buffer_changed)
meta_wayland_seat_update_cursor_surface (surface->compositor->seat);
/* 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)
{
if (commit_attached_surface (surface, pending))
meta_wayland_seat_update_cursor_surface (surface->compositor->seat);
}
static gboolean
actor_surface_commit (MetaWaylandSurface *surface,
MetaWaylandDoubleBufferedState *pending,
gboolean buffer_changed)
MetaWaylandDoubleBufferedState *pending)
{
MetaSurfaceActor *surface_actor = surface->surface_actor;
MetaWaylandBuffer *buffer = pending->buffer;
gboolean buffer_changed;
buffer_changed = commit_attached_surface (surface, pending);
if (buffer_changed && buffer)
{
@ -299,16 +189,15 @@ 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,
gboolean buffer_changed)
MetaWaylandDoubleBufferedState *pending)
{
actor_surface_commit (surface, pending, buffer_changed);
if (buffer_changed)
if (actor_surface_commit (surface, pending))
{
MetaWindow *window = surface->window;
MetaWaylandBuffer *buffer = pending->buffer;
@ -417,8 +306,7 @@ move_double_buffered_state (MetaWaylandDoubleBufferedState *from,
static void
subsurface_surface_commit (MetaWaylandSurface *surface,
MetaWaylandDoubleBufferedState *pending,
gboolean buffer_changed)
MetaWaylandDoubleBufferedState *pending)
{
/*
* If the sub-surface is in synchronous mode, post-pone the commit of its
@ -438,9 +326,7 @@ subsurface_surface_commit (MetaWaylandSurface *surface,
}
else
{
actor_surface_commit (surface, pending, buffer_changed);
if (buffer_changed)
if (actor_surface_commit (surface, pending))
{
MetaSurfaceActor *surface_actor = surface->surface_actor;
MetaWaylandBuffer *buffer = pending->buffer;
@ -473,21 +359,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, buffer_changed);
cursor_surface_commit (surface, pending);
else if (surface->window)
toplevel_surface_commit (surface, pending, buffer_changed);
toplevel_surface_commit (surface, pending);
else if (surface->subsurface.resource)
subsurface_surface_commit (surface, pending, buffer_changed);
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;
}
g_list_foreach (surface->subsurfaces,
parent_surface_committed,
@ -506,9 +392,141 @@ 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
meta_wayland_surface_commit (struct wl_client *client,
struct wl_resource *resource)
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)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
@ -516,49 +534,46 @@ meta_wayland_surface_commit (struct wl_client *client,
if (!surface)
return;
commit_double_buffered_state (surface, &surface->pending);
meta_wayland_surface_commit (surface);
}
static void
meta_wayland_surface_set_buffer_transform (struct wl_client *client,
struct wl_resource *resource,
int32_t transform)
wl_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
meta_wayland_surface_set_buffer_scale (struct wl_client *client,
struct wl_resource *resource,
int scale)
wl_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_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
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
};
void
meta_wayland_surface_make_toplevel (MetaWaylandSurface *surface)
meta_wayland_surface_set_window (MetaWaylandSurface *surface,
MetaWindow *window)
{
clutter_actor_set_reactive (CLUTTER_ACTOR (surface->surface_actor), TRUE);
}
gboolean has_window = (window != NULL);
void
meta_wayland_surface_window_unmanaged (MetaWaylandSurface *surface)
{
clutter_actor_set_reactive (CLUTTER_ACTOR (surface->surface_actor), FALSE);
surface->window = NULL;
clutter_actor_set_reactive (CLUTTER_ACTOR (surface->surface_actor), has_window);
surface->window = window;
}
static void
@ -612,7 +627,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_surface_interface, surface, wl_surface_destructor);
wl_resource_set_implementation (surface->resource, &meta_wayland_wl_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));
@ -909,6 +924,7 @@ 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,
@ -923,8 +939,8 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
return;
}
meta_wayland_surface_make_toplevel (surface);
surface->window = meta_window_wayland_new (meta_get_display (), surface);
window = meta_window_wayland_new (meta_get_display (), surface);
meta_wayland_surface_set_window (surface, window);
}
static void
@ -962,6 +978,7 @@ 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;
@ -979,15 +996,15 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
return;
}
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);
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_window_set_type (surface->window, META_WINDOW_DROPDOWN_MENU);
meta_wayland_surface_set_window (surface, window);
meta_wayland_pointer_start_popup_grab (&seat->pointer, surface);
}
@ -1270,6 +1287,7 @@ wl_shell_get_shell_surface (struct wl_client *client,
struct wl_resource *surface_resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWindow *window;
if (!create_surface_extension (&surface->wl_shell_surface,
META_WL_SHELL_SURFACE_VERSION,
@ -1284,8 +1302,8 @@ wl_shell_get_shell_surface (struct wl_client *client,
return;
}
meta_wayland_surface_make_toplevel (surface);
surface->window = meta_window_wayland_new (meta_get_display (), surface);
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 = {

View File

@ -111,8 +111,8 @@ MetaWaylandSurface *meta_wayland_surface_create (MetaWaylandCompositor *composit
guint32 id,
guint32 version);
void meta_wayland_surface_make_toplevel (MetaWaylandSurface *surface);
void meta_wayland_surface_window_unmanaged (MetaWaylandSurface *surface);
void meta_wayland_surface_set_window (MetaWaylandSurface *surface,
MetaWindow *window);
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 2 /* 3 not implemented yet */
#define META_WL_SEAT_VERSION 3
#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 2 /* from wl_seat; 3 not implemented yet */
#define META_WL_KEYBOARD_VERSION 2 /* from wl_seat; 3 not implemented yet */
#define META_WL_POINTER_VERSION 3 /* from wl_seat */
#define META_WL_KEYBOARD_VERSION 3 /* from wl_seat */
#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,3 +1,5 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* X Wayland Support
*
@ -19,33 +21,29 @@
* 02111-1307, USA.
*/
#include <glib.h>
#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
xserver_set_window_id (struct wl_client *client,
struct wl_resource *compositor_resource,
struct wl_resource *surface_resource,
guint32 xid)
associate_window_with_surface (MetaWindow *window,
MetaWaylandSurface *surface)
{
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;
MetaDisplay *display = window->display;
/* If the window has an existing surface, like if we're
* undecorating or decorating the window, then we need
@ -54,51 +52,75 @@ xserver_set_window_id (struct wl_client *client,
if (window->surface)
window->surface->window = NULL;
meta_wayland_surface_make_toplevel (surface);
surface->window = window;
meta_wayland_surface_set_window (surface, 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 const struct xserver_interface xserver_implementation = {
xserver_set_window_id
};
static void
bind_xserver (struct wl_client *client,
void *data,
guint32 version,
guint32 id)
static gboolean
associate_window_with_surface_id (MetaXWaylandManager *manager,
MetaWindow *window,
guint32 surface_id)
{
MetaXWaylandManager *manager = data;
struct wl_resource *resource;
/* If it's a different client than the xserver we launched,
* just freeze up... */
if (client != manager->client)
return;
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;
}
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);
typedef struct {
MetaXWaylandManager *manager;
MetaWindow *window;
guint32 surface_id;
} AssociateWindowWithSurfaceOp;
xserver_send_listen_socket (manager->xserver_resource, manager->abstract_fd);
xserver_send_listen_socket (manager->xserver_resource, manager->unix_fd);
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);
/* 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);
return G_SOURCE_REMOVE;
}
/* 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);
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);
}
}
static char *
@ -206,8 +228,7 @@ 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: %s\n",
addr.sun_path + 1, strerror (errno));
g_warning ("failed to bind to @%s: %m", addr.sun_path + 1);
close (fd);
return -1;
}
@ -239,8 +260,7 @@ bind_to_unix_socket (int display)
unlink (addr.sun_path);
if (bind (fd, (struct sockaddr *) &addr, size) < 0)
{
char *msg = strerror (errno);
g_warning ("failed to bind to %s (%s)\n", addr.sun_path, msg);
g_warning ("failed to bind to %s: %m\n", addr.sun_path);
close (fd);
return -1;
}
@ -255,18 +275,6 @@ 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,
@ -292,20 +300,11 @@ x_io_error (Display *display)
return 0;
}
gboolean
meta_xwayland_start (MetaXWaylandManager *manager,
struct wl_display *wl_display)
static gboolean
choose_xdisplay (MetaXWaylandManager *manager)
{
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
{
@ -343,68 +342,102 @@ meta_xwayland_start (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 (lockfile);
unlink (manager->lockfile);
return 1;
}
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);
manager->pid = fork ();
if (manager->pid == 0)
{
char socket_fd[8], unix_fd[8], abstract_fd[8];
manager->display_name = g_strdup_printf (":%d", manager->display_index);
/* 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);
{
GError *error = NULL;
gchar *args[] = { XWAYLAND_PATH,
manager->display_name,
"-wayland",
"-rootless",
"-noreset",
"-nolisten",
"all",
NULL };
int flags = 0;
fd = dup (manager->abstract_fd);
snprintf (abstract_fd, sizeof (abstract_fd), "%d", fd);
flags |= G_SPAWN_LEAVE_DESCRIPTORS_OPEN;
flags |= G_SPAWN_DO_NOT_REAP_CHILD;
fd = dup (manager->unix_fd);
snprintf (unix_fd, sizeof (unix_fd), "%d", fd);
/* xwayland, please. */
if (getenv ("XWAYLAND_STFU"))
{
flags |= G_SPAWN_STDOUT_TO_DEV_NULL;
flags |= G_SPAWN_STDERR_TO_DEV_NULL;
}
/* xwayland, please. */
if (getenv ("XWAYLAND_STFU"))
{
int dev_null;
dev_null = open ("/dev/null", O_WRONLY);
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]);
dup2 (dev_null, STDOUT_FILENO);
dup2 (dev_null, STDERR_FILENO);
}
manager->pid = pid;
g_child_watch_add (pid, xserver_died, NULL);
}
else
{
g_error ("Failed to fork for xwayland server: %s", error->message);
}
}
/* We have to ignore SIGUSR1 in the child to make sure
* that the server will send it to mutter-wayland. */
signal(SIGUSR1, SIG_IGN);
g_strfreev (env);
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]);
/* 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

@ -0,0 +1,35 @@
/* -*- 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

@ -1,18 +0,0 @@
<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_with_return (display);
meta_error_trap_push (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_with_return (display);
meta_error_trap_push (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_with_return (display);
meta_error_trap_push (display);
str1 = XGetAtomName (display->xdisplay, first);
if (meta_error_trap_pop_with_return (display) != Success)
str1 = NULL;
meta_error_trap_push_with_return (display);
meta_error_trap_push (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_with_return (display);
meta_error_trap_push (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_with_return (display);
meta_error_trap_push (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_with_return (display);
meta_error_trap_push (display);
if (XGetWindowProperty (display->xdisplay, xwindow, xatom,
0, G_MAXLONG,
False, req_type, &results->type, &results->format,
@ -736,6 +736,29 @@ 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)
@ -743,15 +766,14 @@ 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 = meta_text_property_to_utf8 (results->display->xdisplay,
&tp);
*utf8_str_p = text_property_to_utf8 (results->display->xdisplay, &tp);
if (tp.value != NULL)
XFree (tp.value);