xorg-server: Changes to 'ubuntu-xenial'
debian/changelog | 8
debian/patches/xmir.patch | 477 +++++++++++++++++++++++++++++++---------------
2 files changed, 330 insertions(+), 155 deletions(-)
New commits:
commit d4889a21e47bc45b56e7f65feda63090fad3336f
Author: Timo Aaltonen <tjaalton@debian.org>
Date: Wed Sep 14 18:03:32 2016 +0300
close the microrelease bug
diff --git a/debian/changelog b/debian/changelog
index d59d35d..2e0673d 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,6 +1,6 @@
xorg-server (2:1.18.4-0ubuntu0.1) xenial; urgency=medium
- * New upstream bugfix release.
+ * New upstream bugfix release. (LP: #1619142)
* randr-adjust-masters-last-set-time.diff,
randr-do-not-check-the-screen-size.diff:
Fix issues changing display mode on prime setups. (LP: #1586260)
commit 5d680c9cc48b471551ab89c43eb69ccefca83769
Author: Timo Aaltonen <tjaalton@debian.org>
Date: Wed Sep 14 15:41:04 2016 +0300
add new xmir patch based on yakkety
diff --git a/debian/changelog b/debian/changelog
index b50d00e..d59d35d 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -7,6 +7,12 @@ xorg-server (2:1.18.4-0ubuntu0.1) xenial; urgency=medium
* os-treat-ssh-as-a-non-local-client.diff: Dropped, upstream.
* drm_device_keep_trying.patch: Dropped, shouldn't be needed anymore,
and causes issues on non-x86 archs. (LP: #1581076)
+ * debian/patches/xmir.patch: backport XMir fixes from Ubuntu "Yakkety Yak"
+ - fix button/menu focus failures (lp: #1590553)
+ - ignore 'unnkown 11 event' (lp: #1617925)
+ - don't call epoxy every frame (lp: #1617932)
+ - fix unclickable parts of the screen after rotation (lp: #1613708)
+ - fix key repeat issues (lp: #1591356)
-- Timo Aaltonen <tjaalton@debian.org> Thu, 01 Sep 2016 10:28:26 +0300
diff --git a/debian/patches/xmir.patch b/debian/patches/xmir.patch
index 3af0c45..c51aac0 100644
--- a/debian/patches/xmir.patch
+++ b/debian/patches/xmir.patch
@@ -1,4 +1,4 @@
-From d1786a76da403e240abd98f65c95a2d0a242b495 Mon Sep 17 00:00:00 2001
+From 8467ede06b3b40fae1d362d73cfa313737e0defc Mon Sep 17 00:00:00 2001
From: Robert Ancell <robert.ancell@canonical.com>
Date: Fri, 29 Apr 2016 14:57:53 +0200
Subject: [PATCH xserver 1/3] XMir DDX
@@ -16,20 +16,20 @@ Contributions from:
hw/xmir/.gitignore | 1 +
hw/xmir/Makefile.am | 61 ++
hw/xmir/dri2/Makefile.am | 14 +
- hw/xmir/dri2/dri2.c | 1398 ++++++++++++++++++++++++++++++++++++++
- hw/xmir/dri2/dri2.h | 364 ++++++++++
- hw/xmir/dri2/dri2ext.c | 683 +++++++++++++++++++
+ hw/xmir/dri2/dri2.c | 1398 ++++++++++++++++++++++++++++++++++
+ hw/xmir/dri2/dri2.h | 364 +++++++++
+ hw/xmir/dri2/dri2ext.c | 683 +++++++++++++++++
hw/xmir/dri2/dri2int.h | 26 +
hw/xmir/xmir-cursor.c | 210 ++++++
- hw/xmir/xmir-cvt.c | 304 +++++++++
- hw/xmir/xmir-dri2.c | 545 +++++++++++++++
- hw/xmir/xmir-glamor.c | 1160 ++++++++++++++++++++++++++++++++
- hw/xmir/xmir-input.c | 592 ++++++++++++++++
- hw/xmir/xmir-output.c | 449 +++++++++++++
- hw/xmir/xmir-thread-proxy.c | 109 +++
- hw/xmir/xmir.c | 1571 +++++++++++++++++++++++++++++++++++++++++++
- hw/xmir/xmir.h | 226 +++++++
- 18 files changed, 7745 insertions(+), 2 deletions(-)
+ hw/xmir/xmir-cvt.c | 304 ++++++++
+ hw/xmir/xmir-dri2.c | 551 ++++++++++++++
+ hw/xmir/xmir-glamor.c | 1164 +++++++++++++++++++++++++++++
+ hw/xmir/xmir-input.c | 611 +++++++++++++++
+ hw/xmir/xmir-output.c | 476 ++++++++++++
+ hw/xmir/xmir-thread-proxy.c | 115 +++
+ hw/xmir/xmir.c | 1729 +++++++++++++++++++++++++++++++++++++++++++
+ hw/xmir/xmir.h | 232 ++++++
+ 18 files changed, 7971 insertions(+), 2 deletions(-)
create mode 100644 hw/xmir/.gitignore
create mode 100644 hw/xmir/Makefile.am
create mode 100644 hw/xmir/dri2/Makefile.am
@@ -47,11 +47,9 @@ Contributions from:
create mode 100644 hw/xmir/xmir.c
create mode 100644 hw/xmir/xmir.h
-diff --git a/configure.ac b/configure.ac
-index 77cf234..8bf62a0 100644
--- a/configure.ac
+++ b/configure.ac
-@@ -628,6 +628,7 @@ AC_ARG_ENABLE(xvfb, AS_HELP_STRING([--enable-xvfb], [Build Xvfb server
+@@ -633,6 +633,7 @@
AC_ARG_ENABLE(xnest, AS_HELP_STRING([--enable-xnest], [Build Xnest server (default: auto)]), [XNEST=$enableval], [XNEST=auto])
AC_ARG_ENABLE(xquartz, AS_HELP_STRING([--enable-xquartz], [Build Xquartz server for OS-X (default: auto)]), [XQUARTZ=$enableval], [XQUARTZ=auto])
AC_ARG_ENABLE(xwayland, AS_HELP_STRING([--enable-xwayland], [Build Xwayland server (default: auto)]), [XWAYLAND=$enableval], [XWAYLAND=auto])
@@ -59,7 +57,7 @@ index 77cf234..8bf62a0 100644
AC_ARG_ENABLE(standalone-xpbproxy, AS_HELP_STRING([--enable-standalone-xpbproxy], [Build a standalone xpbproxy (in addition to the one integrated into Xquartz as a separate thread) (default: no)]), [STANDALONE_XPBPROXY=$enableval], [STANDALONE_XPBPROXY=no])
AC_ARG_ENABLE(xwin, AS_HELP_STRING([--enable-xwin], [Build XWin server (default: auto)]), [XWIN=$enableval], [XWIN=auto])
AC_ARG_ENABLE(glamor, AS_HELP_STRING([--enable-glamor], [Build glamor dix module (default: no)]), [GLAMOR=$enableval], [GLAMOR=no])
-@@ -746,6 +747,7 @@ case $host_os in
+@@ -751,6 +752,7 @@
XVFB=no
XNEST=no
XWAYLAND=no
@@ -67,7 +65,7 @@ index 77cf234..8bf62a0 100644
COMPOSITE=no
DGA=no
-@@ -2482,6 +2484,27 @@ if test "x$XWAYLAND" = xyes; then
+@@ -2503,6 +2505,27 @@
[${WAYLAND_PREFIX}/bin$PATH_SEPARATOR$PATH])
fi
@@ -95,7 +93,7 @@ index 77cf234..8bf62a0 100644
dnl and the rest of these are generic, so they're in config.h
dnl
-@@ -2630,6 +2653,8 @@ hw/kdrive/fbdev/Makefile
+@@ -2651,6 +2674,8 @@
hw/kdrive/linux/Makefile
hw/kdrive/src/Makefile
hw/xwayland/Makefile
@@ -104,11 +102,9 @@ index 77cf234..8bf62a0 100644
test/Makefile
test/xi1/Makefile
test/xi2/Makefile
-diff --git a/hw/Makefile.am b/hw/Makefile.am
-index 19895dc..b7b958c 100644
--- a/hw/Makefile.am
+++ b/hw/Makefile.am
-@@ -30,6 +30,10 @@ if XWAYLAND
+@@ -30,6 +30,10 @@
XWAYLAND_SUBDIRS = xwayland
endif
@@ -119,7 +115,7 @@ index 19895dc..b7b958c 100644
SUBDIRS = \
$(XORG_SUBDIRS) \
$(XWIN_SUBDIRS) \
-@@ -38,9 +42,10 @@ SUBDIRS = \
+@@ -38,9 +42,10 @@
$(DMX_SUBDIRS) \
$(KDRIVE_SUBDIRS) \
$(XQUARTZ_SUBDIRS) \
@@ -132,16 +128,10 @@ index 19895dc..b7b958c 100644
relink:
$(AM_V_at)for i in $(SUBDIRS) ; do $(MAKE) -C $$i relink || exit 1 ; done
-diff --git a/hw/xmir/.gitignore b/hw/xmir/.gitignore
-new file mode 100644
-index 0000000..b6a16d4
--- /dev/null
+++ b/hw/xmir/.gitignore
@@ -0,0 +1 @@
+Xmir
-diff --git a/hw/xmir/Makefile.am b/hw/xmir/Makefile.am
-new file mode 100644
-index 0000000..be5225e
--- /dev/null
+++ b/hw/xmir/Makefile.am
@@ -0,0 +1,61 @@
@@ -206,9 +196,6 @@ index 0000000..be5225e
+
+relink:
+ $(AM_V_at)rm -f Xmir$(EXEEXT) && $(MAKE) Xmir$(EXEEXT)
-diff --git a/hw/xmir/dri2/Makefile.am b/hw/xmir/dri2/Makefile.am
-new file mode 100644
-index 0000000..696240c
--- /dev/null
+++ b/hw/xmir/dri2/Makefile.am
@@ -0,0 +1,14 @@
@@ -226,9 +213,6 @@ index 0000000..696240c
+ dri2ext.c \
+ dri2int.h
+
-diff --git a/hw/xmir/dri2/dri2.c b/hw/xmir/dri2/dri2.c
-new file mode 100644
-index 0000000..6aa19ba
--- /dev/null
+++ b/hw/xmir/dri2/dri2.c
@@ -0,0 +1,1398 @@
@@ -1630,9 +1614,6 @@ index 0000000..6aa19ba
+ *is_param_recognized = FALSE;
+ return Success;
+}
-diff --git a/hw/xmir/dri2/dri2.h b/hw/xmir/dri2/dri2.h
-new file mode 100644
-index 0000000..318898b
--- /dev/null
+++ b/hw/xmir/dri2/dri2.h
@@ -0,0 +1,364 @@
@@ -2000,9 +1981,6 @@ index 0000000..318898b
+extern Bool noDRI2Extension;
+
+#endif
-diff --git a/hw/xmir/dri2/dri2ext.c b/hw/xmir/dri2/dri2ext.c
-new file mode 100644
-index 0000000..befbb82
--- /dev/null
+++ b/hw/xmir/dri2/dri2ext.c
@@ -0,0 +1,683 @@
@@ -2689,9 +2667,6 @@ index 0000000..befbb82
+
+ DRI2ModuleSetup();
+}
-diff --git a/hw/xmir/dri2/dri2int.h b/hw/xmir/dri2/dri2int.h
-new file mode 100644
-index 0000000..7f53eba
--- /dev/null
+++ b/hw/xmir/dri2/dri2int.h
@@ -0,0 +1,26 @@
@@ -2721,9 +2696,6 @@ index 0000000..7f53eba
+ */
+
+extern Bool DRI2ModuleSetup(void);
-diff --git a/hw/xmir/xmir-cursor.c b/hw/xmir/xmir-cursor.c
-new file mode 100644
-index 0000000..81873a4
--- /dev/null
+++ b/hw/xmir/xmir-cursor.c
@@ -0,0 +1,210 @@
@@ -2937,9 +2909,6 @@ index 0000000..81873a4
+ &xmir_pointer_sprite_funcs,
+ &xmir_pointer_screen_funcs, TRUE);
+}
-diff --git a/hw/xmir/xmir-cvt.c b/hw/xmir/xmir-cvt.c
-new file mode 100644
-index 0000000..6070d77
--- /dev/null
+++ b/hw/xmir/xmir-cvt.c
@@ -0,0 +1,304 @@
@@ -3247,12 +3216,9 @@ index 0000000..6070d77
+
+ return RRModeGet(&modeinfo, name);
+}
-diff --git a/hw/xmir/xmir-dri2.c b/hw/xmir/xmir-dri2.c
-new file mode 100644
-index 0000000..b24d4b9
--- /dev/null
+++ b/hw/xmir/xmir-dri2.c
-@@ -0,0 +1,545 @@
+@@ -0,0 +1,551 @@
+/*
+ * Copyright © 2015 Canonical Ltd
+ *
@@ -3744,10 +3710,16 @@ index 0000000..b24d4b9
+
+static int xmir_dri_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
+{
-+ /* TODO: Implement this?
-+ * At least doing nothing like this is enough to shut up Chromium
-+ * error messages.
-+ */
++ /* TODO: Implement this properly after Mir implements it. */
++ const uint64_t now_us = GetTimeInMicros();
++ const uint64_t fake_frame_rate_hz = 60;
++ const uint64_t fake_frame_time_us = 1000000 / fake_frame_rate_hz;
++ const uint64_t fake_msc = now_us / fake_frame_time_us;
++ const uint64_t fake_ust = fake_msc * fake_frame_time_us;
++ if (ust)
++ *(uint64_t*)ust = fake_ust;
++ if (msc)
++ *(uint64_t*)msc = fake_msc;
+ return Success;
+}
+
@@ -3798,12 +3770,9 @@ index 0000000..b24d4b9
+ ret = DRI2ScreenInit(xmir_screen->screen, &xmir_screen->dri2);
+ return ret;
+}
-diff --git a/hw/xmir/xmir-glamor.c b/hw/xmir/xmir-glamor.c
-new file mode 100644
-index 0000000..7ad0245
--- /dev/null
+++ b/hw/xmir/xmir-glamor.c
-@@ -0,0 +1,1160 @@
+@@ -0,0 +1,1164 @@
+/*
+ * Copyright © 2015 Canonical Ltd
+ *
@@ -4163,7 +4132,8 @@ index 0000000..7ad0245
+ struct xmir_screen *xmir_screen = xmir_screen_get(src->pScreen);
+ DebugF("Box: (%i,%i)->(%i,%i)\n", ext->x1, ext->y1, ext->x2, ext->y2);
+
-+ if (epoxy_has_gl_extension("GL_EXT_framebuffer_blit") && !xmir_screen->doubled && !orientation) {
++ if (xmir_screen->glamor_has_GL_EXT_framebuffer_blit &&
++ !xmir_screen->doubled && !orientation) {
+ glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, src_pixmap_priv->fbo->fb);
+
+ glBlitFramebuffer(ext->x1, ext->y2, ext->x2, ext->y1,
@@ -4642,6 +4612,9 @@ index 0000000..7ad0245
+ return FALSE;
+ }
+
++ xmir_screen->glamor_has_GL_EXT_framebuffer_blit =
++ epoxy_has_gl_extension("GL_EXT_framebuffer_blit");
++
+ if (!xmir_screen->gbm && xmir_screen->glamor != glamor_egl_sync) {
+ xmir_screen->swap_context = eglCreateContext(xmir_screen->egl_display, egl_config, EGL_NO_CONTEXT, gles2_attribs);
+ if (!xmir_screen->swap_context) {
@@ -4964,12 +4937,9 @@ index 0000000..7ad0245
+
+ return TRUE;
+}
-diff --git a/hw/xmir/xmir-input.c b/hw/xmir/xmir-input.c
-new file mode 100644
-index 0000000..14c4709
--- /dev/null
+++ b/hw/xmir/xmir-input.c
-@@ -0,0 +1,592 @@
+@@ -0,0 +1,609 @@
+/*
+ * Copyright © 2015 Canonical Ltd
+ *
@@ -5014,7 +4984,7 @@ index 0000000..14c4709
+xmir_pointer_proc(DeviceIntPtr device, int what)
+{
+#define NBUTTONS 10
-+#define NAXES 2
++#define NAXES 4
+ BYTE map[NBUTTONS + 1];
+ int i = 0;
+ Atom btn_labels[NBUTTONS] = { 0 };
@@ -5038,8 +5008,10 @@ index 0000000..14c4709
+
+ axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X);
+ axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y);
++ axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HWHEEL);
++ axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_WHEEL);
+
-+ if (!InitValuatorClassDeviceStruct(device, 2, btn_labels,
++ if (!InitValuatorClassDeviceStruct(device, NAXES, btn_labels,
+ GetMotionHistorySize(), Absolute))
+ return BadValue;
+
@@ -5048,6 +5020,13 @@ index 0000000..14c4709
+ 0, 0xFFFF, 10000, 0, 10000, Absolute);
+ InitValuatorAxisStruct(device, 1, axes_labels[1],
+ 0, 0xFFFF, 10000, 0, 10000, Absolute);
++ InitValuatorAxisStruct(device, 2, axes_labels[2],
++ NO_AXIS_LIMITS, NO_AXIS_LIMITS, 0, 0, 0, Relative);
++ InitValuatorAxisStruct(device, 3, axes_labels[3],
++ NO_AXIS_LIMITS, NO_AXIS_LIMITS, 0, 0, 0, Relative);
++
++ SetScrollValuator(device, 2, SCROLL_TYPE_HORIZONTAL, 1.0, SCROLL_FLAG_NONE);
++ SetScrollValuator(device, 3, SCROLL_TYPE_VERTICAL, 1.0, SCROLL_FLAG_PREFERRED);
+
+ if (!InitPtrFeedbackClassDeviceStruct(device, xmir_pointer_control))
+ return BadValue;
@@ -5192,7 +5171,7 @@ index 0000000..14c4709
+{
+ int sx = mir_pointer_event_axis_value(pev, mir_pointer_axis_x);
+ int sy = mir_pointer_event_axis_value(pev, mir_pointer_axis_y);
-+ int vscroll = 0;
++ float vscroll, hscroll;
+ ValuatorMask mask;
+
+ pointer_ensure_focus(xmir_input, xmir_window, xmir_input->pointer, sx, sy);
@@ -5202,17 +5181,17 @@ index 0000000..14c4709
+ valuator_mask_zero(&mask);
+ valuator_mask_set(&mask, 0, sx);
+ valuator_mask_set(&mask, 1, sy);
-+
+ QueuePointerEvents(xmir_input->pointer, MotionNotify, 0,
+ POINTER_ABSOLUTE | POINTER_SCREEN, &mask);
+
-+ /* Mouse wheel: Moving the wheel is a press+release of button 4/5 */
+ vscroll = mir_pointer_event_axis_value(pev, mir_pointer_axis_vscroll);
-+ if (vscroll) {
-+ int button = vscroll < 0 ? 5 : 4;
++ hscroll = mir_pointer_event_axis_value(pev, mir_pointer_axis_hscroll);
++ if (vscroll || hscroll) {
+ valuator_mask_zero(&mask);
-+ QueuePointerEvents(xmir_input->pointer, ButtonPress, button, 0, &mask);
-+ QueuePointerEvents(xmir_input->pointer, ButtonRelease, button, 0, &mask);
++ valuator_mask_set_double(&mask, 3, -vscroll);
++ valuator_mask_set_double(&mask, 2, hscroll);
++ QueuePointerEvents(xmir_input->pointer, MotionNotify, 0,
++ POINTER_RELATIVE, &mask);
+ }
+}
+
@@ -5348,15 +5327,23 @@ index 0000000..14c4709
+{
+ switch (mir_input_event_get_type(ev)) {
+ case mir_input_event_type_key: {
-+ MirKeyboardEvent const *kev;
-+ MirKeyboardAction action;
++ MirKeyboardEvent const *kev = mir_input_event_get_keyboard_event(ev);
++ MirKeyboardAction action = mir_keyboard_event_action(kev);
++ int code = mir_keyboard_event_scan_code(kev) + 8;
+
-+ kev = mir_input_event_get_keyboard_event(ev);
-+ action = mir_keyboard_event_action(kev);
-+
-+ QueueKeyboardEvents(xmir_input->keyboard,
-+ action == mir_keyboard_action_up ? KeyRelease : KeyPress,
-+ mir_keyboard_event_scan_code(kev) + 8);
++ /*
++ * Note: mir_keyboard_action_repeat must KeyRelease then KeyPress
++ * because it is already preceded by mir_keyboard_action_down and will
++ * be followed by mir_keyboard_action_up.
++ */
++ if (action == mir_keyboard_action_up ||
++ action == mir_keyboard_action_repeat) {
++ QueueKeyboardEvents(xmir_input->keyboard, KeyRelease, code);
++ }
++ if (action == mir_keyboard_action_down ||
++ action == mir_keyboard_action_repeat) {
++ QueueKeyboardEvents(xmir_input->keyboard, KeyPress, code);
++ }
+ break;
+ }
+ case mir_input_event_type_touch: {
@@ -5562,12 +5549,9 @@ index 0000000..14c4709
+
+ mieqFini();
+}
-diff --git a/hw/xmir/xmir-output.c b/hw/xmir/xmir-output.c
-new file mode 100644
-index 0000000..f538749
--- /dev/null
+++ b/hw/xmir/xmir-output.c
-@@ -0,0 +1,449 @@
+@@ -0,0 +1,476 @@
+/*
+ * Copyright © 2015 Canonical Ltd
+ *
@@ -5692,8 +5676,8 @@ index 0000000..f538749
+ /* Odd resolutions like 1366x768 don't show correctly otherwise */
+ randr_mode->mode.width = mode->horizontal_resolution;
+ randr_mode->mode.height = mode->vertical_resolution;
-+ sprintf(randr_mode->name, "%dx%d@%.1fHz",
-+ randr_mode->mode.width, randr_mode->mode.height, mode->refresh_rate);
++ sprintf(randr_mode->name, "%dx%d",
++ randr_mode->mode.width, randr_mode->mode.height);
+
+ RROutputSetPhysicalSize(xmir_output->randr_output, mir_output->physical_width_mm, mir_output->physical_height_mm);
+ RROutputSetModes(xmir_output->randr_output, &randr_mode, 1, 1);
@@ -5714,6 +5698,33 @@ index 0000000..f538749
+}
+
+static void
++xmir_screen_update_windowed_output(struct xmir_screen *xmir_screen)
++{
++ struct xmir_output *xmir_output = xmir_screen->windowed;
++ RRModePtr randr_mode;
++
++ RROutputSetConnection(xmir_output->randr_output, RR_Connected);
++ RROutputSetSubpixelOrder(xmir_output->randr_output, SubPixelUnknown);
++
++ xmir_output->width = xmir_screen->screen->width;
++ xmir_output->height = xmir_screen->screen->height;
++ xmir_output->x = 0;
++ xmir_output->y = 0;
++
++ randr_mode = xmir_cvt(xmir_output->width, xmir_output->height, 60, 0, 0);
++ randr_mode->mode.width = xmir_output->width;
++ randr_mode->mode.height = xmir_output->height;
++ sprintf(randr_mode->name, "%dx%d",
++ randr_mode->mode.width, randr_mode->mode.height);
++
++ RROutputSetPhysicalSize(xmir_output->randr_output, 0, 0);
++ RROutputSetModes(xmir_output->randr_output, &randr_mode, 1, 1);
++ RRCrtcNotify(xmir_output->randr_crtc, randr_mode,
++ xmir_output->x, xmir_output->y,
++ RR_Rotate_0, NULL, 1, &xmir_output->randr_output);
++}
++
++static void
+xmir_output_screen_resized(struct xmir_screen *xmir_screen)
+{
+ ScreenPtr screen = xmir_screen->screen;
@@ -5736,15 +5747,15 @@ index 0000000..f538749
+ update_desktop_dimensions();
+}
+
-+static void
-+xmir_output_create(struct xmir_screen *xmir_screen, MirDisplayOutput *mir_output, const char *name)
++static struct xmir_output*
++xmir_output_create(struct xmir_screen *xmir_screen, const char *name)
+{
+ struct xmir_output *xmir_output;
+
+ xmir_output = calloc(sizeof *xmir_output, 1);
+ if (xmir_output == NULL) {
+ FatalError("No memory for creating output\n");
-+ return;
++ return NULL;
+ }
+
+ xmir_output->xmir_screen = xmir_screen;
@@ -5754,8 +5765,7 @@ index 0000000..f538749
+ RRCrtcGammaSetSize(xmir_output->randr_crtc, 256);
+ RROutputSetCrtcs(xmir_output->randr_output, &xmir_output->randr_crtc, 1);
+ xorg_list_append(&xmir_output->link, &xmir_screen->output_list);
-+ if (mir_output)
-+ xmir_output_update(xmir_output, mir_output);
++ return xmir_output;
+}
+
+void
@@ -5873,8 +5883,6 @@ index 0000000..f538749
+ return;
+
+ if (!xmir_screen->windowed) {
-+ xmir_screen->windowed = 1;
-+
+ XMIR_DEBUG(("Root resized, removing all outputs and inserting fake output\n"));
+
+ while (!xorg_list_is_empty(&xmir_screen->output_list)) {
@@ -5884,6 +5892,8 @@ index 0000000..f538749
+ RROutputDestroy(xmir_output->randr_output);
+ xmir_output_destroy(xmir_output);
+ }
++
++ xmir_screen->windowed = xmir_output_create(xmir_screen, "Windowed");
+ }
+
+ XMIR_DEBUG(("Output resized %ix%i with rotation %i\n",
@@ -5918,16 +5928,12 @@ index 0000000..f538749
+ int y;
+ for (y = copy_box.y1; y < copy_box.y2; ++y) {
+ memcpy(dst, src, line_len);
-+ /* Bother filling the edges?
+ memset(dst+line_len, 0, dst_stride-line_len);
-+ */
+ src += src_stride;
+ dst += dst_stride;
+ }
-+ /* Bother filling the edges?
+ if (y < window_height)
+ memset(dst, 0, (window_height - y) * dst_stride);
-+ */
+ }
+
+ screen->width = window_width;
@@ -5937,7 +5943,7 @@ index 0000000..f538749
+
+ screen->SetScreenPixmap(pixmap);
+
-+ SetRootClip(screen, TRUE);
++ SetRootClip(screen, ROOT_CLIP_FULL);
+
+ box.x1 = box.y1 = 0;
+ box.x2 = window_width;
@@ -5957,6 +5963,7 @@ index 0000000..f538749
+ miPointerSetScreen(pDev, 0, x, y);
+ }
+
++ xmir_screen_update_windowed_output(xmir_screen);
+ if (ConnectionInfo)
+ RRScreenSizeNotify(xmir_screen->screen);
+ update_desktop_dimensions();
@@ -5996,6 +6003,7 @@ index 0000000..f538749
+ for (i = 0; i < display_config->num_outputs; i++) {
+ char name[32];
+ MirDisplayOutput *mir_output = &display_config->outputs[i];
++ struct xmir_output *xmir_output;
+ const char* output_type_str = xmir_get_output_type_str(mir_output);
+ int type_count = i;
+
@@ -6003,7 +6011,10 @@ index 0000000..f538749
+ type_count = output_type_count[mir_output->type]++;
+
+ snprintf(name, sizeof name, "%s-%d", output_type_str, type_count);
-+ xmir_output_create(xmir_screen, mir_output, name);
++ xmir_output = xmir_output_create(xmir_screen, name);
++ if (!xmir_output)
++ return FALSE;
++ xmir_output_update(xmir_output, mir_output);
+ }
+
+ RRScreenSetSizeRange(xmir_screen->screen, 320, 200, INT16_MAX, INT16_MAX);
@@ -6017,12 +6028,9 @@ index 0000000..f538749
+
+ return TRUE;
+}
-diff --git a/hw/xmir/xmir-thread-proxy.c b/hw/xmir/xmir-thread-proxy.c
-new file mode 100644
-index 0000000..dbb187f
--- /dev/null
+++ b/hw/xmir/xmir-thread-proxy.c
-@@ -0,0 +1,109 @@
+@@ -0,0 +1,115 @@
+/*
+ * Copyright © 2012-2015 Canonical Ltd
+ *
@@ -6121,23 +6129,26 @@ index 0000000..dbb187f
+}
+
+void
-+xmir_process_from_eventloop(void)
++xmir_process_from_eventloop_except(const struct xmir_window *w)
+{
+ for (;;) {
+ struct message msg;
+ ssize_t got = read(pipefds[0], &msg, sizeof msg);
+ if (got < 0)
+ return;
-+ if (got == sizeof(msg))
++ if (got == sizeof(msg) && w != msg.xmir_window)
+ msg.callback(msg.xmir_screen, msg.xmir_window, msg.arg);
+ }
+}
-diff --git a/hw/xmir/xmir.c b/hw/xmir/xmir.c
-new file mode 100644
-index 0000000..34f78c9
++
++void
++xmir_process_from_eventloop(void)
++{
++ xmir_process_from_eventloop_except(NULL);
++}
--- /dev/null
+++ b/hw/xmir/xmir.c
-@@ -0,0 +1,1571 @@
+@@ -0,0 +1,1729 @@
+/*
+ * Copyright © 2015 Canonical Ltd
+ *
@@ -6204,19 +6215,21 @@ index 0000000..34f78c9
+ Atom _NET_WM_WINDOW_TYPE_COMBO;
+ Atom _NET_WM_WINDOW_TYPE_DND;
+ Atom _NET_WM_WINDOW_TYPE_NORMAL;
++ Atom _MIR_WM_PERSISTENT_ID;
+} known_atom;
+
-+static Atom get_atom(const char *name, Atom *cache)
++static Atom get_atom(const char *name, Atom *cache, Bool create)
+{
+ if (!*cache) {
-+ *cache = MakeAtom(name, strlen(name), False);
++ *cache = MakeAtom(name, strlen(name), create);
+ if (*cache)
+ XMIR_DEBUG(("Atom %s = %lu\n", name, (unsigned long)*cache));
+ }
+ return *cache;
+}
+
-+#define GET_ATOM(_a) get_atom(#_a, &known_atom._a)
++#define GET_ATOM(_a) get_atom(#_a, &known_atom._a, False)
++#define MAKE_ATOM(_a) get_atom(#_a, &known_atom._a, True)
+
+extern __GLXprovider __glXDRI2Provider;
+
@@ -6224,6 +6237,12 @@ index 0000000..34f78c9
+
+static const char get_title_from_top_window[] = "@";
+
++struct xmir_swap {
++ int server_generation;
++ struct xmir_screen *xmir_screen;
++ struct xmir_window *xmir_window;
++};
++
+static void xmir_handle_buffer_received(MirBufferStream *stream, void *ctx);
+
+/* Required by GLX module */
@@ -6273,9 +6292,7 @@ index 0000000..34f78c9
+{
+ ErrorF("-rootless Run rootless\n");
+ ErrorF(" -flatten Flatten rootless X windows into a single surface\n");
-+ ErrorF(" (Unity8 requires -flatten; LP: #1497085)\n");
+ ErrorF(" -neverclose Never close the flattened rootless window\n");
-+ ErrorF(" (ugly workaround for Unity8 bug LP: #1501346)\n");
+ ErrorF("-title <name> Set window title (@ = automatic)\n");
+ ErrorF("-sw disable glamor rendering\n");
+ ErrorF("-egl force use of EGL calls, disables DRI2 pass-through\n");
@@ -6444,6 +6461,38 @@ index 0000000..34f78c9
+ return 0;
+}
+
++enum XWMHints_flag {
++ InputHint = 1
++ /* There are more but not yet required */
++};
++
++typedef struct {
++ long flags; /* marks which fields in this structure are defined */
++ Bool input; /* does this application rely on the window manager to
++ get keyboard input? */
++ int initial_state; /* see below */
++ Pixmap icon_pixmap; /* pixmap to be used as icon */
++ Window icon_window; /* window to be used as icon */
++ int icon_x, icon_y; /* initial position of icon */
++ Pixmap icon_mask; /* icon mask bitmap */
++ XID window_group; /* id of related window group */
++ /* this structure may be extended in the future */
++} XWMHints;
++
++static XWMHints*
++xmir_get_window_prop_hints(WindowPtr window)
++{
++ if (window->optional) {
++ PropertyPtr p = window->optional->userProps;
++ while (p) {
++ if (p->propertyName == XA_WM_HINTS)
++ return (XWMHints*)p->data;
++ p = p->next;
++ }
++ }
++ return NULL;
++}
++
+static void
+damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
+{
@@ -6516,9 +6565,14 @@ index 0000000..34f78c9
+ line_len = (x2 - x1) * bpp;
+ for (y = y1; y < y2; ++y) {
+ memcpy(dst, src, line_len);
++ if (x2 < region.width)
++ memset(dst+x2*bpp, 0, (region.width - x2)*bpp);
+ src += src_stride;
+ dst += region.stride;
+ }
++
++ if (y2 < region.height)
++ memset(dst, 0, (region.height - y2)*region.stride);
+}
+
+static void
@@ -6553,11 +6607,21 @@ index 0000000..34f78c9
+ }
+}
+
++static void
++xmir_swap(struct xmir_screen *xmir_screen, struct xmir_window *xmir_win)
++{
++ MirBufferStream *stream = mir_surface_get_buffer_stream(xmir_win->surface);
++ struct xmir_swap *swap = calloc(sizeof(struct xmir_swap), 1);
++ swap->server_generation = serverGeneration;
++ swap->xmir_screen = xmir_screen;
++ swap->xmir_window = xmir_win;
++ mir_buffer_stream_swap_buffers(stream, xmir_handle_buffer_received, swap);
++}
++
+void xmir_repaint(struct xmir_window *xmir_win)
+{
+ struct xmir_screen *xmir_screen = xmir_screen_get(xmir_win->window->drawable.pScreen);
+ RegionPtr dirty = &xmir_win->region;
-+ MirBufferStream *stream = mir_surface_get_buffer_stream(xmir_win->surface);
+ char wm_name[256];
+ WindowPtr named = NULL;
+
@@ -6614,14 +6678,12 @@ index 0000000..34f78c9
+ case glamor_off:
+ xmir_sw_copy(xmir_screen, xmir_win, dirty);
+ xmir_win->has_free_buffer = FALSE;
-+ mir_buffer_stream_swap_buffers(stream, xmir_handle_buffer_received,
-+ xmir_win);
++ xmir_swap(xmir_screen, xmir_win);
+ break;
+ case glamor_dri:
+ xmir_glamor_copy(xmir_screen, xmir_win, dirty);
+ xmir_win->has_free_buffer = FALSE;
-+ mir_buffer_stream_swap_buffers(stream, xmir_handle_buffer_received,
-+ xmir_win);
++ xmir_swap(xmir_screen, xmir_win);
+ break;
+ case glamor_egl:
+ case glamor_egl_sync:
@@ -6665,6 +6727,9 @@ index 0000000..34f78c9
+ xclient_lagging = buf_width != xmir_win->window->drawable.width ||
+ buf_height != xmir_win->window->drawable.height;
+
++ if (xserver_lagging || !xorg_list_is_empty(&xmir_win->link_damage))
++ xmir_repaint(xmir_win);
++
+ if (xclient_lagging) {
+ if (xmir_screen->rootless) {
+ XID vlist[2] = {buf_width, buf_height};
@@ -6682,9 +6747,6 @@ index 0000000..34f78c9
+ */
+ }
+
-+ if (xserver_lagging || !xorg_list_is_empty(&xmir_win->link_damage))
-+ xmir_repaint(xmir_win);
-+
+ if (xserver_lagging)
+ DamageDamageRegion(&xmir_win->window->drawable, &xmir_win->region);
+}
@@ -6692,11 +6754,15 @@ index 0000000..34f78c9
+static void
+xmir_handle_buffer_received(MirBufferStream *stream, void *ctx)
+{
-+ struct xmir_window *xmir_win = ctx;
-+ struct xmir_screen *xmir_screen = xmir_screen_get(xmir_win->window->drawable.pScreen);
++ struct xmir_swap *swap = ctx;
++ struct xmir_screen *xmir_screen = swap->xmir_screen;
+
-+ xmir_post_to_eventloop(xmir_handle_buffer_available, xmir_screen,
-+ xmir_win, 0);
++ if (swap->server_generation == serverGeneration && !xmir_screen->closing) {
++ xmir_post_to_eventloop(xmir_handle_buffer_available, xmir_screen,
++ swap->xmir_window, 0);
++ }
++
++ free(swap);
+}
+
+static Bool
@@ -6750,6 +6816,8 @@ index 0000000..34f78c9
+ int mir_height = window->drawable.height / (1 + xmir_screen->doubled);
+ MirSurfaceSpec* spec = NULL;
+ WindowPtr wm_transient_for = NULL, positioning_parent = NULL;
++ MirPersistentId *persistent_id = NULL;
++ XWMHints *wm_hints = NULL;
+ char wm_name[1024];
+
+ screen->RealizeWindow = xmir_screen->RealizeWindow;
@@ -6768,17 +6836,28 @@ index 0000000..34f78c9
+ wm_type = xmir_get_window_prop_atom(window, GET_ATOM(_NET_WM_WINDOW_TYPE));
+ wm_transient_for = xmir_get_window_prop_window(window, XA_WM_TRANSIENT_FOR);
+
-+ XMIR_DEBUG(("Realize %swindow %p \"%s\": %dx%d %+d%+d parent=%p\n"
++ XMIR_DEBUG(("Realize %swindow %p id=0x%x \"%s\": %dx%d %+d%+d parent=%p\n"
+ "\tdepth=%d redir=%u type=%hu class=%u visibility=%u viewable=%u\n"
-+ "\toverride=%d _NET_WM_WINDOW_TYPE=%lu WM_TRANSIENT_FOR=%p\n",
++ "\toverride=%d _NET_WM_WINDOW_TYPE=%lu(%s)\n"
++ "\tWM_TRANSIENT_FOR=%p\n",
+ window == screen->root ? "ROOT " : "",
-+ window, wm_name, mir_width, mir_height,
++ window, (int)window->drawable.id, wm_name, mir_width, mir_height,
+ window->drawable.x, window->drawable.y,
+ window->parent,
+ window->drawable.depth,
+ window->redirectDraw, window->drawable.type,
+ window->drawable.class, window->visibility, window->viewable,
-+ window->overrideRedirect, (unsigned long)wm_type, wm_transient_for));
++ window->overrideRedirect,
++ (unsigned long)wm_type, NameForAtom(wm_type)?:"",
++ wm_transient_for));
++
++ wm_hints = xmir_get_window_prop_hints(window);
++ if (wm_hints) {
++ XMIR_DEBUG(("\tWM_HINTS={flags=0x%lx,input=%s}\n",
++ wm_hints->flags, wm_hints->input?"True":"False"));
++ } else {
++ XMIR_DEBUG(("\tWM_HINTS=<none>\n"));
++ }
+
+ if (!window->viewable) {
+ return ret;
@@ -6913,6 +6992,17 @@ index 0000000..34f78c9
+ }
+ mir_surface_spec_release(spec);
+
++ persistent_id =
++ mir_surface_request_persistent_id_sync(xmir_window->surface);
++ if (mir_persistent_id_is_valid(persistent_id)) {
++ const char *str = mir_persistent_id_as_string(persistent_id);
++ dixChangeWindowProperty(serverClient, window,
++ MAKE_ATOM(_MIR_WM_PERSISTENT_ID),
++ XA_STRING, 8, PropModeReplace,
++ strlen(str), (void*)str, FALSE);
++ }
++ mir_persistent_id_release(persistent_id);
++
+ xmir_window->has_free_buffer = TRUE;
+ if (!mir_surface_is_valid(xmir_window->surface)) {
+ ErrorF("failed to create a surface: %s\n", mir_surface_get_error_message(xmir_window->surface));
@@ -6970,6 +7060,66 @@ index 0000000..34f78c9
+ }
+}
+
++static Window
++xmir_get_current_input_focus(DeviceIntPtr kbd)
++{
++ Window id = None;
++ FocusClassPtr focus = kbd->focus;
++ if (focus->win == NoneWin)
++ id = None;
++ else if (focus->win == PointerRootWin)
++ id = PointerRoot;
++ else
++ id = focus->win->drawable.id;
++ return id;
++}
++
++static void
++xmir_handle_focus_event(struct xmir_window *xmir_window,
++ MirSurfaceFocusState state)
++{
++ struct xmir_screen *xmir_screen = xmir_window->xmir_screen;
++ DeviceIntPtr keyboard = inputInfo.keyboard; /*PickKeyboard(serverClient);*/
++
++ if (xmir_screen->destroying_root)
++ return;
++
++ if (xmir_window->surface) { /* It's a real Mir window */
++ xmir_screen->last_focus = (state == mir_surface_focused) ?
++ xmir_window->window : NULL;
++ }
++
++ if (xmir_screen->rootless) {
++ WindowPtr window = xmir_window->window;
++ const XWMHints *hints = xmir_get_window_prop_hints(window);
++ Bool refuse_focus = window->overrideRedirect ||
++ (hints && (hints->flags & InputHint) && !hints->input);
++ if (!refuse_focus) {
++ Window id = (state == mir_surface_focused) ?
++ window->drawable.id : None;
++ SetInputFocus(serverClient, keyboard, id, RevertToParent,
++ CurrentTime, False);
++ }
++ } else if (!strcmp(xmir_screen->title, get_title_from_top_window)) {
++ /*
++ * So as to not break default behaviour, we only hack focus within
++ * the root window when in Unity8 invasive mode (-title @).
++ */
++ Window id = None;
++ if (state == mir_surface_focused) {
++ id = xmir_screen->saved_focus;
++ if (id == None)
++ id = PointerRoot;
++ } else {
++ xmir_screen->saved_focus = xmir_get_current_input_focus(keyboard);
++ id = None;
++ }
++ SetInputFocus(serverClient, keyboard, id, RevertToNone, CurrentTime,
++ False);
++ }
++ /* else normal root window mode -- Xmir does not interfere in focus */
++}
++
+void
+xmir_handle_surface_event(struct xmir_window *xmir_window, MirSurfaceAttrib attr, int val)
+{
@@ -6985,10 +7135,7 @@ index 0000000..34f78c9
+ break;
+ case mir_surface_attrib_focus:
+ XMIR_DEBUG(("Focus: %s\n", xmir_surface_focus_str(val)));
-+ if (xmir_window->surface) { /* It's a real Mir window */
-+ xmir_window->xmir_screen->last_focus =
-+ (val == mir_surface_focused) ? xmir_window->window : NULL;
-+ }
++ xmir_handle_focus_event(xmir_window, (MirSurfaceFocusState)val);
+ break;
+ case mir_surface_attrib_dpi:
+ XMIR_DEBUG(("DPI: %i\n", val));
@@ -7180,8 +7327,7 @@ index 0000000..34f78c9
+ xmir_window->surface = NULL;
+ }
+
-+ /* drain all events from input and damage to prevent a race condition after mir_surface_release_sync */
-+ xmir_process_from_eventloop();
++ xmir_process_from_eventloop_except(xmir_window);
+
+ RegionUninit(&xmir_window->region);
+}
@@ -7215,6 +7361,9 @@ index 0000000..34f78c9
+ struct xmir_screen *xmir_screen = xmir_screen_get(screen);
+ Bool ret;
+
++ if (!window->parent)
++ xmir_screen->destroying_root = TRUE;
++
+ xmir_unmap_input(xmir_screen, window);
+ xmir_unmap_surface(xmir_screen, window, TRUE);
+
@@ -7262,6 +7411,8 @@ index 0000000..34f78c9
+ struct xmir_output *xmir_output, *next_xmir_output;
+ Bool ret;
+
++ xmir_screen->closing = TRUE;
++
+ if (xmir_screen->glamor && xmir_screen->gbm)
+ DRI2CloseScreen(screen);
+
@@ -7571,11 +7722,14 @@ index 0000000..34f78c9
+ return FALSE;
+ }
+
-+ /* Core DPI cannot report correct values (it's one value, we have multiple displays)
-+ * Use the value from the -dpi commandline if set, or 96 otherwise.
++ /*
++ * Core DPI cannot report correct values (it's one value and we might have
++ * multiple displays). Use the value from the -dpi command line if set, or
++ * 96 otherwise.
+ *
-+ * This matches the behaviour of all the desktop Xorg drivers. Clients which
-+ * care can use the XRANDR extension to get correct per-output DPI information.
++ * This matches the behaviour of all the desktop Xorg drivers. Clients
++ * which care can use the XRandR extension to get correct per-output DPI
++ * information.
+ */
+ xmir_screen->dpi = monitorResolution > 0 ? monitorResolution : 96;
+
@@ -7666,6 +7820,21 @@ index 0000000..34f78c9
+ xmir_screen->CloseScreen = pScreen->CloseScreen;
Reply to: