summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Fourdan <ofourdan@redhat.com>2019-12-17 15:07:07 +0100
committerOlivier Fourdan <ofourdan@redhat.com>2019-12-20 16:19:01 +0100
commit89e32d00f6e03fcdab267bfd9f0b0c5c2747d380 (patch)
tree79501d2713e67afcd6a796fb69f5a93a5cc7ad24
parent3a59650ba74e9d97473fa39269fdb74ad7e1cd43 (diff)
xwayland: Move Xwayland windows to its own sources
Over time, Xwayland main source file `xwayland.c` has grown in size which makes it look cluttered and harder to read. Move the code dealing with Xwayland window to its own source and header files. Signed-off-by: Olivier Fourdan <ofourdan@redhat.com> Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
-rw-r--r--hw/xwayland/Makefile.am2
-rw-r--r--hw/xwayland/meson.build2
-rw-r--r--hw/xwayland/xwayland-glamor.c1
-rw-r--r--hw/xwayland/xwayland-input.c14
-rw-r--r--hw/xwayland/xwayland-output.c10
-rw-r--r--hw/xwayland/xwayland-present.c10
-rw-r--r--hw/xwayland/xwayland-window-buffers.c5
-rw-r--r--hw/xwayland/xwayland-window.c825
-rw-r--r--hw/xwayland/xwayland-window.h81
-rw-r--r--hw/xwayland/xwayland.c778
-rw-r--r--hw/xwayland/xwayland.h26
11 files changed, 946 insertions, 808 deletions
diff --git a/hw/xwayland/Makefile.am b/hw/xwayland/Makefile.am
index 7decc8f06..4abc4692a 100644
--- a/hw/xwayland/Makefile.am
+++ b/hw/xwayland/Makefile.am
@@ -20,6 +20,8 @@ Xwayland_SOURCES = \
xwayland-output.c \
xwayland-cvt.c \
xwayland-vidmode.c \
+ xwayland-window.c \
+ xwayland-window.h \
xwayland-window-buffers.c \
xwayland-window-buffers.h \
xwayland.h \
diff --git a/hw/xwayland/meson.build b/hw/xwayland/meson.build
index d4a408cb4..178f9166e 100644
--- a/hw/xwayland/meson.build
+++ b/hw/xwayland/meson.build
@@ -9,6 +9,8 @@ srcs = [
'xwayland-output.c',
'xwayland-cvt.c',
'xwayland-vidmode.c',
+ 'xwayland-window.c',
+ 'xwayland-window.h',
'xwayland-window-buffers.c',
'xwayland-window-buffers.h',
'../../mi/miinitext.c',
diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
index e1ac22348..6330b1f4c 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -39,6 +39,7 @@
#include "xwayland.h"
#include "xwayland-glamor.h"
+#include "xwayland-window.h"
static void
glamor_egl_make_current(struct glamor_context *glamor_ctx)
diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
index 9c574314d..6bec7f762 100644
--- a/hw/xwayland/xwayland-input.c
+++ b/hw/xwayland/xwayland-input.c
@@ -24,18 +24,28 @@
* SOFTWARE.
*/
-#include "xwayland.h"
+#include <xwayland-config.h>
#include <linux/input.h>
-
#include <sys/mman.h>
+
+#include <inputstr.h>
+#include <exevents.h>
#include <xkbsrv.h>
#include <xserver-properties.h>
#include <inpututils.h>
+#include <mi.h>
#include <mipointer.h>
#include <mipointrst.h>
#include <misc.h>
+
+#include "xwayland.h"
+#include "xwayland-window.h"
+
+#include "pointer-constraints-unstable-v1-client-protocol.h"
+#include "relative-pointer-unstable-v1-client-protocol.h"
#include "tablet-unstable-v2-client-protocol.h"
+#include "xwayland-keyboard-grab-unstable-v1-client-protocol.h"
struct axis_discrete_pending {
struct xorg_list l;
diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c
index da6316930..238bebcdf 100644
--- a/hw/xwayland/xwayland-output.c
+++ b/hw/xwayland/xwayland-output.c
@@ -23,14 +23,16 @@
* SOFTWARE.
*/
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
+#include <xwayland-config.h>
-#include "xwayland.h"
#include <randrstr.h>
#include <X11/Xatom.h>
+#include "xwayland.h"
+#include "xwayland-window.h"
+
+#include "xdg-output-unstable-v1-client-protocol.h"
+
#define DEFAULT_DPI 96
#define ALL_ROTATIONS (RR_Rotate_0 | \
RR_Rotate_90 | \
diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c
index 32fd6d397..1397b4ba4 100644
--- a/hw/xwayland/xwayland-present.c
+++ b/hw/xwayland/xwayland-present.c
@@ -23,11 +23,17 @@
* SOFTWARE.
*/
-#include "xwayland.h"
-#include "glamor.h"
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+#include <windowstr.h>
#include <present.h>
+#include "xwayland.h"
+#include "xwayland-window.h"
+#include "glamor.h"
+
/*
* When not flipping let Present copy with 60fps.
* When flipping wait on frame_callback, otherwise
diff --git a/hw/xwayland/xwayland-window-buffers.c b/hw/xwayland/xwayland-window-buffers.c
index 22fef3ffd..43c887a82 100644
--- a/hw/xwayland/xwayland-window-buffers.c
+++ b/hw/xwayland/xwayland-window-buffers.c
@@ -24,6 +24,11 @@
* Olivier Fourdan <ofourdan@redhat.com>
*/
+#include <xwayland-config.h>
+
+#include "gcstruct.h"
+
+#include "xwayland-window.h"
#include "xwayland-window-buffers.h"
#define BUFFER_TIMEOUT 1 * 1000 /* ms */
diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
new file mode 100644
index 000000000..9246edd02
--- /dev/null
+++ b/hw/xwayland/xwayland-window.c
@@ -0,0 +1,825 @@
+/*
+ * Copyright © 2011-2014 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of the
+ * copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xatom.h>
+
+#include "compositeext.h"
+#include "compint.h"
+#include "inputstr.h"
+#include "propertyst.h"
+
+#include "xwayland-types.h"
+#include "xwayland-window.h"
+#include "xwayland-window-buffers.h"
+#include "xwayland-shm.h"
+#include "xwayland.h"
+
+#include "viewporter-client-protocol.h"
+
+static DevPrivateKeyRec xwl_window_private_key;
+static DevPrivateKeyRec xwl_damage_private_key;
+
+static void
+xwl_window_set_allow_commits(struct xwl_window *xwl_window, Bool allow,
+ const char *debug_msg)
+{
+ xwl_window->allow_commits = allow;
+ DebugF("xwayland: win %d allow_commits = %d (%s)\n",
+ xwl_window->window->drawable.id, allow, debug_msg);
+}
+
+static void
+xwl_window_set_allow_commits_from_property(struct xwl_window *xwl_window,
+ PropertyPtr prop)
+{
+ static Bool warned = FALSE;
+ CARD32 *propdata;
+
+ if (prop->propertyName != xwl_window->xwl_screen->allow_commits_prop)
+ FatalError("Xwayland internal error: prop mismatch in %s.\n", __func__);
+
+ if (prop->type != XA_CARDINAL || prop->format != 32 || prop->size != 1) {
+ /* Not properly set, so fall back to safe and glitchy */
+ xwl_window_set_allow_commits(xwl_window, TRUE, "WM fault");
+
+ if (!warned) {
+ LogMessage(X_WARNING, "Window manager is misusing property %s.\n",
+ NameForAtom(prop->propertyName));
+ warned = TRUE;
+ }
+ return;
+ }
+
+ propdata = prop->data;
+ xwl_window_set_allow_commits(xwl_window, !!propdata[0], "from property");
+}
+
+struct xwl_window *
+xwl_window_get(WindowPtr window)
+{
+ return dixLookupPrivate(&window->devPrivates, &xwl_window_private_key);
+}
+
+static DamagePtr
+window_get_damage(WindowPtr window)
+{
+ return dixLookupPrivate(&window->devPrivates, &xwl_damage_private_key);
+}
+
+struct xwl_window *
+xwl_window_from_window(WindowPtr window)
+{
+ struct xwl_window *xwl_window;
+
+ while (window) {
+ xwl_window = xwl_window_get(window);
+ if (xwl_window)
+ return xwl_window;
+
+ window = window->parent;
+ }
+
+ return NULL;
+}
+
+void
+xwl_window_update_property(struct xwl_window *xwl_window,
+ PropertyStateRec *propstate)
+{
+ switch (propstate->state) {
+ case PropertyNewValue:
+ xwl_window_set_allow_commits_from_property(xwl_window, propstate->prop);
+ break;
+
+ case PropertyDelete:
+ xwl_window_set_allow_commits(xwl_window, TRUE, "property deleted");
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void
+damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
+{
+ WindowPtr window = data;
+ struct xwl_window *xwl_window = xwl_window_get(window);
+ struct xwl_screen *xwl_screen;
+
+ if (!xwl_window)
+ return;
+
+ xwl_screen = xwl_window->xwl_screen;
+
+#ifdef GLAMOR_HAS_GBM
+ if (xwl_window->present_flipped) {
+ /* This damage is from a Present flip, which already committed a new
+ * buffer for the surface, so we don't need to do anything in response
+ */
+ RegionEmpty(DamageRegion(pDamage));
+ xorg_list_del(&xwl_window->link_damage);
+ xwl_window->present_flipped = FALSE;
+ return;
+ }
+#endif
+
+ xorg_list_add(&xwl_window->link_damage, &xwl_screen->damage_window_list);
+}
+
+static void
+damage_destroy(DamagePtr pDamage, void *data)
+{
+}
+
+static Bool
+register_damage(WindowPtr window)
+{
+ DamagePtr damage;
+
+ damage = DamageCreate(damage_report, damage_destroy, DamageReportNonEmpty,
+ FALSE, window->drawable.pScreen, window);
+ if (damage == NULL) {
+ ErrorF("Failed creating damage\n");
+ return FALSE;
+ }
+
+ DamageRegister(&window->drawable, damage);
+ DamageSetReportAfterOp(damage, TRUE);
+
+ dixSetPrivate(&window->devPrivates, &xwl_damage_private_key, damage);
+
+ return TRUE;
+}
+
+static void
+unregister_damage(WindowPtr window)
+{
+ DamagePtr damage;
+
+ damage = dixLookupPrivate(&window->devPrivates, &xwl_damage_private_key);
+ if (!damage)
+ return;
+
+ DamageUnregister(damage);
+ DamageDestroy(damage);
+
+ dixSetPrivate(&window->devPrivates, &xwl_damage_private_key, NULL);
+}
+
+Bool
+xwl_window_has_viewport_enabled(struct xwl_window *xwl_window)
+{
+ return (xwl_window->viewport != NULL);
+}
+
+static void
+xwl_window_disable_viewport(struct xwl_window *xwl_window)
+{
+ assert (xwl_window->viewport);
+
+ DebugF("XWAYLAND: disabling viewport\n");
+ wp_viewport_destroy(xwl_window->viewport);
+ xwl_window->viewport = NULL;
+}
+
+static void
+xwl_window_enable_viewport(struct xwl_window *xwl_window,
+ struct xwl_output *xwl_output,
+ struct xwl_emulated_mode *emulated_mode)
+{
+ /* If necessary disable old viewport to apply new settings */
+ if (xwl_window_has_viewport_enabled(xwl_window))
+ xwl_window_disable_viewport(xwl_window);
+
+ DebugF("XWAYLAND: enabling viewport %dx%d -> %dx%d\n",
+ emulated_mode->width, emulated_mode->height,
+ xwl_output->width, xwl_output->height);
+
+ xwl_window->viewport =
+ wp_viewporter_get_viewport(xwl_window->xwl_screen->viewporter,
+ xwl_window->surface);
+
+ wp_viewport_set_source(xwl_window->viewport,
+ wl_fixed_from_int(0),
+ wl_fixed_from_int(0),
+ wl_fixed_from_int(emulated_mode->width),
+ wl_fixed_from_int(emulated_mode->height));
+ wp_viewport_set_destination(xwl_window->viewport,
+ xwl_output->width,
+ xwl_output->height);
+
+ xwl_window->scale_x = (float)emulated_mode->width / xwl_output->width;
+ xwl_window->scale_y = (float)emulated_mode->height / xwl_output->height;
+}
+
+static Bool
+xwl_screen_client_is_window_manager(struct xwl_screen *xwl_screen,
+ ClientPtr client)
+{
+ WindowPtr root = xwl_screen->screen->root;
+ OtherClients *others;
+
+ for (others = wOtherClients(root); others; others = others->next) {
+ if (SameClient(others, client)) {
+ if (others->mask & (SubstructureRedirectMask | ResizeRedirectMask))
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static ClientPtr
+xwl_window_get_owner(struct xwl_window *xwl_window)
+{
+ WindowPtr window = xwl_window->window;
+ ClientPtr client = wClient(window);
+
+ /* If the toplevel window is owned by the window-manager, then the
+ * actual client toplevel window has been reparented to a window-manager
+ * decoration window. In that case return the client of the
+ * first *and only* child of the toplevel (decoration) window.
+ */
+ if (xwl_screen_client_is_window_manager(xwl_window->xwl_screen, client)) {
+ if (window->firstChild && window->firstChild == window->lastChild)
+ return wClient(window->firstChild);
+ else
+ return NULL; /* Should never happen, skip resolution emulation */
+ }
+
+ return client;
+}
+
+static Bool
+xwl_window_should_enable_viewport(struct xwl_window *xwl_window,
+ struct xwl_output **xwl_output_ret,
+ struct xwl_emulated_mode **emulated_mode_ret)
+{
+ struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
+ struct xwl_emulated_mode *emulated_mode;
+ struct xwl_output *xwl_output;
+ ClientPtr owner;
+
+ if (!xwl_screen_has_resolution_change_emulation(xwl_screen))
+ return FALSE;
+
+ owner = xwl_window_get_owner(xwl_window);
+ if (!owner)
+ return FALSE;
+
+ /* 1. Test if the window matches the emulated mode on one of the outputs
+ * This path gets hit by most games / libs (e.g. SDL, SFML, OGRE)
+ */
+ xorg_list_for_each_entry(xwl_output, &xwl_screen->output_list, link) {
+ emulated_mode = xwl_output_get_emulated_mode_for_client(xwl_output, owner);
+ if (!emulated_mode)
+ continue;
+
+ if (xwl_window->x == xwl_output->x &&
+ xwl_window->y == xwl_output->y &&
+ xwl_window->width == emulated_mode->width &&
+ xwl_window->height == emulated_mode->height) {
+
+ *emulated_mode_ret = emulated_mode;
+ *xwl_output_ret = xwl_output;
+ return TRUE;
+ }
+ }
+
+ /* 2. Test if the window uses override-redirect + vidmode
+ * and matches (fully covers) the entire screen.
+ * This path gets hit by: allegro4, ClanLib-1.0.
+ */
+ xwl_output = xwl_screen_get_first_output(xwl_screen);
+ emulated_mode = xwl_output_get_emulated_mode_for_client(xwl_output, owner);
+ if (xwl_output && xwl_window->window->overrideRedirect &&
+ emulated_mode && emulated_mode->from_vidmode &&
+ xwl_window->x == 0 && xwl_window->y == 0 &&
+ xwl_window->width == xwl_screen->width &&
+ xwl_window->height == xwl_screen->height) {
+
+ *emulated_mode_ret = emulated_mode;
+ *xwl_output_ret = xwl_output;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void
+xwl_window_check_resolution_change_emulation(struct xwl_window *xwl_window)
+{
+ struct xwl_emulated_mode *emulated_mode;
+ struct xwl_output *xwl_output;
+
+ if (xwl_window_should_enable_viewport(xwl_window, &xwl_output, &emulated_mode))
+ xwl_window_enable_viewport(xwl_window, xwl_output, emulated_mode);
+ else if (xwl_window_has_viewport_enabled(xwl_window))
+ xwl_window_disable_viewport(xwl_window);
+}
+
+/* This checks if the passed in Window is a toplevel client window, note this
+ * returns false for window-manager decoration windows and returns true for
+ * the actual client top-level window even if it has been reparented to
+ * a window-manager decoration window.
+ */
+Bool
+xwl_window_is_toplevel(WindowPtr window)
+{
+ struct xwl_screen *xwl_screen = xwl_screen_get(window->drawable.pScreen);
+
+ if (xwl_screen_client_is_window_manager(xwl_screen, wClient(window)))
+ return FALSE;
+
+ /* CSD and override-redirect toplevel windows */
+ if (window_get_damage(window))
+ return TRUE;
+
+ /* Normal toplevel client windows, reparented to decoration window */
+ return (window->parent && window_get_damage(window->parent));
+}
+
+static void
+xwl_window_init_allow_commits(struct xwl_window *xwl_window)
+{
+ PropertyPtr prop = NULL;
+ int ret;
+
+ ret = dixLookupProperty(&prop, xwl_window->window,
+ xwl_window->xwl_screen->allow_commits_prop,
+ serverClient, DixReadAccess);
+ if (ret == Success && prop)
+ xwl_window_set_allow_commits_from_property(xwl_window, prop);
+ else
+ xwl_window_set_allow_commits(xwl_window, TRUE, "no property");
+}
+
+static void
+send_surface_id_event(struct xwl_window *xwl_window)
+{
+ static const char atom_name[] = "WL_SURFACE_ID";
+ static Atom type_atom;
+ DeviceIntPtr dev;
+ xEvent e;
+
+ if (type_atom == None)
+ type_atom = MakeAtom(atom_name, strlen(atom_name), TRUE);
+
+ e.u.u.type = ClientMessage;
+ e.u.u.detail = 32;
+ e.u.clientMessage.window = xwl_window->window->drawable.id;
+ e.u.clientMessage.u.l.type = type_atom;
+ e.u.clientMessage.u.l.longs0 =
+ wl_proxy_get_id((struct wl_proxy *) xwl_window->surface);
+ e.u.clientMessage.u.l.longs1 = 0;
+ e.u.clientMessage.u.l.longs2 = 0;
+ e.u.clientMessage.u.l.longs3 = 0;
+ e.u.clientMessage.u.l.longs4 = 0;
+
+ dev = PickPointer(serverClient);
+ DeliverEventsToWindow(dev, xwl_window->xwl_screen->screen->root,
+ &e, 1, SubstructureRedirectMask, NullGrab);
+}
+
+static void
+shell_surface_ping(void *data,
+ struct wl_shell_surface *shell_surface, uint32_t serial)
+{
+ wl_shell_surface_pong(shell_surface, serial);
+}
+
+static void
+shell_surface_configure(void *data,
+ struct wl_shell_surface *wl_shell_surface,
+ uint32_t edges, int32_t width, int32_t height)
+{
+}
+
+static void
+shell_surface_popup_done(void *data, struct wl_shell_surface *wl_shell_surface)
+{
+}
+
+static const struct wl_shell_surface_listener shell_surface_listener = {
+ shell_surface_ping,
+ shell_surface_configure,
+ shell_surface_popup_done
+};
+
+static Bool
+ensure_surface_for_window(WindowPtr window)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ struct xwl_screen *xwl_screen;
+ struct xwl_window *xwl_window;
+ struct wl_region *region;
+
+ if (xwl_window_get(window))
+ return TRUE;
+
+ xwl_screen = xwl_screen_get(screen);
+
+ if (xwl_screen->rootless) {
+ if (window->redirectDraw != RedirectDrawManual)
+ return TRUE;
+ }
+ else {
+ if (window->parent)
+ return TRUE;
+ }
+
+ xwl_window = calloc(1, sizeof *xwl_window);
+ if (xwl_window == NULL)
+ return FALSE;
+
+ xwl_window->xwl_screen = xwl_screen;
+ xwl_window->window = window;
+ xwl_window->width = window->drawable.width;
+ xwl_window->height = window->drawable.height;
+ xwl_window->surface = wl_compositor_create_surface(xwl_screen->compositor);
+ if (xwl_window->surface == NULL) {
+ ErrorF("wl_display_create_surface failed\n");
+ goto err;
+ }
+
+ if (!xwl_screen->rootless) {
+ xwl_window->shell_surface =
+ wl_shell_get_shell_surface(xwl_screen->shell, xwl_window->surface);
+ if (xwl_window->shell_surface == NULL) {
+ ErrorF("Failed creating shell surface\n");
+ goto err_surf;
+ }
+
+ wl_shell_surface_add_listener(xwl_window->shell_surface,
+ &shell_surface_listener, xwl_window);
+
+ wl_shell_surface_set_toplevel(xwl_window->shell_surface);
+
+ region = wl_compositor_create_region(xwl_screen->compositor);
+ if (region == NULL) {
+ ErrorF("Failed creating region\n");
+ goto err_surf;
+ }
+
+ wl_region_add(region, 0, 0,
+ window->drawable.width, window->drawable.height);
+ wl_surface_set_opaque_region(xwl_window->surface, region);
+ wl_region_destroy(region);
+ }
+
+ wl_display_flush(xwl_screen->display);
+
+ send_surface_id_event(xwl_window);
+
+ wl_surface_set_user_data(xwl_window->surface, xwl_window);
+
+ compRedirectWindow(serverClient, window, CompositeRedirectManual);
+
+ dixSetPrivate(&window->devPrivates, &xwl_window_private_key, xwl_window);
+ xorg_list_init(&xwl_window->link_damage);
+ xorg_list_add(&xwl_window->link_window, &xwl_screen->window_list);
+
+#ifdef GLAMOR_HAS_GBM
+ xorg_list_init(&xwl_window->frame_callback_list);
+#endif
+
+ xwl_window_buffers_init(xwl_window);
+
+ xwl_window_init_allow_commits(xwl_window);
+
+ return TRUE;
+
+err_surf:
+ if (xwl_window->shell_surface)
+ wl_shell_surface_destroy(xwl_window->shell_surface);
+ wl_surface_destroy(xwl_window->surface);
+err:
+ free(xwl_window);
+ return FALSE;
+}
+
+Bool
+xwl_realize_window(WindowPtr window)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ struct xwl_screen *xwl_screen;
+ Bool ret;
+
+ xwl_screen = xwl_screen_get(screen);
+
+ screen->RealizeWindow = xwl_screen->RealizeWindow;
+ ret = (*screen->RealizeWindow) (window);
+ xwl_screen->RealizeWindow = screen->RealizeWindow;
+ screen->RealizeWindow = xwl_realize_window;
+
+ if (!ret)
+ return FALSE;
+
+ if (xwl_screen->rootless && !window->parent) {
+ BoxRec box = { 0, 0, xwl_screen->width, xwl_screen->height };
+
+ RegionReset(&window->winSize, &box);
+ RegionNull(&window->clipList);
+ RegionNull(&window->borderClip);
+ }
+
+ if (xwl_screen->rootless ?
+ (window->drawable.class == InputOutput &&
+ window->parent == window->drawable.pScreen->root) :
+ !window->parent) {
+ if (!register_damage(window))
+ return FALSE;
+ }
+
+ xwl_output_set_window_randr_emu_props(xwl_screen, window);
+
+ return ensure_surface_for_window(window);
+}
+
+Bool
+xwl_unrealize_window(WindowPtr window)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ struct xwl_screen *xwl_screen;
+ struct xwl_window *xwl_window;
+ struct xwl_seat *xwl_seat;
+ Bool ret;
+
+ xwl_screen = xwl_screen_get(screen);
+
+ xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) {
+ if (xwl_seat->focus_window && xwl_seat->focus_window->window == window)
+ xwl_seat->focus_window = NULL;
+ if (xwl_seat->tablet_focus_window && xwl_seat->tablet_focus_window->window == window)
+ xwl_seat->tablet_focus_window = NULL;
+ if (xwl_seat->last_xwindow == window)
+ xwl_seat->last_xwindow = NullWindow;
+ if (xwl_seat->cursor_confinement_window &&
+ xwl_seat->cursor_confinement_window->window == window)
+ xwl_seat_unconfine_pointer(xwl_seat);
+ if (xwl_seat->pointer_warp_emulator &&
+ xwl_seat->pointer_warp_emulator->locked_window &&
+ xwl_seat->pointer_warp_emulator->locked_window->window == window)
+ xwl_seat_destroy_pointer_warp_emulator(xwl_seat);
+ xwl_seat_clear_touch(xwl_seat, window);
+ }
+
+ compUnredirectWindow(serverClient, window, CompositeRedirectManual);
+
+ screen->UnrealizeWindow = xwl_screen->UnrealizeWindow;
+ ret = (*screen->UnrealizeWindow) (window);
+ xwl_screen->UnrealizeWindow = screen->UnrealizeWindow;
+ screen->UnrealizeWindow = xwl_unrealize_window;
+
+ xwl_window = xwl_window_get(window);
+ if (!xwl_window)
+ return ret;
+
+ if (xwl_window_has_viewport_enabled(xwl_window))
+ xwl_window_disable_viewport(xwl_window);
+
+ wl_surface_destroy(xwl_window->surface);
+ xorg_list_del(&xwl_window->link_damage);
+ xorg_list_del(&xwl_window->link_window);
+ unregister_damage(window);
+
+ xwl_window_buffers_dispose(xwl_window);
+
+ if (xwl_window->frame_callback)
+ wl_callback_destroy(xwl_window->frame_callback);
+
+#ifdef GLAMOR_HAS_GBM
+ if (xwl_screen->present)
+ xwl_present_unrealize_window(window);
+#endif
+
+ free(xwl_window);
+ dixSetPrivate(&window->devPrivates, &xwl_window_private_key, NULL);
+
+ return ret;
+}
+
+void
+xwl_window_set_window_pixmap(WindowPtr window,
+ PixmapPtr pixmap)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ struct xwl_screen *xwl_screen;
+ struct xwl_window *xwl_window;
+ PixmapPtr old_pixmap;
+
+ old_pixmap = (*screen->GetWindowPixmap) (window);
+ xwl_screen = xwl_screen_get(screen);
+
+ screen->SetWindowPixmap = xwl_screen->SetWindowPixmap;
+ (*screen->SetWindowPixmap) (window, pixmap);
+ xwl_screen->SetWindowPixmap = screen->SetWindowPixmap;
+ screen->SetWindowPixmap = xwl_window_set_window_pixmap;
+
+ if (!RegionNotEmpty(&window->winSize))
+ return;
+
+ ensure_surface_for_window(window);
+
+ if (old_pixmap->drawable.width == pixmap->drawable.width &&
+ old_pixmap->drawable.height == pixmap->drawable.height)
+ return;
+
+ xwl_window = xwl_window_get(window);
+ if (xwl_window)
+ xwl_window_buffers_recycle(xwl_window);
+}
+
+void
+xwl_resize_window(WindowPtr window,
+ int x, int y,
+ unsigned int width, unsigned int height,
+ WindowPtr sib)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ struct xwl_screen *xwl_screen;
+ struct xwl_window *xwl_window;
+
+ xwl_screen = xwl_screen_get(screen);
+ xwl_window = xwl_window_get(window);
+
+ screen->ResizeWindow = xwl_screen->ResizeWindow;
+ (*screen->ResizeWindow) (window, x, y, width, height, sib);
+ xwl_screen->ResizeWindow = screen->ResizeWindow;
+ screen->ResizeWindow = xwl_resize_window;
+
+ if (xwl_window) {
+ xwl_window->x = x;
+ xwl_window->y = y;
+ xwl_window->width = width;
+ xwl_window->height = height;
+ xwl_window_check_resolution_change_emulation(xwl_window);
+ }
+}
+
+static void
+frame_callback(void *data,
+ struct wl_callback *callback,
+ uint32_t time)
+{
+ struct xwl_window *xwl_window = data;
+
+ wl_callback_destroy (xwl_window->frame_callback);
+ xwl_window->frame_callback = NULL;
+
+#ifdef GLAMOR_HAS_GBM
+ if (xwl_window->xwl_screen->present) {
+ struct xwl_present_window *xwl_present_window, *tmp;
+
+ xorg_list_for_each_entry_safe(xwl_present_window, tmp,
+ &xwl_window->frame_callback_list,
+ frame_callback_list) {
+ xwl_present_frame_callback(xwl_present_window);
+ }
+ }
+#endif
+}
+
+static const struct wl_callback_listener frame_listener = {
+ frame_callback
+};
+
+void
+xwl_window_create_frame_callback(struct xwl_window *xwl_window)
+{
+ xwl_window->frame_callback = wl_surface_frame(xwl_window->surface);
+ wl_callback_add_listener(xwl_window->frame_callback, &frame_listener,
+ xwl_window);
+}
+
+Bool
+xwl_destroy_window(WindowPtr window)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+ Bool ret;
+
+#ifdef GLAMOR_HAS_GBM
+ if (xwl_screen->present)
+ xwl_present_cleanup(window);
+#endif
+
+ screen->DestroyWindow = xwl_screen->DestroyWindow;
+
+ if (screen->DestroyWindow)
+ ret = screen->DestroyWindow (window);
+ else
+ ret = TRUE;
+
+ xwl_screen->DestroyWindow = screen->DestroyWindow;
+ screen->DestroyWindow = xwl_destroy_window;
+
+ return ret;
+}
+
+void xwl_surface_damage(struct xwl_screen *xwl_screen,
+ struct wl_surface *surface,
+ int32_t x, int32_t y, int32_t width, int32_t height)
+{
+ if (wl_surface_get_version(surface) >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION)
+ wl_surface_damage_buffer(surface, x, y, width, height);
+ else
+ wl_surface_damage(surface, x, y, width, height);
+}
+
+void
+xwl_window_post_damage(struct xwl_window *xwl_window)
+{
+ struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
+ RegionPtr region;
+ BoxPtr box;
+ struct wl_buffer *buffer;
+ PixmapPtr pixmap;
+ int i;
+
+ assert(!xwl_window->frame_callback);
+
+ region = DamageRegion(window_get_damage(xwl_window->window));
+ pixmap = xwl_window_buffers_get_pixmap(xwl_window, region);
+
+#ifdef XWL_HAS_GLAMOR
+ if (xwl_screen->glamor)
+ buffer = xwl_glamor_pixmap_get_wl_buffer(pixmap,
+ NULL);
+ else
+#endif
+ buffer = xwl_shm_pixmap_get_wl_buffer(pixmap);
+
+#ifdef XWL_HAS_GLAMOR
+ if (xwl_screen->glamor)
+ xwl_glamor_post_damage(xwl_window, pixmap, region);
+#endif
+
+ wl_surface_attach(xwl_window->surface, buffer, 0, 0);
+
+ /* Arbitrary limit to try to avoid flooding the Wayland
+ * connection. If we flood it too much anyway, this could
+ * abort in libwayland-client.
+ */
+ if (RegionNumRects(region) > 256) {
+ box = RegionExtents(region);
+ xwl_surface_damage(xwl_screen, xwl_window->surface,
+ box->x1 + xwl_window->window->borderWidth,
+ box->y1 + xwl_window->window->borderWidth,
+ box->x2 - box->x1, box->y2 - box->y1);
+ } else {
+ box = RegionRects(region);
+ for (i = 0; i < RegionNumRects(region); i++, box++) {
+ xwl_surface_damage(xwl_screen, xwl_window->surface,
+ box->x1 + xwl_window->window->borderWidth,
+ box->y1 + xwl_window->window->borderWidth,
+ box->x2 - box->x1, box->y2 - box->y1);
+ }
+ }
+
+ xwl_window_create_frame_callback(xwl_window);
+ wl_surface_commit(xwl_window->surface);
+ DamageEmpty(window_get_damage(xwl_window->window));
+
+ xorg_list_del(&xwl_window->link_damage);
+}
+
+Bool
+xwl_window_init(void)
+{
+ if (!dixRegisterPrivateKey(&xwl_window_private_key, PRIVATE_WINDOW, 0))
+ return FALSE;
+
+ if (!dixRegisterPrivateKey(&xwl_damage_private_key, PRIVATE_WINDOW, 0))
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/hw/xwayland/xwayland-window.h b/hw/xwayland/xwayland-window.h
new file mode 100644
index 000000000..873e191f2
--- /dev/null
+++ b/hw/xwayland/xwayland-window.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright © 2011-2014 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of the
+ * copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef XWAYLAND_WINDOW_H
+#define XWAYLAND_WINDOW_H
+
+#include <xwayland-config.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <X11/X.h>
+#include <dix.h>
+#include <propertyst.h>
+
+#include "xwayland-types.h"
+
+struct xwl_window {
+ struct xwl_screen *xwl_screen;
+ struct wl_surface *surface;
+ struct wp_viewport *viewport;
+ int32_t x, y, width, height;
+ float scale_x, scale_y;
+ struct wl_shell_surface *shell_surface;
+ WindowPtr window;
+ struct xorg_list link_damage;
+ struct xorg_list link_window;
+ struct wl_callback *frame_callback;
+ Bool allow_commits;
+ struct xorg_list window_buffers_available;
+ struct xorg_list window_buffers_unavailable;
+ OsTimerPtr window_buffers_timer;
+#ifdef GLAMOR_HAS_GBM
+ struct xorg_list frame_callback_list;
+ Bool present_flipped;
+#endif
+};
+
+struct xwl_window *xwl_window_get(WindowPtr window);
+struct xwl_window *xwl_window_from_window(WindowPtr window);
+
+void xwl_window_update_property(struct xwl_window *xwl_window,
+ PropertyStateRec *propstate);
+Bool xwl_window_has_viewport_enabled(struct xwl_window *xwl_window);
+Bool xwl_window_is_toplevel(WindowPtr window);
+void xwl_window_check_resolution_change_emulation(struct xwl_window *xwl_window);
+
+void xwl_window_set_window_pixmap(WindowPtr window, PixmapPtr pixmap);
+Bool xwl_realize_window(WindowPtr window);
+Bool xwl_unrealize_window(WindowPtr window);
+void xwl_resize_window(WindowPtr window,
+ int x, int y,
+ unsigned int width, unsigned int height,
+ WindowPtr sib);
+Bool xwl_destroy_window(WindowPtr window);
+void xwl_window_post_damage(struct xwl_window *xwl_window);
+void xwl_window_create_frame_callback(struct xwl_window *xwl_window);
+Bool xwl_window_init(void);
+
+#endif /* XWAYLAND_WINDOW_H */
diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c
index 764511d4e..b8f6b4c16 100644
--- a/hw/xwayland/xwayland.c
+++ b/hw/xwayland/xwayland.c
@@ -23,7 +23,6 @@
* SOFTWARE.
*/
-
#include <stdio.h>
#include <X11/Xatom.h>
@@ -40,6 +39,7 @@
#include "xwayland.h"
#include "xwayland-glamor.h"
#include "xwayland-shm.h"
+#include "xwayland-window.h"
#include "xwayland-window-buffers.h"
#ifdef XF86VIDMODE
@@ -170,11 +170,9 @@ ddxProcessArgument(int argc, char *argv[], int i)
}
static DevPrivateKeyRec xwl_client_private_key;
-static DevPrivateKeyRec xwl_window_private_key;
static DevPrivateKeyRec xwl_screen_private_key;
static DevPrivateKeyRec xwl_pixmap_private_key;
static DevPrivateKeyRec xwl_pixmap_cb_private_key;
-static DevPrivateKeyRec xwl_damage_private_key;
struct xwl_client *
xwl_client_get(ClientPtr client)
@@ -182,12 +180,6 @@ xwl_client_get(ClientPtr client)
return dixLookupPrivate(&client->devPrivates, &xwl_client_private_key);
}
-static struct xwl_window *
-xwl_window_get(WindowPtr window)
-{
- return dixLookupPrivate(&window->devPrivates, &xwl_window_private_key);
-}
-
struct xwl_screen *
xwl_screen_get(ScreenPtr screen)
{
@@ -229,59 +221,6 @@ xwl_screen_get_first_output(struct xwl_screen *xwl_screen)
}
static void
-xwl_window_set_allow_commits(struct xwl_window *xwl_window, Bool allow,
- const char *debug_msg)
-{
- xwl_window->allow_commits = allow;
- DebugF("xwayland: win %d allow_commits = %d (%s)\n",
- xwl_window->window->drawable.id, allow, debug_msg);
-}
-
-static void
-xwl_window_set_allow_commits_from_property(struct xwl_window *xwl_window,
- PropertyPtr prop)
-{
- static Bool warned = FALSE;
- CARD32 *propdata;
-
- if (prop->propertyName != xwl_window->xwl_screen->allow_commits_prop)
- FatalError("Xwayland internal error: prop mismatch in %s.\n", __func__);
-
- if (prop->type != XA_CARDINAL || prop->format != 32 || prop->size != 1) {
- /* Not properly set, so fall back to safe and glitchy */
- xwl_window_set_allow_commits(xwl_window, TRUE, "WM fault");
-
- if (!warned) {
- LogMessage(X_WARNING, "Window manager is misusing property %s.\n",
- NameForAtom(prop->propertyName));
- warned = TRUE;
- }
- return;
- }
-
- propdata = prop->data;
- xwl_window_set_allow_commits(xwl_window, !!propdata[0], "from property");
-}
-
-static void
-xwl_window_property_allow_commits(struct xwl_window *xwl_window,
- PropertyStateRec *propstate)
-{
- switch (propstate->state) {
- case PropertyNewValue:
- xwl_window_set_allow_commits_from_property(xwl_window, propstate->prop);
- break;
-
- case PropertyDelete:
- xwl_window_set_allow_commits(xwl_window, TRUE, "property deleted");
- break;
-
- default:
- break;
- }
-}
-
-static void
xwl_property_callback(CallbackListPtr *pcbl, void *closure,
void *calldata)
{
@@ -300,7 +239,7 @@ xwl_property_callback(CallbackListPtr *pcbl, void *closure,
xwl_screen = xwl_screen_get(screen);
if (rec->prop->propertyName == xwl_screen->allow_commits_prop)
- xwl_window_property_allow_commits(xwl_window, rec);
+ xwl_window_update_property(xwl_window, rec);
}
struct xwl_pixmap_buffer_release_cb {
@@ -390,22 +329,6 @@ xwl_close_screen(ScreenPtr screen)
return screen->CloseScreen(screen);
}
-struct xwl_window *
-xwl_window_from_window(WindowPtr window)
-{
- struct xwl_window *xwl_window;
-
- while (window) {
- xwl_window = xwl_window_get(window);
- if (xwl_window)
- return xwl_window;
-
- window = window->parent;
- }
-
- return NULL;
-}
-
static struct xwl_seat *
xwl_screen_get_default_seat(struct xwl_screen *xwl_screen)
{
@@ -499,104 +422,6 @@ xwl_cursor_confined_to(DeviceIntPtr device,
xwl_seat_confine_pointer(xwl_seat, xwl_window);
}
-static void
-damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
-{
- WindowPtr window = data;
- struct xwl_window *xwl_window = xwl_window_get(window);
- struct xwl_screen *xwl_screen;
-
- if (!xwl_window)
- return;
-
- xwl_screen = xwl_window->xwl_screen;
-
-#ifdef GLAMOR_HAS_GBM
- if (xwl_window->present_flipped) {
- /* This damage is from a Present flip, which already committed a new
- * buffer for the surface, so we don't need to do anything in response
- */
- RegionEmpty(DamageRegion(pDamage));
- xorg_list_del(&xwl_window->link_damage);
- xwl_window->present_flipped = FALSE;
- return;
- }
-#endif
-
- xorg_list_add(&xwl_window->link_damage, &xwl_screen->damage_window_list);
-}
-
-static void
-damage_destroy(DamagePtr pDamage, void *data)
-{
-}
-
-static Bool
-register_damage(WindowPtr window)
-{
- DamagePtr damage;
-
- damage = DamageCreate(damage_report, damage_destroy, DamageReportNonEmpty,
- FALSE, window->drawable.pScreen, window);
- if (damage == NULL) {
- ErrorF("Failed creating damage\n");
- return FALSE;
- }
-
- DamageRegister(&window->drawable, damage);
- DamageSetReportAfterOp(damage, TRUE);
-
- dixSetPrivate(&window->devPrivates, &xwl_damage_private_key, damage);
-
- return TRUE;
-}
-
-static void
-unregister_damage(WindowPtr window)
-{
- DamagePtr damage;
-
- damage = dixLookupPrivate(&window->devPrivates, &xwl_damage_private_key);
- if (!damage)
- return;
-
- DamageUnregister(damage);
- DamageDestroy(damage);
-
- dixSetPrivate(&window->devPrivates, &xwl_damage_private_key, NULL);
-}
-
-static DamagePtr
-window_get_damage(WindowPtr window)
-{
- return dixLookupPrivate(&window->devPrivates, &xwl_damage_private_key);
-}
-
-static void
-shell_surface_ping(void *data,
- struct wl_shell_surface *shell_surface, uint32_t serial)
-{
- wl_shell_surface_pong(shell_surface, serial);
-}
-
-static void
-shell_surface_configure(void *data,
- struct wl_shell_surface *wl_shell_surface,
- uint32_t edges, int32_t width, int32_t height)
-{
-}
-
-static void
-shell_surface_popup_done(void *data, struct wl_shell_surface *wl_shell_surface)
-{
-}
-
-static const struct wl_shell_surface_listener shell_surface_listener = {
- shell_surface_ping,
- shell_surface_configure,
- shell_surface_popup_done
-};
-
void
xwl_pixmap_set_private(PixmapPtr pixmap, struct xwl_pixmap *xwl_pixmap)
{
@@ -609,158 +434,6 @@ xwl_pixmap_get(PixmapPtr pixmap)
return dixLookupPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key);
}
-Bool
-xwl_window_has_viewport_enabled(struct xwl_window *xwl_window)
-{
- return (xwl_window->viewport != NULL);
-}
-
-static void
-xwl_window_disable_viewport(struct xwl_window *xwl_window)
-{
- assert (xwl_window->viewport);
-
- DebugF("XWAYLAND: disabling viewport\n");
- wp_viewport_destroy(xwl_window->viewport);
- xwl_window->viewport = NULL;
-}
-
-static void
-xwl_window_enable_viewport(struct xwl_window *xwl_window,
- struct xwl_output *xwl_output,
- struct xwl_emulated_mode *emulated_mode)
-{
- /* If necessary disable old viewport to apply new settings */
- if (xwl_window_has_viewport_enabled(xwl_window))
- xwl_window_disable_viewport(xwl_window);
-
- DebugF("XWAYLAND: enabling viewport %dx%d -> %dx%d\n",
- emulated_mode->width, emulated_mode->height,
- xwl_output->width, xwl_output->height);
-
- xwl_window->viewport =
- wp_viewporter_get_viewport(xwl_window->xwl_screen->viewporter,
- xwl_window->surface);
-
- wp_viewport_set_source(xwl_window->viewport,
- wl_fixed_from_int(0),
- wl_fixed_from_int(0),
- wl_fixed_from_int(emulated_mode->width),
- wl_fixed_from_int(emulated_mode->height));
- wp_viewport_set_destination(xwl_window->viewport,
- xwl_output->width,
- xwl_output->height);
-
- xwl_window->scale_x = (float)emulated_mode->width / xwl_output->width;
- xwl_window->scale_y = (float)emulated_mode->height / xwl_output->height;
-}
-
-static Bool
-xwl_screen_client_is_window_manager(struct xwl_screen *xwl_screen,
- ClientPtr client)
-{
- WindowPtr root = xwl_screen->screen->root;
- OtherClients *others;
-
- for (others = wOtherClients(root); others; others = others->next) {
- if (SameClient(others, client)) {
- if (others->mask & (SubstructureRedirectMask | ResizeRedirectMask))
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-static ClientPtr
-xwl_window_get_owner(struct xwl_window *xwl_window)
-{
- WindowPtr window = xwl_window->window;
- ClientPtr client = wClient(window);
-
- /* If the toplevel window is owned by the window-manager, then the
- * actual client toplevel window has been reparented to a window-manager
- * decoration window. In that case return the client of the
- * first *and only* child of the toplevel (decoration) window.
- */
- if (xwl_screen_client_is_window_manager(xwl_window->xwl_screen, client)) {
- if (window->firstChild && window->firstChild == window->lastChild)
- return wClient(window->firstChild);
- else
- return NULL; /* Should never happen, skip resolution emulation */
- }
-
- return client;
-}
-
-static Bool
-xwl_window_should_enable_viewport(struct xwl_window *xwl_window,
- struct xwl_output **xwl_output_ret,
- struct xwl_emulated_mode **emulated_mode_ret)
-{
- struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
- struct xwl_emulated_mode *emulated_mode;
- struct xwl_output *xwl_output;
- ClientPtr owner;
-
- if (!xwl_screen_has_resolution_change_emulation(xwl_screen))
- return FALSE;
-
- owner = xwl_window_get_owner(xwl_window);
- if (!owner)
- return FALSE;
-
- /* 1. Test if the window matches the emulated mode on one of the outputs
- * This path gets hit by most games / libs (e.g. SDL, SFML, OGRE)
- */
- xorg_list_for_each_entry(xwl_output, &xwl_screen->output_list, link) {
- emulated_mode = xwl_output_get_emulated_mode_for_client(xwl_output, owner);
- if (!emulated_mode)
- continue;
-
- if (xwl_window->x == xwl_output->x &&
- xwl_window->y == xwl_output->y &&
- xwl_window->width == emulated_mode->width &&
- xwl_window->height == emulated_mode->height) {
-
- *emulated_mode_ret = emulated_mode;
- *xwl_output_ret = xwl_output;
- return TRUE;
- }
- }
-
- /* 2. Test if the window uses override-redirect + vidmode
- * and matches (fully covers) the entire screen.
- * This path gets hit by: allegro4, ClanLib-1.0.
- */
- xwl_output = xwl_screen_get_first_output(xwl_screen);
- emulated_mode = xwl_output_get_emulated_mode_for_client(xwl_output, owner);
- if (xwl_output && xwl_window->window->overrideRedirect &&
- emulated_mode && emulated_mode->from_vidmode &&
- xwl_window->x == 0 && xwl_window->y == 0 &&
- xwl_window->width == xwl_screen->width &&
- xwl_window->height == xwl_screen->height) {
-
- *emulated_mode_ret = emulated_mode;
- *xwl_output_ret = xwl_output;
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-xwl_window_check_resolution_change_emulation(struct xwl_window *xwl_window)
-{
- struct xwl_emulated_mode *emulated_mode;
- struct xwl_output *xwl_output;
-
- if (xwl_window_should_enable_viewport(xwl_window, &xwl_output, &emulated_mode))
- xwl_window_enable_viewport(xwl_window, xwl_output, emulated_mode);
- else if (xwl_window_has_viewport_enabled(xwl_window))
- xwl_window_disable_viewport(xwl_window);
-}
-
void
xwl_screen_check_resolution_change_emulation(struct xwl_screen *xwl_screen)
{
@@ -770,447 +443,6 @@ xwl_screen_check_resolution_change_emulation(struct xwl_screen *xwl_screen)
xwl_window_check_resolution_change_emulation(xwl_window);
}
-/* This checks if the passed in Window is a toplevel client window, note this
- * returns false for window-manager decoration windows and returns true for
- * the actual client top-level window even if it has been reparented to
- * a window-manager decoration window.
- */
-Bool
-xwl_window_is_toplevel(WindowPtr window)
-{
- struct xwl_screen *xwl_screen = xwl_screen_get(window->drawable.pScreen);
-
- if (xwl_screen_client_is_window_manager(xwl_screen, wClient(window)))
- return FALSE;
-
- /* CSD and override-redirect toplevel windows */
- if (window_get_damage(window))
- return TRUE;
-
- /* Normal toplevel client windows, reparented to decoration window */
- return (window->parent && window_get_damage(window->parent));
-}
-
-static void
-xwl_window_init_allow_commits(struct xwl_window *xwl_window)
-{
- PropertyPtr prop = NULL;
- int ret;
-
- ret = dixLookupProperty(&prop, xwl_window->window,
- xwl_window->xwl_screen->allow_commits_prop,
- serverClient, DixReadAccess);
- if (ret == Success && prop)
- xwl_window_set_allow_commits_from_property(xwl_window, prop);
- else
- xwl_window_set_allow_commits(xwl_window, TRUE, "no property");
-}
-
-static void
-send_surface_id_event(struct xwl_window *xwl_window)
-{
- static const char atom_name[] = "WL_SURFACE_ID";
- static Atom type_atom;
- DeviceIntPtr dev;
- xEvent e;
-
- if (type_atom == None)
- type_atom = MakeAtom(atom_name, strlen(atom_name), TRUE);
-
- e.u.u.type = ClientMessage;
- e.u.u.detail = 32;
- e.u.clientMessage.window = xwl_window->window->drawable.id;
- e.u.clientMessage.u.l.type = type_atom;
- e.u.clientMessage.u.l.longs0 =
- wl_proxy_get_id((struct wl_proxy *) xwl_window->surface);
- e.u.clientMessage.u.l.longs1 = 0;
- e.u.clientMessage.u.l.longs2 = 0;
- e.u.clientMessage.u.l.longs3 = 0;
- e.u.clientMessage.u.l.longs4 = 0;
-
- dev = PickPointer(serverClient);
- DeliverEventsToWindow(dev, xwl_window->xwl_screen->screen->root,
- &e, 1, SubstructureRedirectMask, NullGrab);
-}
-
-static Bool
-ensure_surface_for_window(WindowPtr window)
-{
- ScreenPtr screen = window->drawable.pScreen;
- struct xwl_screen *xwl_screen;
- struct xwl_window *xwl_window;
- struct wl_region *region;
-
- if (xwl_window_get(window))
- return TRUE;
-
- xwl_screen = xwl_screen_get(screen);
-
- if (xwl_screen->rootless) {
- if (window->redirectDraw != RedirectDrawManual)
- return TRUE;
- }
- else {
- if (window->parent)
- return TRUE;
- }
-
- xwl_window = calloc(1, sizeof *xwl_window);
- if (xwl_window == NULL)
- return FALSE;
-
- xwl_window->xwl_screen = xwl_screen;
- xwl_window->window = window;
- xwl_window->width = window->drawable.width;
- xwl_window->height = window->drawable.height;
- xwl_window->surface = wl_compositor_create_surface(xwl_screen->compositor);
- if (xwl_window->surface == NULL) {
- ErrorF("wl_display_create_surface failed\n");
- goto err;
- }
-
- if (!xwl_screen->rootless) {
- xwl_window->shell_surface =
- wl_shell_get_shell_surface(xwl_screen->shell, xwl_window->surface);
- if (xwl_window->shell_surface == NULL) {
- ErrorF("Failed creating shell surface\n");
- goto err_surf;
- }
-
- wl_shell_surface_add_listener(xwl_window->shell_surface,
- &shell_surface_listener, xwl_window);
-
- wl_shell_surface_set_toplevel(xwl_window->shell_surface);
-
- region = wl_compositor_create_region(xwl_screen->compositor);
- if (region == NULL) {
- ErrorF("Failed creating region\n");
- goto err_surf;
- }
-
- wl_region_add(region, 0, 0,
- window->drawable.width, window->drawable.height);
- wl_surface_set_opaque_region(xwl_window->surface, region);
- wl_region_destroy(region);
- }
-
- wl_display_flush(xwl_screen->display);
-
- send_surface_id_event(xwl_window);
-
- wl_surface_set_user_data(xwl_window->surface, xwl_window);
-
- compRedirectWindow(serverClient, window, CompositeRedirectManual);
-
- dixSetPrivate(&window->devPrivates, &xwl_window_private_key, xwl_window);
- xorg_list_init(&xwl_window->link_damage);
- xorg_list_add(&xwl_window->link_window, &xwl_screen->window_list);
-
-#ifdef GLAMOR_HAS_GBM
- xorg_list_init(&xwl_window->frame_callback_list);
-#endif
-
- xwl_window_buffers_init(xwl_window);
-
- xwl_window_init_allow_commits(xwl_window);
-
- return TRUE;
-
-err_surf:
- if (xwl_window->shell_surface)
- wl_shell_surface_destroy(xwl_window->shell_surface);
- wl_surface_destroy(xwl_window->surface);
-err:
- free(xwl_window);
- return FALSE;
-}
-
-static Bool
-xwl_realize_window(WindowPtr window)
-{
- ScreenPtr screen = window->drawable.pScreen;
- struct xwl_screen *xwl_screen;
- Bool ret;
-
- xwl_screen = xwl_screen_get(screen);
-
- screen->RealizeWindow = xwl_screen->RealizeWindow;
- ret = (*screen->RealizeWindow) (window);
- xwl_screen->RealizeWindow = screen->RealizeWindow;
- screen->RealizeWindow = xwl_realize_window;
-
- if (!ret)
- return FALSE;
-
- if (xwl_screen->rootless && !window->parent) {
- BoxRec box = { 0, 0, xwl_screen->width, xwl_screen->height };
-
- RegionReset(&window->winSize, &box);
- RegionNull(&window->clipList);
- RegionNull(&window->borderClip);
- }
-
- if (xwl_screen->rootless ?
- (window->drawable.class == InputOutput &&
- window->parent == window->drawable.pScreen->root) :
- !window->parent) {
- if (!register_damage(window))
- return FALSE;
- }
-
- xwl_output_set_window_randr_emu_props(xwl_screen, window);
-
- return ensure_surface_for_window(window);
-}
-
-static Bool
-xwl_unrealize_window(WindowPtr window)
-{
- ScreenPtr screen = window->drawable.pScreen;
- struct xwl_screen *xwl_screen;
- struct xwl_window *xwl_window;
- struct xwl_seat *xwl_seat;
- Bool ret;
-
- xwl_screen = xwl_screen_get(screen);
-
- xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) {
- if (xwl_seat->focus_window && xwl_seat->focus_window->window == window)
- xwl_seat->focus_window = NULL;
- if (xwl_seat->tablet_focus_window && xwl_seat->tablet_focus_window->window == window)
- xwl_seat->tablet_focus_window = NULL;
- if (xwl_seat->last_xwindow == window)
- xwl_seat->last_xwindow = NullWindow;
- if (xwl_seat->cursor_confinement_window &&
- xwl_seat->cursor_confinement_window->window == window)
- xwl_seat_unconfine_pointer(xwl_seat);
- if (xwl_seat->pointer_warp_emulator &&
- xwl_seat->pointer_warp_emulator->locked_window &&
- xwl_seat->pointer_warp_emulator->locked_window->window == window)
- xwl_seat_destroy_pointer_warp_emulator(xwl_seat);
- xwl_seat_clear_touch(xwl_seat, window);
- }
-
- compUnredirectWindow(serverClient, window, CompositeRedirectManual);
-
- screen->UnrealizeWindow = xwl_screen->UnrealizeWindow;
- ret = (*screen->UnrealizeWindow) (window);
- xwl_screen->UnrealizeWindow = screen->UnrealizeWindow;
- screen->UnrealizeWindow = xwl_unrealize_window;
-
- xwl_window = xwl_window_get(window);
- if (!xwl_window)
- return ret;
-
- if (xwl_window_has_viewport_enabled(xwl_window))
- xwl_window_disable_viewport(xwl_window);
-
- wl_surface_destroy(xwl_window->surface);
- xorg_list_del(&xwl_window->link_damage);
- xorg_list_del(&xwl_window->link_window);
- unregister_damage(window);
-
- xwl_window_buffers_dispose(xwl_window);
-
- if (xwl_window->frame_callback)
- wl_callback_destroy(xwl_window->frame_callback);
-
-#ifdef GLAMOR_HAS_GBM
- if (xwl_screen->present)
- xwl_present_unrealize_window(window);
-#endif
-
- free(xwl_window);
- dixSetPrivate(&window->devPrivates, &xwl_window_private_key, NULL);
-
- return ret;
-}
-
-static void
-xwl_set_window_pixmap(WindowPtr window,
- PixmapPtr pixmap)
-{
- ScreenPtr screen = window->drawable.pScreen;
- struct xwl_screen *xwl_screen;
- struct xwl_window *xwl_window;
- PixmapPtr old_pixmap;
-
- old_pixmap = (*screen->GetWindowPixmap) (window);
- xwl_screen = xwl_screen_get(screen);
-
- screen->SetWindowPixmap = xwl_screen->SetWindowPixmap;
- (*screen->SetWindowPixmap) (window, pixmap);
- xwl_screen->SetWindowPixmap = screen->SetWindowPixmap;
- screen->SetWindowPixmap = xwl_set_window_pixmap;
-
- if (!RegionNotEmpty(&window->winSize))
- return;
-
- ensure_surface_for_window(window);
-
- if (old_pixmap->drawable.width == pixmap->drawable.width &&
- old_pixmap->drawable.height == pixmap->drawable.height)
- return;
-
- xwl_window = xwl_window_get(window);
- if (xwl_window)
- xwl_window_buffers_recycle(xwl_window);
-}
-
-static void
-xwl_resize_window(WindowPtr window,
- int x, int y,
- unsigned int width, unsigned int height,
- WindowPtr sib)
-{
- ScreenPtr screen = window->drawable.pScreen;
- struct xwl_screen *xwl_screen;
- struct xwl_window *xwl_window;
-
- xwl_screen = xwl_screen_get(screen);
- xwl_window = xwl_window_get(window);
-
- screen->ResizeWindow = xwl_screen->ResizeWindow;
- (*screen->ResizeWindow) (window, x, y, width, height, sib);
- xwl_screen->ResizeWindow = screen->ResizeWindow;
- screen->ResizeWindow = xwl_resize_window;
-
- if (xwl_window) {
- xwl_window->x = x;
- xwl_window->y = y;
- xwl_window->width = width;
- xwl_window->height = height;
- xwl_window_check_resolution_change_emulation(xwl_window);
- }
-}
-
-static void
-frame_callback(void *data,
- struct wl_callback *callback,
- uint32_t time)
-{
- struct xwl_window *xwl_window = data;
-
- wl_callback_destroy (xwl_window->frame_callback);
- xwl_window->frame_callback = NULL;
-
-#ifdef GLAMOR_HAS_GBM
- if (xwl_window->xwl_screen->present) {
- struct xwl_present_window *xwl_present_window, *tmp;
-
- xorg_list_for_each_entry_safe(xwl_present_window, tmp,
- &xwl_window->frame_callback_list,
- frame_callback_list) {
- xwl_present_frame_callback(xwl_present_window);
- }
- }
-#endif
-}
-
-static const struct wl_callback_listener frame_listener = {
- frame_callback
-};
-
-void
-xwl_window_create_frame_callback(struct xwl_window *xwl_window)
-{
- xwl_window->frame_callback = wl_surface_frame(xwl_window->surface);
- wl_callback_add_listener(xwl_window->frame_callback, &frame_listener,
- xwl_window);
-}
-
-static Bool
-xwl_destroy_window(WindowPtr window)
-{
- ScreenPtr screen = window->drawable.pScreen;
- struct xwl_screen *xwl_screen = xwl_screen_get(screen);
- Bool ret;
-
-#ifdef GLAMOR_HAS_GBM
- if (xwl_screen->present)
- xwl_present_cleanup(window);
-#endif
-
- screen->DestroyWindow = xwl_screen->DestroyWindow;
-
- if (screen->DestroyWindow)
- ret = screen->DestroyWindow (window);
- else
- ret = TRUE;
-
- xwl_screen->DestroyWindow = screen->DestroyWindow;
- screen->DestroyWindow = xwl_destroy_window;
-
- return ret;
-}
-
-void xwl_surface_damage(struct xwl_screen *xwl_screen,
- struct wl_surface *surface,
- int32_t x, int32_t y, int32_t width, int32_t height)
-{
- if (wl_surface_get_version(surface) >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION)
- wl_surface_damage_buffer(surface, x, y, width, height);
- else
- wl_surface_damage(surface, x, y, width, height);
-}
-
-static void
-xwl_window_post_damage(struct xwl_window *xwl_window)
-{
- struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
- RegionPtr region;
- BoxPtr box;
- struct wl_buffer *buffer;
- PixmapPtr pixmap;
- int i;
-
- assert(!xwl_window->frame_callback);
-
- region = DamageRegion(window_get_damage(xwl_window->window));
- pixmap = xwl_window_buffers_get_pixmap(xwl_window, region);
-
-#ifdef XWL_HAS_GLAMOR
- if (xwl_screen->glamor)
- buffer = xwl_glamor_pixmap_get_wl_buffer(pixmap,
- NULL);
- else
-#endif
- buffer = xwl_shm_pixmap_get_wl_buffer(pixmap);
-
-#ifdef XWL_HAS_GLAMOR
- if (xwl_screen->glamor)
- xwl_glamor_post_damage(xwl_window, pixmap, region);
-#endif
-
- wl_surface_attach(xwl_window->surface, buffer, 0, 0);
-
- /* Arbitrary limit to try to avoid flooding the Wayland
- * connection. If we flood it too much anyway, this could
- * abort in libwayland-client.
- */
- if (RegionNumRects(region) > 256) {
- box = RegionExtents(region);
- xwl_surface_damage(xwl_screen, xwl_window->surface,
- box->x1 + xwl_window->window->borderWidth,
- box->y1 + xwl_window->window->borderWidth,
- box->x2 - box->x1, box->y2 - box->y1);
- } else {
- box = RegionRects(region);
- for (i = 0; i < RegionNumRects(region); i++, box++) {
- xwl_surface_damage(xwl_screen, xwl_window->surface,
- box->x1 + xwl_window->window->borderWidth,
- box->y1 + xwl_window->window->borderWidth,
- box->x2 - box->x1, box->y2 - box->y1);
- }
- }
-
- xwl_window_create_frame_callback(xwl_window);
- wl_surface_commit(xwl_window->surface);
- DamageEmpty(window_get_damage(xwl_window->window));
-
- xorg_list_del(&xwl_window->link_damage);
-}
-
static void
xwl_screen_post_damage(struct xwl_screen *xwl_screen)
{
@@ -1447,13 +679,11 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
if (!dixRegisterPrivateKey(&xwl_screen_private_key, PRIVATE_SCREEN, 0))
return FALSE;
- if (!dixRegisterPrivateKey(&xwl_window_private_key, PRIVATE_WINDOW, 0))
- return FALSE;
if (!dixRegisterPrivateKey(&xwl_pixmap_private_key, PRIVATE_PIXMAP, 0))
return FALSE;
if (!dixRegisterPrivateKey(&xwl_pixmap_cb_private_key, PRIVATE_PIXMAP, 0))
return FALSE;
- if (!dixRegisterPrivateKey(&xwl_damage_private_key, PRIVATE_WINDOW, 0))
+ if (!xwl_window_init())
return FALSE;
/* There are no easy to use new / delete client hooks, we could use a
* ClientStateCallback, but it is easier to let the dix code manage the
@@ -1603,7 +833,7 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
if (xwl_screen->rootless) {
xwl_screen->SetWindowPixmap = pScreen->SetWindowPixmap;
- pScreen->SetWindowPixmap = xwl_set_window_pixmap;
+ pScreen->SetWindowPixmap = xwl_window_set_window_pixmap;
}
pScreen->CursorWarpedTo = xwl_cursor_warped_to;
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
index 8db682a8f..5b802c0fd 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -123,27 +123,6 @@ struct xwl_screen {
Atom allow_commits_prop;
};
-struct xwl_window {
- struct xwl_screen *xwl_screen;
- struct wl_surface *surface;
- struct wp_viewport *viewport;
- int32_t x, y, width, height;
- float scale_x, scale_y;
- struct wl_shell_surface *shell_surface;
- WindowPtr window;
- struct xorg_list link_damage;
- struct xorg_list link_window;
- struct wl_callback *frame_callback;
- Bool allow_commits;
- struct xorg_list window_buffers_available;
- struct xorg_list window_buffers_unavailable;
- OsTimerPtr window_buffers_timer;
-#ifdef GLAMOR_HAS_GBM
- struct xorg_list frame_callback_list;
- Bool present_flipped;
-#endif
-};
-
#ifdef GLAMOR_HAS_GBM
struct xwl_present_window {
struct xwl_screen *xwl_screen;
@@ -363,9 +342,6 @@ struct xwl_screen *xwl_screen_get(ScreenPtr screen);
Bool xwl_screen_has_resolution_change_emulation(struct xwl_screen *xwl_screen);
struct xwl_output *xwl_screen_get_first_output(struct xwl_screen *xwl_screen);
void xwl_screen_check_resolution_change_emulation(struct xwl_screen *xwl_screen);
-void xwl_window_create_frame_callback(struct xwl_window *xwl_window);
-Bool xwl_window_has_viewport_enabled(struct xwl_window *xwl_window);
-Bool xwl_window_is_toplevel(WindowPtr window);
void xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *tool);
void xwl_seat_set_cursor(struct xwl_seat *xwl_seat);
@@ -417,8 +393,6 @@ Bool xwl_pixmap_set_buffer_release_cb(PixmapPtr pixmap,
void xwl_pixmap_del_buffer_release_cb(PixmapPtr pixmap);
void xwl_pixmap_buffer_release_cb(void *data, struct wl_buffer *wl_buffer);
-struct xwl_window *xwl_window_from_window(WindowPtr window);
-
#ifdef XWL_HAS_GLAMOR
#ifdef GLAMOR_HAS_GBM