Merge tag jb8u152-b1343.16

Change-Id: Ib5e79ec062198e4a8e16283f7b4abed6157c3dd2
diff --git a/make/lib/Awt2dLibraries.gmk b/make/lib/Awt2dLibraries.gmk
index 70732ce..405415d 100644
--- a/make/lib/Awt2dLibraries.gmk
+++ b/make/lib/Awt2dLibraries.gmk
@@ -626,6 +626,12 @@
       LIBAWT_XAWT_LDFLAGS += -lpthread
     endif
 
+    ifeq ($(BUILD_XAWT_XWAYLAND), true)
+      LIBAWT_XAWT_FILES += xwayland.c
+      LIBAWT_XAWT_CFLAGS += -DBUILD_XAWT_XWAYLAND=true
+      LIBAWT_XAWT_LDFLAGS_SUFFIX += -lpthread -lxcb -lxcb-composite -lwayland-server -lwayland-client
+    endif
+
     $(eval $(call SetupNativeCompilation,BUILD_LIBAWT_XAWT, \
         LIBRARY := awt_xawt, \
         OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
diff --git a/make/src/classes/build/tools/generatecharacter/GenerateCharacter.java b/make/src/classes/build/tools/generatecharacter/GenerateCharacter.java
index 83973ef..6235e4e 100644
--- a/make/src/classes/build/tools/generatecharacter/GenerateCharacter.java
+++ b/make/src/classes/build/tools/generatecharacter/GenerateCharacter.java
@@ -693,7 +693,7 @@
         PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(theOutputFileName)));
         out.println(commentStart +
             " This file was generated AUTOMATICALLY from a template file " +
-            new java.util.Date() + commentEnd);
+            commentEnd);
         int marklen = commandMarker.length();
         LOOP: while(true) {
             try {
@@ -1808,6 +1808,7 @@
         commentStart = (Csyntax ? "/*" : "//");
         commentEnd = (Csyntax ? " */" : "");
         commandLineDescription = desc.toString();
+        commandLineDescription = "java GenerateCharacter"; // Android Studio: make build deterministic.
     }
 
     private static void searchBins(long[] map, int binsOccupied) throws Exception {
diff --git a/src/lang/annotation/TestConstructorParameterAnnotations.java b/src/lang/annotation/TestConstructorParameterAnnotations.java
new file mode 100644
index 0000000..66c270f
--- /dev/null
+++ b/src/lang/annotation/TestConstructorParameterAnnotations.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug     8074977
+ * @summary Test consistency of annotations on constructor parameters
+ * @compile             TestConstructorParameterAnnotations.java
+ * @run main            TestConstructorParameterAnnotations
+ * @compile -parameters TestConstructorParameterAnnotations.java
+ * @run main            TestConstructorParameterAnnotations
+ */
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+/*
+ * Some constructor parameters are <em>mandated</em>; that is, they
+ * are not explicitly present in the source code, but required to be
+ * present by the Java Language Specification. In other cases, some
+ * constructor parameters are not present in the source, but are
+ * synthesized by the compiler as an implementation artifact. There is
+ * not a reliable mechanism to consistently determine whether or not
+ * a parameter is implicit or not.
+ *
+ * (Using the "-parameters" option to javac does emit the information
+ * needed to make a reliably determination, but the information is not
+ * present by default.)
+ *
+ * The lack of such a mechanism causes complications reading parameter
+ * annotations in some cases since annotations for parameters are
+ * written out for the parameters in the source code, but when reading
+ * annotations at runtime all the parameters, including implicit ones,
+ * are present.
+ */
+public class TestConstructorParameterAnnotations {
+    public static void main(String... args) {
+        int errors = 0;
+        Class<?>[] classes = {NestedClass0.class,
+                              NestedClass1.class,
+                              NestedClass2.class,
+                              NestedClass3.class,
+                              NestedClass4.class,
+                              StaticNestedClass0.class,
+                              StaticNestedClass1.class,
+                              StaticNestedClass2.class,
+                              StaticNestedClass3.class,
+                              StaticNestedClass4.class};
+
+        for (Class<?> clazz : classes) {
+            for (Constructor<?> ctor : clazz.getConstructors()) {
+                System.out.println(ctor);
+                errors += checkGetParameterAnnotations(clazz, ctor);
+                errors += checkGetParametersGetAnnotation(clazz, ctor);
+            }
+        }
+
+        if (errors > 0)
+            throw new RuntimeException(errors + " errors.");
+        return;
+    }
+
+    private static int checkGetParameterAnnotations(Class<?> clazz,
+                                                    Constructor<?> ctor) {
+        String annotationString =
+            Arrays.deepToString(ctor.getParameterAnnotations());
+        String expectedString =
+            clazz.getAnnotation(ExpectedGetParameterAnnotations.class).value();
+
+        if (!Objects.equals(annotationString, expectedString)) {
+            System.err.println("Annotation mismatch on " + ctor +
+                               "\n\tExpected:" + expectedString +
+                               "\n\tActual:  " + annotationString);
+            return 1;
+        }
+        return 0;
+    }
+
+    private static int checkGetParametersGetAnnotation(Class<?> clazz,
+                                                       Constructor<?> ctor) {
+        int errors = 0;
+        int i = 0;
+        ExpectedParameterAnnotations epa =
+            clazz.getAnnotation(ExpectedParameterAnnotations.class);
+
+        for (Parameter param : ctor.getParameters() ) {
+            String annotationString =
+                Objects.toString(param.getAnnotation(MarkerAnnotation.class));
+            String expectedString = epa.value()[i];
+
+            if (!Objects.equals(annotationString, expectedString)) {
+                System.err.println("Annotation mismatch on " + ctor +
+                                   " on param " + param +
+                                   "\n\tExpected:" + expectedString +
+                                   "\n\tActual:  " + annotationString);
+                errors++;
+            }
+            i++;
+        }
+        return errors;
+    }
+
+    @ExpectedGetParameterAnnotations("[[]]")
+    @ExpectedParameterAnnotations({"null"})
+    public class NestedClass0 {
+        public NestedClass0() {}
+    }
+
+    @ExpectedGetParameterAnnotations(
+        "[[], " +
+        "[@TestConstructorParameterAnnotations$MarkerAnnotation(value=1)]]")
+    @ExpectedParameterAnnotations({
+        "null",
+        "@TestConstructorParameterAnnotations$MarkerAnnotation(value=1)"})
+    public class NestedClass1 {
+        public NestedClass1(@MarkerAnnotation(1) int parameter) {}
+    }
+
+    @ExpectedGetParameterAnnotations(
+        "[[], " +
+        "[@TestConstructorParameterAnnotations$MarkerAnnotation(value=2)], " +
+        "[]]")
+    @ExpectedParameterAnnotations({
+        "null",
+        "@TestConstructorParameterAnnotations$MarkerAnnotation(value=2)",
+        "null"})
+    public class NestedClass2 {
+        public NestedClass2(@MarkerAnnotation(2) int parameter1,
+                            int parameter2) {}
+    }
+
+    @ExpectedGetParameterAnnotations(
+        "[[], " +
+        "[@TestConstructorParameterAnnotations$MarkerAnnotation(value=3)], " +
+        "[]]")
+    @ExpectedParameterAnnotations({
+        "null",
+        "@TestConstructorParameterAnnotations$MarkerAnnotation(value=3)",
+            "null"})
+    public class NestedClass3 {
+        public <P> NestedClass3(@MarkerAnnotation(3) P parameter1,
+                                int parameter2) {}
+    }
+
+    @ExpectedGetParameterAnnotations(
+        "[[], " +
+        "[@TestConstructorParameterAnnotations$MarkerAnnotation(value=4)], " +
+        "[]]")
+    @ExpectedParameterAnnotations({
+        "null",
+        "@TestConstructorParameterAnnotations$MarkerAnnotation(value=4)",
+        "null"})
+    public class NestedClass4 {
+        public <P, Q> NestedClass4(@MarkerAnnotation(4) P parameter1,
+                                   Q parameter2) {}
+    }
+
+    @ExpectedGetParameterAnnotations("[]")
+    @ExpectedParameterAnnotations({"null"})
+    public static class StaticNestedClass0 {
+        public StaticNestedClass0() {}
+    }
+
+    @ExpectedGetParameterAnnotations(
+        "[[@TestConstructorParameterAnnotations$MarkerAnnotation(value=1)]]")
+    @ExpectedParameterAnnotations({
+        "@TestConstructorParameterAnnotations$MarkerAnnotation(value=1)"})
+    public static class StaticNestedClass1 {
+        public StaticNestedClass1(@MarkerAnnotation(1) int parameter) {}
+    }
+
+    @ExpectedGetParameterAnnotations(
+        "[[@TestConstructorParameterAnnotations$MarkerAnnotation(value=2)], " +
+        "[]]")
+    @ExpectedParameterAnnotations({
+        "@TestConstructorParameterAnnotations$MarkerAnnotation(value=2)",
+        "null"})
+    public static class StaticNestedClass2 {
+        public StaticNestedClass2(@MarkerAnnotation(2) int parameter1,
+                            int parameter2) {}
+    }
+
+    @ExpectedGetParameterAnnotations(
+        "[[@TestConstructorParameterAnnotations$MarkerAnnotation(value=3)], " +
+        "[]]")
+    @ExpectedParameterAnnotations({
+        "@TestConstructorParameterAnnotations$MarkerAnnotation(value=3)",
+        "null"})
+    public static class StaticNestedClass3 {
+        public <P> StaticNestedClass3(@MarkerAnnotation(3) P parameter1,
+                                      int parameter2) {}
+    }
+
+    @ExpectedGetParameterAnnotations(
+        "[[@TestConstructorParameterAnnotations$MarkerAnnotation(value=4)], " +
+        "[]]")
+    @ExpectedParameterAnnotations({
+        "@TestConstructorParameterAnnotations$MarkerAnnotation(value=4)",
+        "null"})
+    public static class StaticNestedClass4 {
+        public <P, Q> StaticNestedClass4(@MarkerAnnotation(4) P parameter1,
+                                         Q parameter2) {}
+    }
+
+    @Target(ElementType.PARAMETER)
+    @Retention(RetentionPolicy.RUNTIME)
+    @interface MarkerAnnotation {
+        int value();
+    }
+
+    /**
+     * String form of expected value of calling
+     * getParameterAnnotations on a constructor.
+     */
+    @Target(ElementType.TYPE)
+    @Retention(RetentionPolicy.RUNTIME)
+    @interface ExpectedGetParameterAnnotations {
+        String value();
+    }
+
+    /**
+     * String form of expected value of calling
+     * getAnnotation(MarkerAnnotation.class) on each element of the
+     * result of getParameters() on a constructor.
+     */
+    @Target(ElementType.TYPE)
+    @Retention(RetentionPolicy.RUNTIME)
+    @interface ExpectedParameterAnnotations {
+        String[] value();
+    }
+}
diff --git a/src/lang/annotation/typeAnnotations/TestConstructorParameterTypeAnnotations.java b/src/lang/annotation/typeAnnotations/TestConstructorParameterTypeAnnotations.java
new file mode 100644
index 0000000..ee36976
--- /dev/null
+++ b/src/lang/annotation/typeAnnotations/TestConstructorParameterTypeAnnotations.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug     8074977
+ * @summary Test consistency of annotations on constructor parameters
+ * @compile             TestConstructorParameterTypeAnnotations.java
+ * @run main            TestConstructorParameterTypeAnnotations
+ * @compile -parameters TestConstructorParameterTypeAnnotations.java
+ * @run main            TestConstructorParameterTypeAnnotations
+ */
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+/*
+ * Some constructor parameters are <em>mandated</em>; that is, they
+ * are not explicitly present in the source code, but required to be
+ * present by the Java Language Specification. In other cases, some
+ * constructor parameters are not present in the source, but are
+ * synthesized by the compiler as an implementation artifact. There is
+ * not a reliable mechanism to consistently determine whether or not
+ * a parameter is implicit or not.
+ *
+ * (Using the "-parameters" option to javac does emit the information
+ * needed to make a reliably determination, but the information is not
+ * present by default.)
+ *
+ * The lack of such a mechanism causes complications reading parameter
+ * annotations in some cases since annotations for parameters are
+ * written out for the parameters in the source code, but when reading
+ * annotations at runtime all the parameters, including implicit ones,
+ * are present.
+ */
+public class TestConstructorParameterTypeAnnotations {
+    public static void main(String... args) {
+        int errors = 0;
+        Class<?>[] classes = {NestedClass0.class,
+                              NestedClass1.class,
+                              NestedClass2.class,
+                              NestedClass3.class,
+                              NestedClass4.class,
+                              StaticNestedClass0.class,
+                              StaticNestedClass1.class,
+                              StaticNestedClass2.class };
+
+        for (Class<?> clazz : classes) {
+            for (Constructor<?> ctor : clazz.getConstructors()) {
+                System.out.println(ctor);
+                errors += checkGetParameterAnnotations(clazz, ctor);
+                errors += checkGetAnnotatedParametersGetAnnotation(clazz, ctor);
+            }
+        }
+
+        if (errors > 0)
+            throw new RuntimeException(errors + " errors.");
+        return;
+    }
+
+    private static int checkGetParameterAnnotations(Class<?> clazz,
+                                                    Constructor<?> ctor) {
+        String annotationString =
+            Arrays.deepToString(ctor.getParameterAnnotations());
+        String expectedString =
+            clazz.getAnnotation(ExpectedGetParameterAnnotations.class).value();
+
+        if (!Objects.equals(annotationString, expectedString)) {
+            System.err.println("Annotation mismatch on " + ctor +
+                               "\n\tExpected:" + expectedString +
+                               "\n\tActual:  " + annotationString);
+            return 1;
+        }
+        return 0;
+    }
+
+    private static int checkGetAnnotatedParametersGetAnnotation(Class<?> clazz,
+                                                       Constructor<?> ctor) {
+        int errors = 0;
+        int i = 0;
+        ExpectedParameterTypeAnnotations epa =
+            clazz.getAnnotation(ExpectedParameterTypeAnnotations.class);
+
+        for (AnnotatedType param : ctor.getAnnotatedParameterTypes() ) {
+            String annotationString =
+                Objects.toString(param.getAnnotation(MarkerTypeAnnotation.class));
+            String expectedString = epa.value()[i];
+
+            if (!Objects.equals(annotationString, expectedString)) {
+                System.err.println("Annotation mismatch on " + ctor +
+                                   " on param " + param +
+                                   "\n\tExpected:" + expectedString +
+                                   "\n\tActual:  " + annotationString);
+                errors++;
+            }
+            i++;
+        }
+        return errors;
+    }
+
+    @ExpectedGetParameterAnnotations("[[]]")
+    @ExpectedParameterTypeAnnotations({"null"})
+    public class NestedClass0 {
+        public NestedClass0() {}
+    }
+
+    @ExpectedGetParameterAnnotations("[[], []]")
+    @ExpectedParameterTypeAnnotations({
+        "null",
+        "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(value=1)"})
+    public class NestedClass1 {
+        public NestedClass1(@MarkerTypeAnnotation(1) int parameter) {}
+    }
+
+    @ExpectedGetParameterAnnotations("[[], [], []]")
+    @ExpectedParameterTypeAnnotations({
+        "null",
+        "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(value=2)",
+        "null"})
+    public class NestedClass2 {
+        public NestedClass2(@MarkerTypeAnnotation(2) int parameter1,
+                            int parameter2) {}
+    }
+
+    @ExpectedGetParameterAnnotations("[[], [], []]")
+    @ExpectedParameterTypeAnnotations({
+        "null",
+        "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(value=3)",
+        "null"})
+    public class NestedClass3 {
+        public <P> NestedClass3(@MarkerTypeAnnotation(3) P parameter1,
+                                int parameter2) {}
+    }
+
+    @ExpectedGetParameterAnnotations("[[], [], []]")
+    @ExpectedParameterTypeAnnotations({
+        "null",
+        "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(value=4)",
+        "null"})
+    public class NestedClass4 {
+        public <P, Q> NestedClass4(@MarkerTypeAnnotation(4) P parameter1,
+                                   Q parameter2) {}
+    }
+
+    @ExpectedGetParameterAnnotations("[]")
+    @ExpectedParameterTypeAnnotations({"null"})
+    public static class StaticNestedClass0 {
+        public StaticNestedClass0() {}
+    }
+
+    @ExpectedGetParameterAnnotations("[[]]")
+    @ExpectedParameterTypeAnnotations({
+        "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(value=1)"})
+    public static class StaticNestedClass1 {
+        public StaticNestedClass1(@MarkerTypeAnnotation(1) int parameter) {}
+    }
+
+    @ExpectedGetParameterAnnotations("[[], []]")
+    @ExpectedParameterTypeAnnotations({
+        "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(value=2)",
+        "null"})
+    public static class StaticNestedClass2 {
+        public StaticNestedClass2(@MarkerTypeAnnotation(2) int parameter1,
+                                  int parameter2) {}
+    }
+
+    @ExpectedGetParameterAnnotations("[[], []]")
+    @ExpectedParameterTypeAnnotations({
+        "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(value=3)",
+        "null"})
+    public static class StaticNestedClass3 {
+         public <P> StaticNestedClass3(@MarkerTypeAnnotation(3) P parameter1,
+                                      int parameter2) {}
+    }
+
+    @ExpectedGetParameterAnnotations("[[], []]")
+    @ExpectedParameterTypeAnnotations({
+        "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(value=4)",
+        "null"})
+    public static class StaticNestedClass4 {
+        public <P, Q> StaticNestedClass4(@MarkerTypeAnnotation(4) P parameter1,
+                                         Q parameter2) {}
+    }
+
+    @Target(ElementType.TYPE_USE)
+    @Retention(RetentionPolicy.RUNTIME)
+    @interface MarkerTypeAnnotation {
+        int value();
+    }
+
+    /**
+     * String form of expected value of calling
+     * getParameterAnnotations on a constructor.
+     */
+    @Target(ElementType.TYPE)
+    @Retention(RetentionPolicy.RUNTIME)
+    @interface ExpectedGetParameterAnnotations {
+        String value();
+    }
+
+    /**
+     * String form of expected value of calling
+     * getAnnotation(MarkerTypeAnnotation.class) on each element of the
+     * result of getParameters() on a constructor.
+     */
+    @Target(ElementType.TYPE)
+    @Retention(RetentionPolicy.RUNTIME)
+    @interface ExpectedParameterTypeAnnotations {
+        String[] value();
+    }
+}
diff --git a/src/macosx/native/sun/awt/AWTWindow.m b/src/macosx/native/sun/awt/AWTWindow.m
index 238b37b..c88bdc5 100644
--- a/src/macosx/native/sun/awt/AWTWindow.m
+++ b/src/macosx/native/sun/awt/AWTWindow.m
@@ -319,6 +319,9 @@
     if (self.nsWindow == nil) return nil; // no hope either
     [self.nsWindow release]; // the property retains the object already
 
+    // Tell the system we have an sRGB backing store
+    [self.nsWindow setColorSpace: [NSColorSpace sRGBColorSpace]];
+
     self.isEnabled = YES;
     self.isMinimizing = NO;
     self.javaPlatformWindow = platformWindow;
diff --git a/src/share/classes/java/lang/reflect/Constructor.java b/src/share/classes/java/lang/reflect/Constructor.java
index bf17091..e5b9436 100644
--- a/src/share/classes/java/lang/reflect/Constructor.java
+++ b/src/share/classes/java/lang/reflect/Constructor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -524,19 +524,18 @@
     }
 
     @Override
-    void handleParameterNumberMismatch(int resultLength, int numParameters) {
+    boolean handleParameterNumberMismatch(int resultLength, int numParameters) {
         Class<?> declaringClass = getDeclaringClass();
         if (declaringClass.isEnum() ||
             declaringClass.isAnonymousClass() ||
             declaringClass.isLocalClass() )
-            return ; // Can't do reliable parameter counting
+            return false; // Can't do reliable parameter counting
         else {
-            if (!declaringClass.isMemberClass() || // top-level
-                // Check for the enclosing instance parameter for
-                // non-static member classes
-                (declaringClass.isMemberClass() &&
-                 ((declaringClass.getModifiers() & Modifier.STATIC) == 0)  &&
-                 resultLength + 1 != numParameters) ) {
+            if (declaringClass.isMemberClass() &&
+                ((declaringClass.getModifiers() & Modifier.STATIC) == 0)  &&
+                resultLength + 1 == numParameters) {
+                return true;
+            } else {
                 throw new AnnotationFormatError(
                           "Parameter annotations don't match number of parameters");
             }
diff --git a/src/share/classes/java/lang/reflect/Executable.java b/src/share/classes/java/lang/reflect/Executable.java
index 3e82d99..832b5cd 100644
--- a/src/share/classes/java/lang/reflect/Executable.java
+++ b/src/share/classes/java/lang/reflect/Executable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -554,12 +554,18 @@
 
         Annotation[][] result = parseParameterAnnotations(parameterAnnotations);
 
-        if (result.length != numParameters)
-            handleParameterNumberMismatch(result.length, numParameters);
+        if (result.length != numParameters &&
+            handleParameterNumberMismatch(result.length, numParameters)) {
+            Annotation[][] tmp = new Annotation[result.length+1][];
+            // Shift annotations down one to account for an implicit leading parameter
+            System.arraycopy(result, 0, tmp, 1, result.length);
+            tmp[0] = new Annotation[0];
+            result = tmp;
+        }
         return result;
     }
 
-    abstract void handleParameterNumberMismatch(int resultLength, int numParameters);
+    abstract boolean handleParameterNumberMismatch(int resultLength, int numParameters);
 
     /**
      * {@inheritDoc}
diff --git a/src/share/classes/java/lang/reflect/Method.java b/src/share/classes/java/lang/reflect/Method.java
index ddf0f38..02efc80 100644
--- a/src/share/classes/java/lang/reflect/Method.java
+++ b/src/share/classes/java/lang/reflect/Method.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -649,7 +649,7 @@
     }
 
     @Override
-    void handleParameterNumberMismatch(int resultLength, int numParameters) {
+    boolean handleParameterNumberMismatch(int resultLength, int numParameters) {
         throw new AnnotationFormatError("Parameter annotations don't match number of parameters");
     }
 }
diff --git a/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java b/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java
index 8eab556..4c94ddf 100644
--- a/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java
+++ b/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -125,9 +125,30 @@
                 tmp.add(t);
             }
         }
+        // If a constructor has a mandated outer this, that parameter
+        // has no annotations and the annotations to parameter mapping
+        // should be offset by 1.
+        boolean offset = false;
+        if (decl instanceof Constructor) {
+            Constructor<?> ctor = (Constructor<?>) decl;
+            Class<?> declaringClass = ctor.getDeclaringClass();
+            if (!declaringClass.isEnum() &&
+                (declaringClass.isMemberClass() &&
+                 (declaringClass.getModifiers() & Modifier.STATIC) == 0) ) {
+                offset = true;
+            }
+        }
         for (int i = 0; i < size; i++) {
-            @SuppressWarnings("unchecked")
-            ArrayList<TypeAnnotation> list = l[i];
+            ArrayList<TypeAnnotation> list;
+            if (offset) {
+                @SuppressWarnings("unchecked")
+                ArrayList<TypeAnnotation> tmp = (i == 0) ? null : l[i - 1];
+                list = tmp;
+            } else {
+                @SuppressWarnings("unchecked")
+                ArrayList<TypeAnnotation> tmp = l[i];
+                list = tmp;
+            }
             TypeAnnotation[] typeAnnotations;
             if (list != null) {
                 typeAnnotations = list.toArray(new TypeAnnotation[list.size()]);
diff --git a/src/share/native/sun/font/layout/LEInsertionList.h b/src/share/native/sun/font/layout/LEInsertionList.h
index 231b5f6..56f9688 100644
--- a/src/share/native/sun/font/layout/LEInsertionList.h
+++ b/src/share/native/sun/font/layout/LEInsertionList.h
@@ -101,7 +101,7 @@
     /**
      * The destructor.
      */
-    ~LEInsertionList();
+    virtual ~LEInsertionList();
 
     /**
      * Add an entry to the insertion list.
diff --git a/src/solaris/classes/sun/awt/X11/XBaseWindow.java b/src/solaris/classes/sun/awt/X11/XBaseWindow.java
index 052af80..1cea1ee 100644
--- a/src/solaris/classes/sun/awt/X11/XBaseWindow.java
+++ b/src/solaris/classes/sun/awt/X11/XBaseWindow.java
@@ -1,3 +1,27 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
 package sun.awt.X11;
 
 import java.awt.*;
diff --git a/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java b/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java
index 959f241..7fd1ca7 100644
--- a/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java
+++ b/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java
@@ -605,8 +605,7 @@
             // its location changes.
             Point oldLocation = getLocation();
 
-            Point newLocation = new Point(AWTAccessor.getComponentAccessor().getX(target),
-                                          AWTAccessor.getComponentAccessor().getY(target));
+            Point newLocation = newDimensions.getLocation();
 
             if (!newLocation.equals(oldLocation)) {
                 handleMoved(newDimensions);
diff --git a/src/solaris/native/sun/awt/awt_GraphicsEnv.c b/src/solaris/native/sun/awt/awt_GraphicsEnv.c
index 1a20b40..d2f989d 100644
--- a/src/solaris/native/sun/awt/awt_GraphicsEnv.c
+++ b/src/solaris/native/sun/awt/awt_GraphicsEnv.c
@@ -32,6 +32,10 @@
 #include <sun_awt_X11GraphicsDevice.h>
 #include <sun_awt_X11GraphicsConfig.h>
 #ifndef HEADLESS
+#ifdef BUILD_XAWT_XWAYLAND
+#include "xwayland.h"
+#include <pthread.h>
+#endif /* BUILD_XAWT_XWAYLAND */
 #include <X11/extensions/Xdbe.h>
 #include <X11/XKBlib.h>
 #include "Xrandr.h"
@@ -178,6 +182,17 @@
 
 #ifndef HEADLESS
 
+#ifdef BUILD_XAWT_XWAYLAND
+/*
+ * XWayland thread function
+ */
+static void *xwayland_start(void *data)
+{
+    xwayland_run((pthread_barrier_t *) data);
+    return 0;
+}
+#endif /* BUILD_XAWT_XWAYLAND */
+
 /*
  * XIOErrorHandler
  */
@@ -748,6 +763,26 @@
         }
     }
 
+#ifdef BUILD_XAWT_XWAYLAND
+    if (getenv("_AWT_USE_XWAYLAND") != NULL &&
+        strlen(getenv("_AWT_USE_XWAYLAND")) > 0) {
+        pthread_barrier_t barrier;
+        pthread_t thread;
+        pthread_attr_t attr;
+        int rv;
+
+        rv = pthread_barrier_init(&barrier, NULL, 2);
+        assert(!rv);
+        pthread_attr_init(&attr);
+        rv = pthread_create(&thread, &attr, xwayland_start, &barrier);
+        assert(!rv);
+        pthread_barrier_wait(&barrier);
+        pthread_barrier_destroy(&barrier);
+
+        setenv("_JAVA_AWT_WM_NONREPARENTING", "1", 1);
+    }
+#endif /* BUILD_XAWT_XWAYLAND */
+
     dpy = awt_display = XOpenDisplay(NULL);
 #ifdef NETSCAPE
     sigprocmask(SIG_SETMASK, &oldset, NULL);
diff --git a/src/solaris/native/sun/awt/xwayland.c b/src/solaris/native/sun/awt/xwayland.c
new file mode 100644
index 0000000..131dc5c
--- /dev/null
+++ b/src/solaris/native/sun/awt/xwayland.c
@@ -0,0 +1,2202 @@
+/*
+ * Copyright 2016 The Chromium Authors. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <assert.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#define WL_HIDE_DEPRECATED
+#include <wayland-client.h>
+#include <wayland-server.h>
+#include <xcb/composite.h>
+#include <xcb/xcb.h>
+
+struct xwl;
+
+struct xwl_host_callback {
+    struct wl_resource *resource;
+    struct wl_callback *proxy;
+};
+
+struct xwl_compositor {
+    struct xwl *xwl;
+    uint32_t id;
+    uint32_t version;
+    struct wl_global *host_global;
+    struct wl_compositor *internal;
+};
+
+struct xwl_host_surface {
+    struct xwl_compositor *compositor;
+    struct wl_resource *resource;
+    struct wl_surface *proxy;
+    int has_contents;
+};
+
+struct xwl_host_compositor {
+    struct xwl_compositor *compositor;
+    struct wl_resource *resource;
+    struct wl_compositor *proxy;
+};
+
+struct xwl_host_buffer {
+    struct wl_resource *resource;
+    struct wl_buffer *proxy;
+};
+
+struct xwl_host_shm_pool {
+    struct wl_resource *resource;
+    struct wl_shm_pool *proxy;
+};
+
+struct xwl_host_shm {
+    struct xwl_shm *shm;
+    struct wl_resource *resource;
+    struct wl_shm *proxy;
+};
+
+struct xwl_shm {
+    struct xwl *xwl;
+    uint32_t id;
+    struct wl_global *host_global;
+};
+
+struct xwl_host_shell {
+    struct xwl_shell *shell;
+    struct wl_resource *resource;
+    struct wl_shell *proxy;
+};
+
+struct xwl_shell {
+    struct xwl *xwl;
+    uint32_t id;
+    struct wl_global *host_global;
+    struct wl_shell *internal;
+};
+
+struct xwl_host_output {
+    struct xwl_output *output;
+    struct wl_resource *resource;
+    struct wl_output *proxy;
+};
+
+struct xwl_output {
+    struct xwl *xwl;
+    uint32_t id;
+    uint32_t version;
+    struct wl_global *host_global;
+    struct wl_list link;
+};
+
+struct xwl_seat {
+    struct xwl *xwl;
+    uint32_t id;
+    uint32_t version;
+    struct wl_global *host_global;
+    struct wl_list link;
+};
+
+struct xwl_host_pointer {
+    struct xwl_seat *seat;
+    struct wl_resource *resource;
+    struct wl_pointer *proxy;
+};
+
+struct xwl_host_keyboard {
+    struct xwl_seat *seat;
+    struct wl_resource *resource;
+    struct wl_keyboard *proxy;
+};
+
+struct xwl_host_touch {
+    struct xwl_seat *seat;
+    struct wl_resource *resource;
+    struct wl_touch *proxy;
+};
+
+struct xwl_host_seat {
+    struct xwl_seat *seat;
+    struct wl_resource *resource;
+    struct wl_seat *proxy;
+};
+
+struct xwl_window {
+    struct xwl *xwl;
+    xcb_window_t id;
+    uint32_t host_surface_id;
+    int unpaired;
+    int x;
+    int y;
+    int mapped;
+    int override_redirect;
+    struct wl_shell_surface *shell_surface;
+    struct wl_list link;
+};
+
+enum {
+    ATOM_WM_S0,
+    ATOM_WM_PROTOCOLS,
+    ATOM_WM_DELETE_WINDOW,
+    ATOM_WL_SURFACE_ID,
+    ATOM_LAST = ATOM_WL_SURFACE_ID,
+};
+
+struct xwl {
+    pthread_barrier_t *barrier;
+    struct wl_display *display;
+    struct wl_display *host_display;
+    struct wl_client *client;
+    struct xwl_compositor* compositor;
+    struct xwl_shm* shm;
+    struct xwl_shell* shell;
+    struct wl_list outputs;
+    struct wl_list seats;
+    struct wl_event_source *display_event_source;
+    int wm_fd;
+    xcb_connection_t *connection;
+    xcb_screen_t *screen;
+    xcb_window_t window;
+    struct wl_list windows, unpaired_windows;
+    struct xwl_window *host_focus_window;
+    xcb_window_t focus_window;
+    int32_t scale;
+    union {
+        const char *name;
+        xcb_intern_atom_cookie_t cookie;
+        xcb_atom_t value;
+    } atoms[ATOM_LAST + 1];
+};
+
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+static void
+xwl_shell_surface_ping(void *data,
+                       struct wl_shell_surface *shell_surface,
+                       uint32_t serial)
+{
+    struct xwl_window *window = wl_shell_surface_get_user_data(shell_surface);
+
+    if (getenv("_AWT_XWAYLAND_SEND_DELETE_ON_PING") != NULL) {
+        xcb_client_message_event_t event = {
+            .response_type = XCB_CLIENT_MESSAGE,
+            .format = 32,
+            .window = window->id,
+            .type = window->xwl->atoms[ATOM_WM_PROTOCOLS].value,
+            .data.data32 = {
+                window->xwl->atoms[ATOM_WM_DELETE_WINDOW].value,
+                XCB_CURRENT_TIME,
+            },
+        };
+
+        xcb_send_event(window->xwl->connection,
+                       0,
+                       window->id,
+                       XCB_EVENT_MASK_NO_EVENT,
+                       (const char *) &event);
+    }
+}
+
+static void
+xwl_shell_surface_configure(void *data,
+                            struct wl_shell_surface *shell_surface,
+                            uint32_t edges,
+                            int32_t width,
+                            int32_t height)
+{
+    struct xwl_window *window = wl_shell_surface_get_user_data(shell_surface);
+    int32_t scale = window->xwl->scale;
+    uint32_t mask, values[2];
+
+    mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
+    values[0] = width * scale;
+    values[1] = height * scale;
+
+    xcb_configure_window(window->xwl->connection, window->id, mask, values);
+}
+
+static void
+xwl_shell_surface_popup_done(void *data,
+                             struct wl_shell_surface *shell_surface)
+{
+}
+
+static const struct wl_shell_surface_listener xwl_shell_surface_listener = {
+    xwl_shell_surface_ping,
+    xwl_shell_surface_configure,
+    xwl_shell_surface_popup_done
+};
+
+static void
+xwl_window_update(struct xwl_window *window)
+{
+    struct wl_resource *host_resource = NULL;
+    struct xwl_host_surface *host_surface;
+    struct wl_surface *surface;
+    struct xwl *xwl = window->xwl;
+    struct xwl_window *parent = NULL;
+    xcb_window_t parent_window = 0;
+    uint32_t flags = 0;
+
+    if (window->host_surface_id) {
+        host_resource = wl_client_get_object(xwl->client,
+                                             window->host_surface_id);
+        if (host_resource && window->unpaired) {
+            wl_list_remove(&window->link);
+            wl_list_insert(&xwl->windows, &window->link);
+            window->unpaired = 0;
+        }
+    } else if (!window->unpaired) {
+        wl_list_remove(&window->link);
+        wl_list_insert(&xwl->unpaired_windows, &window->link);
+        window->unpaired = 1;
+    }
+
+    if (!window->mapped) {
+        if (window->shell_surface) {
+            wl_shell_surface_destroy(window->shell_surface);
+            window->shell_surface = NULL;
+        }
+        return;
+    }
+
+    if (window->shell_surface)
+        return;
+
+    if (!host_resource)
+        return;
+
+    host_surface = wl_resource_get_user_data(host_resource);
+    assert(host_surface);
+
+    assert(xwl->shell);
+    assert(xwl->shell->internal);
+
+    if (window->override_redirect) {
+        parent_window = xwl->focus_window;
+        flags = WL_SHELL_SURFACE_TRANSIENT_INACTIVE;
+    } else {
+        xcb_get_property_reply_t *reply =
+            xcb_get_property_reply(xwl->connection,
+                                   xcb_get_property(xwl->connection,
+                                                    0,
+                                                    window->id,
+                                                    XCB_ATOM_WM_TRANSIENT_FOR,
+                                                    XCB_ATOM_WINDOW,
+                                                    0,
+                                                    1),
+                                   NULL);
+        if (reply)
+            parent_window = *((uint32_t *) xcb_get_property_value(reply));
+    }
+
+    if (parent_window) {
+        struct xwl_window *sibling;
+
+        wl_list_for_each(sibling, &xwl->windows, link) {
+            if (sibling->id == parent_window) {
+                parent = sibling;
+                break;
+            }
+        }
+    }
+
+    window->shell_surface = wl_shell_get_shell_surface(xwl->shell->internal,
+                                                       host_surface->proxy);
+    wl_shell_surface_set_user_data(window->shell_surface, window);
+    wl_shell_surface_add_listener(window->shell_surface,
+                                  &xwl_shell_surface_listener,
+                                  window);
+
+    if (parent) {
+        struct wl_resource *parent_resource =
+            wl_client_get_object(xwl->client, parent->host_surface_id);
+        struct xwl_host_surface *parent_host_surface =
+            wl_resource_get_user_data(parent_resource);
+
+        wl_shell_surface_set_transient(window->shell_surface,
+                                       parent_host_surface->proxy,
+                                       (window->x - parent->x) / xwl->scale,
+                                       (window->y - parent->y) / xwl->scale,
+                                       flags);
+    } else {
+        wl_shell_surface_set_toplevel(window->shell_surface);
+    }
+
+    if (host_surface->has_contents)
+        wl_surface_commit(host_surface->proxy);
+}
+
+static void
+xwl_host_surface_destroy(struct wl_client *client,
+                         struct wl_resource *resource)
+{
+    wl_resource_destroy(resource);
+}
+
+static void
+xwl_host_surface_attach(struct wl_client *client,
+                        struct wl_resource *resource,
+                        struct wl_resource *buffer_resource,
+                        int32_t x,
+                        int32_t y)
+{
+    struct xwl_host_surface *host = wl_resource_get_user_data(resource);
+    struct xwl_host_buffer *host_buffer = wl_resource_get_user_data(
+        buffer_resource);
+    int32_t scale = host->compositor->xwl->scale;
+
+    wl_surface_attach(host->proxy, host_buffer->proxy, x / scale, y / scale);
+    wl_surface_set_buffer_scale(host->proxy, scale);
+}
+
+static void
+xwl_host_surface_damage(struct wl_client *client,
+                        struct wl_resource *resource,
+                        int32_t x,
+                        int32_t y,
+                        int32_t width,
+                        int32_t height)
+{
+    struct xwl_host_surface *host = wl_resource_get_user_data(resource);
+    int32_t scale = host->compositor->xwl->scale;
+    int32_t x1, y1, x2, y2;
+
+    // Round to enclosing rect.
+    x1 = x / scale;
+    y1 = y / scale;
+    x2 = (x + width + scale - 1) / scale;
+    y2 = (y + height + scale - 1) / scale;
+
+    wl_surface_damage(host->proxy, x1, y1, x2 - x1, y2 - y1);
+}
+
+static void
+xwl_frame_callback_done(void *data,
+                        struct wl_callback *callback,
+                        uint32_t time)
+{
+    struct xwl_host_callback *host = wl_callback_get_user_data(callback);
+
+    wl_callback_send_done(host->resource, time);
+}
+
+static const struct wl_callback_listener xwl_frame_callback_listener = {
+    xwl_frame_callback_done
+};
+
+static void
+xwl_host_callback_destroy(struct wl_resource *resource)
+{
+    struct xwl_host_callback *host = wl_resource_get_user_data(resource);
+
+    wl_callback_destroy(host->proxy);
+    wl_resource_set_user_data(resource, NULL);
+    free(host);
+}
+
+static void
+xwl_host_surface_frame(struct wl_client *client,
+                       struct wl_resource *resource,
+                       uint32_t callback)
+{
+    struct xwl_host_surface *host = wl_resource_get_user_data(resource);
+    struct xwl_host_callback *host_callback;
+
+    host_callback = malloc(sizeof(*host_callback));
+    assert(host_callback);
+
+    host_callback->resource = wl_resource_create(client,
+                                                 &wl_callback_interface,
+                                                 1,
+                                                 callback);
+    wl_resource_set_implementation(host_callback->resource,
+                                   NULL,
+                                   host_callback,
+                                   xwl_host_callback_destroy);
+    host_callback->proxy = wl_surface_frame(host->proxy);
+    wl_callback_set_user_data(host_callback->proxy, host_callback);
+    wl_callback_add_listener(host_callback->proxy,
+                             &xwl_frame_callback_listener,
+                             host_callback);
+}
+
+static void
+xwl_host_surface_set_opaque_region(struct wl_client *client,
+                                   struct wl_resource *resource,
+                                   struct wl_resource *region_resource)
+{
+    /* Not implemented */
+    wl_resource_post_no_memory(resource);
+}
+
+static void
+xwl_host_surface_set_input_region(struct wl_client *client,
+                                  struct wl_resource *resource,
+                                  struct wl_resource *region_resource)
+{
+    /* Not implemented */
+    wl_resource_post_no_memory(resource);
+}
+
+static void
+xwl_host_surface_commit(struct wl_client *client,
+                        struct wl_resource *resource)
+{
+    struct xwl_host_surface *host = wl_resource_get_user_data(resource);
+
+    wl_surface_commit(host->proxy);
+    host->has_contents = 1;
+}
+
+static void
+xwl_host_surface_set_buffer_transform(struct wl_client *client,
+                                      struct wl_resource *resource,
+                                      int32_t transform)
+{
+    /* Not implemented */
+    wl_resource_post_no_memory(resource);
+}
+
+static void
+xwl_host_surface_set_buffer_scale(struct wl_client *client,
+                                  struct wl_resource *resource,
+                                  int32_t scale)
+{
+    /* Not implemented */
+    wl_resource_post_no_memory(resource);
+}
+
+#ifdef WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION
+static void
+xwl_host_surface_damage_buffer(struct wl_client *client,
+                               struct wl_resource *resource,
+                               int32_t x,
+                               int32_t y,
+                               int32_t width,
+                               int32_t height)
+{
+    /* Not implemented */
+    wl_resource_post_no_memory(resource);
+}
+#endif
+
+static const struct wl_surface_interface xwl_surface_implementation = {
+    xwl_host_surface_destroy,
+    xwl_host_surface_attach,
+    xwl_host_surface_damage,
+    xwl_host_surface_frame,
+    xwl_host_surface_set_opaque_region,
+    xwl_host_surface_set_input_region,
+    xwl_host_surface_commit,
+    xwl_host_surface_set_buffer_transform,
+    xwl_host_surface_set_buffer_scale,
+#ifdef WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION
+    xwl_host_surface_damage_buffer
+#endif
+};
+
+static void
+xwl_destroy_host_surface(struct wl_resource *resource)
+{
+    struct xwl_host_surface *host = wl_resource_get_user_data(resource);
+    struct xwl_window *window;
+
+    wl_list_for_each(window, &host->compositor->xwl->windows, link) {
+        if (window->host_surface_id == wl_resource_get_id(resource)) {
+            window->host_surface_id = 0;
+            xwl_window_update(window);
+            break;
+        }
+    }
+
+    wl_surface_destroy(host->proxy);
+    wl_resource_set_user_data(resource, NULL);
+    free(host);
+}
+
+static void
+xwl_compositor_create_host_surface(struct wl_client *client,
+                                   struct wl_resource *resource,
+                                   uint32_t id)
+{
+    struct xwl_host_compositor *host = wl_resource_get_user_data(resource);
+    struct xwl_host_surface *host_surface;
+    struct xwl_window *window;
+
+    host_surface = malloc(sizeof(*host_surface));
+    assert(host_surface);
+
+    host_surface->compositor = host->compositor;
+    host_surface->has_contents = 0;
+    host_surface->resource = wl_resource_create(
+        client,
+        &wl_surface_interface,
+        wl_resource_get_version(resource),
+        id);
+    wl_resource_set_implementation(host_surface->resource,
+                                   &xwl_surface_implementation,
+                                   host_surface,
+                                   xwl_destroy_host_surface);
+    host_surface->proxy = wl_compositor_create_surface(host->proxy);
+    wl_surface_set_user_data(host_surface->proxy, host_surface);
+
+    wl_list_for_each(window, &host->compositor->xwl->unpaired_windows, link) {
+        if (window->host_surface_id == id) {
+            xwl_window_update(window);
+            break;
+        }
+    }
+}
+
+static void
+xwl_compositor_create_host_region(struct wl_client *client,
+                                  struct wl_resource *resource,
+                                  uint32_t id)
+{
+    /* Not implemented */
+    wl_resource_post_no_memory(resource);
+}
+
+static const struct wl_compositor_interface xwl_compositor_implementation = {
+    xwl_compositor_create_host_surface,
+    xwl_compositor_create_host_region
+};
+
+static void
+xwl_destroy_host_compositor(struct wl_resource *resource)
+{
+    struct xwl_host_compositor *host = wl_resource_get_user_data(resource);
+
+    wl_compositor_destroy(host->proxy);
+    wl_resource_set_user_data(resource, NULL);
+    free(host);
+}
+
+static void
+xwl_bind_host_compositor(struct wl_client *client,
+                         void *data,
+                         uint32_t version,
+                         uint32_t id)
+{
+    struct xwl_compositor* compositor = (struct xwl_compositor *) data;
+    struct xwl_host_compositor *host;
+
+    host = malloc(sizeof(*host));
+    assert(host);
+    host->compositor = compositor;
+    host->resource = wl_resource_create(client,
+                                        &wl_compositor_interface,
+                                        MIN(version, compositor->version),
+                                        id);
+    wl_resource_set_implementation(host->resource,
+                                   &xwl_compositor_implementation,
+                                   host,
+                                   xwl_destroy_host_compositor);
+    host->proxy = wl_registry_bind(
+        wl_display_get_registry(compositor->xwl->display),
+        compositor->id,
+        &wl_compositor_interface,
+        compositor->version);
+    wl_compositor_set_user_data(host->proxy, host);
+}
+
+static void
+xwl_host_buffer_destroy(struct wl_client *client,
+                        struct wl_resource *resource)
+{
+    wl_resource_destroy(resource);
+}
+
+static const struct wl_buffer_interface xwl_buffer_implementation = {
+    xwl_host_buffer_destroy
+};
+
+static void
+xwl_buffer_release(void *data,
+                   struct wl_buffer *buffer)
+{
+    struct xwl_host_buffer *host = wl_buffer_get_user_data(buffer);
+
+    wl_buffer_send_release(host->resource);
+}
+
+static const struct wl_buffer_listener xwl_buffer_listener = {
+    xwl_buffer_release
+};
+
+static void
+xwl_destroy_host_buffer(struct wl_resource *resource)
+{
+    struct xwl_host_buffer *host = wl_resource_get_user_data(resource);
+
+    wl_buffer_destroy(host->proxy);
+    wl_resource_set_user_data(resource, NULL);
+    free(host);
+}
+
+static void
+xwl_host_shm_pool_create_host_buffer(struct wl_client *client,
+                                     struct wl_resource *resource,
+                                     uint32_t id,
+                                     int32_t offset,
+                                     int32_t width,
+                                     int32_t height,
+                                     int32_t stride,
+                                     uint32_t format)
+{
+    struct xwl_host_shm_pool *host = wl_resource_get_user_data(resource);
+    struct xwl_host_buffer *host_buffer;
+
+    host_buffer = malloc(sizeof(*host_buffer));
+    assert(host_buffer);
+
+    host_buffer->resource = wl_resource_create(client,
+                                               &wl_buffer_interface,
+                                               1,
+                                               id);
+    wl_resource_set_implementation(host_buffer->resource,
+                                   &xwl_buffer_implementation,
+                                   host_buffer,
+                                   xwl_destroy_host_buffer);
+    host_buffer->proxy = wl_shm_pool_create_buffer(host->proxy,
+                                                   offset,
+                                                   width,
+                                                   height,
+                                                   stride,
+                                                   format);
+    wl_buffer_set_user_data(host_buffer->proxy, host_buffer);
+    wl_buffer_add_listener(host_buffer->proxy,
+                           &xwl_buffer_listener,
+                           host_buffer);
+}
+
+static void
+xwl_host_shm_pool_destroy(struct wl_client *client,
+                          struct wl_resource *resource)
+{
+    wl_resource_destroy(resource);
+}
+
+static void
+xwl_host_shm_pool_resize(struct wl_client *client,
+                         struct wl_resource *resource,
+                         int32_t size)
+{
+    struct xwl_host_shm_pool *host = wl_resource_get_user_data(resource);
+
+    wl_shm_pool_resize(host->proxy, size);
+}
+
+static const struct wl_shm_pool_interface xwl_shm_pool_implementation = {
+    xwl_host_shm_pool_create_host_buffer,
+    xwl_host_shm_pool_destroy,
+    xwl_host_shm_pool_resize
+};
+
+static void
+xwl_destroy_host_shm_pool(struct wl_resource *resource)
+{
+    struct xwl_host_shm_pool *host = wl_resource_get_user_data(resource);
+
+    wl_shm_pool_destroy(host->proxy);
+    wl_resource_set_user_data(resource, NULL);
+    free(host);
+}
+
+static void
+xwl_shm_create_host_pool(struct wl_client *client,
+                         struct wl_resource *resource,
+                         uint32_t id,
+                         int fd,
+                         int32_t size)
+{
+    struct xwl_host_shm *host = wl_resource_get_user_data(resource);
+    struct xwl_host_shm_pool *host_shm_pool;
+
+    host_shm_pool = malloc(sizeof(*host_shm_pool));
+    assert(host_shm_pool);
+
+    host_shm_pool->resource = wl_resource_create(client,
+                                                 &wl_shm_pool_interface,
+                                                 1,
+                                                 id);
+    wl_resource_set_implementation(host_shm_pool->resource,
+                                   &xwl_shm_pool_implementation,
+                                   host_shm_pool,
+                                   xwl_destroy_host_shm_pool);
+    host_shm_pool->proxy = wl_shm_create_pool(host->proxy, fd, size);
+    wl_shm_pool_set_user_data(host_shm_pool->proxy, host_shm_pool);
+
+    close(fd);
+}
+
+static const struct wl_shm_interface xwl_shm_implementation = {
+    xwl_shm_create_host_pool
+};
+
+static void
+xwl_destroy_host_shm(struct wl_resource *resource)
+{
+    struct xwl_host_shm *host = wl_resource_get_user_data(resource);
+
+    wl_shm_destroy(host->proxy);
+    wl_resource_set_user_data(resource, NULL);
+    free(host);
+}
+
+static void
+xwl_bind_host_shm(struct wl_client *client,
+                  void *data,
+                  uint32_t version,
+                  uint32_t id)
+{
+    struct xwl_shm* shm = (struct xwl_shm *) data;
+    struct xwl_host_shm *host;
+
+    host = malloc(sizeof(*host));
+    assert(host);
+    host->shm = shm;
+    host->resource = wl_resource_create(client,
+                                        &wl_shm_interface,
+                                        1,
+                                        id);
+    wl_resource_set_implementation(host->resource,
+                                   &xwl_shm_implementation,
+                                   host,
+                                   xwl_destroy_host_shm);
+    host->proxy = wl_registry_bind(wl_display_get_registry(shm->xwl->display),
+                                   shm->id,
+                                   &wl_shm_interface,
+                                   wl_resource_get_version(host->resource));
+    wl_shm_set_user_data(host->proxy, host);
+}
+
+static void
+xwl_host_shell_get_host_shell_surface(struct wl_client *client,
+                                      struct wl_resource *resource,
+                                      uint32_t id,
+                                      struct wl_resource *surface_resource)
+{
+    /* Not implemented */
+    wl_resource_post_no_memory(resource);
+}
+
+static const struct wl_shell_interface xwl_shell_implementation = {
+    xwl_host_shell_get_host_shell_surface
+};
+
+static void
+xwl_destroy_host_shell(struct wl_resource *resource)
+{
+    struct xwl_host_shell *host = wl_resource_get_user_data(resource);
+
+    wl_shell_destroy(host->proxy);
+    wl_resource_set_user_data(resource, NULL);
+    free(host);
+}
+
+static void
+xwl_bind_host_shell(struct wl_client *client,
+                    void *data,
+                    uint32_t version,
+                    uint32_t id)
+{
+    struct xwl_shell* shell = (struct xwl_shell *) data;
+    struct xwl_host_shell *host;
+
+    host = malloc(sizeof(*host));
+    assert(host);
+    host->shell = shell;
+    host->resource = wl_resource_create(client,
+                                        &wl_shell_interface,
+                                        1,
+                                        id);
+    wl_resource_set_implementation(host->resource,
+                                   &xwl_shell_implementation,
+                                   host,
+                                   xwl_destroy_host_shell);
+    host->proxy = wl_registry_bind(wl_display_get_registry(shell->xwl->display),
+                                   shell->id,
+                                   &wl_shell_interface,
+                                   wl_resource_get_version(host->resource));
+    wl_shell_set_user_data(host->proxy, host);
+}
+
+static void
+xwl_output_geometry(void *data,
+                    struct wl_output *output,
+                    int x,
+                    int y,
+                    int physical_width,
+                    int physical_height,
+                    int subpixel,
+                    const char *make,
+                    const char *model,
+                    int transform)
+{
+    struct xwl_host_output *host = wl_output_get_user_data(output);
+
+    wl_output_send_geometry(host->resource,
+                            x,
+                            y,
+                            physical_width,
+                            physical_height,
+                            subpixel,
+                            make,
+                            model,
+                            transform);
+}
+
+static void
+xwl_output_mode(void *data,
+                struct wl_output *output,
+                uint32_t flags,
+                int width,
+                int height,
+                int refresh)
+{
+    struct xwl_host_output *host = wl_output_get_user_data(output);
+
+    wl_output_send_mode(host->resource, flags, width, height, refresh);
+}
+
+static void
+xwl_output_done(void *data,
+                struct wl_output *output)
+{
+    struct xwl_host_output *host = wl_output_get_user_data(output);
+
+    wl_output_send_done(host->resource);
+}
+
+static void
+xwl_output_scale(void *data,
+                 struct wl_output *output,
+                 int32_t scale)
+{
+    struct xwl_host_output *host = wl_output_get_user_data(output);
+
+    // Always 1 as device scale factor is emulated.
+    wl_output_send_scale(host->resource, 1);
+}
+
+static const struct wl_output_listener xwl_output_listener = {
+    xwl_output_geometry,
+    xwl_output_mode,
+    xwl_output_done,
+    xwl_output_scale
+};
+
+static void
+xwl_destroy_host_output(struct wl_resource *resource)
+{
+    struct xwl_host_output *host = wl_resource_get_user_data(resource);
+
+    wl_output_destroy(host->proxy);
+    wl_resource_set_user_data(resource, NULL);
+    free(host);
+}
+
+static void
+xwl_bind_host_output(struct wl_client *client,
+                     void *data,
+                     uint32_t version,
+                     uint32_t id)
+{
+    struct xwl_output* output = (struct xwl_output *) data;
+    struct xwl_host_output *host;
+
+    host = malloc(sizeof(*host));
+    assert(host);
+    host->output = output;
+    host->resource = wl_resource_create(client,
+                                        &wl_output_interface,
+                                        MIN(version, output->version),
+                                        id);
+    wl_resource_set_implementation(host->resource,
+                                   NULL,
+                                   host,
+                                   xwl_destroy_host_output);
+    host->proxy = wl_registry_bind(
+        wl_display_get_registry(output->xwl->display),
+        output->id,
+        &wl_output_interface,
+        wl_resource_get_version(host->resource));
+    wl_output_set_user_data(host->proxy, host);
+    wl_output_add_listener(host->proxy, &xwl_output_listener, host);
+}
+
+static void
+xwl_host_pointer_set_cursor(struct wl_client *client,
+                            struct wl_resource *resource,
+                            uint32_t serial,
+                            struct wl_resource *surface_resource,
+                            int32_t hotspot_x,
+                            int32_t hotspot_y)
+{
+    struct xwl_host_pointer *host = wl_resource_get_user_data(resource);
+    struct xwl_host_surface *host_surface = NULL;
+    int32_t scale = host->seat->xwl->scale;
+
+    if (surface_resource)
+        host_surface = wl_resource_get_user_data(surface_resource);
+
+    wl_pointer_set_cursor(host->proxy,
+                          serial,
+                          host_surface ? host_surface->proxy : NULL,
+                          hotspot_x / scale,
+                          hotspot_y / scale);
+}
+
+static void
+xwl_host_pointer_release(struct wl_client *client,
+                         struct wl_resource *resource)
+{
+    wl_resource_destroy(resource);
+}
+
+static const struct wl_pointer_interface xwl_pointer_implementation = {
+    xwl_host_pointer_set_cursor,
+    xwl_host_pointer_release
+};
+
+static void
+xwl_pointer_enter(void *data,
+                  struct wl_pointer *pointer,
+                  uint32_t serial,
+                  struct wl_surface *surface,
+                  wl_fixed_t x,
+                  wl_fixed_t y)
+{
+    struct xwl_host_pointer *host = wl_pointer_get_user_data(pointer);
+    struct xwl_host_surface *host_surface = wl_surface_get_user_data(surface);
+    int32_t scale = host->seat->xwl->scale;
+
+    wl_pointer_send_enter(host->resource,
+                          serial,
+                          host_surface->resource,
+                          x * scale,
+                          y * scale);
+}
+
+static void
+xwl_pointer_leave(void *data,
+                  struct wl_pointer *pointer,
+                  uint32_t serial,
+                  struct wl_surface *surface)
+{
+    struct xwl_host_pointer *host = wl_pointer_get_user_data(pointer);
+    struct xwl_host_surface *host_surface =
+        surface ? wl_surface_get_user_data(surface) : NULL;
+
+    if (!host_surface)
+        return;
+
+    wl_pointer_send_leave(host->resource, serial, host_surface->resource);
+}
+
+static void
+xwl_pointer_motion(void *data,
+                   struct wl_pointer *pointer,
+                   uint32_t time,
+                   wl_fixed_t x,
+                   wl_fixed_t y)
+{
+    struct xwl_host_pointer *host = wl_pointer_get_user_data(pointer);
+    int32_t scale = host->seat->xwl->scale;
+
+    wl_pointer_send_motion(host->resource, time, x * scale, y * scale);
+}
+
+static void
+xwl_pointer_button(void *data,
+                   struct wl_pointer *pointer,
+                   uint32_t serial,
+                   uint32_t time,
+                   uint32_t button,
+                   uint32_t state)
+{
+    struct xwl_host_pointer *host = wl_pointer_get_user_data(pointer);
+
+    wl_pointer_send_button(host->resource,
+                           serial,
+                           time,
+                           button,
+                           state);
+}
+
+static void
+xwl_pointer_axis(void *data,
+                 struct wl_pointer *pointer,
+                 uint32_t time,
+                 uint32_t axis,
+                 wl_fixed_t value)
+{
+    struct xwl_host_pointer *host = wl_pointer_get_user_data(pointer);
+    int32_t scale = host->seat->xwl->scale;
+
+    wl_pointer_send_axis(host->resource, time, axis, value * scale);
+}
+
+#ifdef WL_POINTER_FRAME_SINCE_VERSION
+static void
+xwl_pointer_frame(void *data,
+                  struct wl_pointer *pointer)
+{
+    struct xwl_host_pointer *host = wl_pointer_get_user_data(pointer);
+
+    wl_pointer_send_frame(host->resource);
+}
+#endif
+
+#ifdef WL_POINTER_AXIS_SOURCE_SINCE_VERSION
+void
+xwl_pointer_axis_source(void *data,
+                        struct wl_pointer *pointer,
+                        uint32_t axis_source)
+{
+    struct xwl_host_pointer *host = wl_pointer_get_user_data(pointer);
+
+    wl_pointer_send_axis_source(host->resource, axis_source);
+}
+#endif
+
+#ifdef WL_POINTER_AXIS_STOP_SINCE_VERSION
+static void
+xwl_pointer_axis_stop(void *data,
+                      struct wl_pointer *pointer,
+                      uint32_t time,
+                      uint32_t axis)
+{
+    struct xwl_host_pointer *host = wl_pointer_get_user_data(pointer);
+
+    wl_pointer_send_axis_stop(host->resource, time, axis);
+}
+#endif
+
+#ifdef WL_POINTER_AXIS_DISCRETE_SINCE_VERSION
+static void
+xwl_pointer_axis_discrete(void *data,
+                          struct wl_pointer *pointer,
+                          uint32_t axis,
+                          int32_t discrete)
+{
+    struct xwl_host_pointer *host = wl_pointer_get_user_data(pointer);
+
+    wl_pointer_send_axis_discrete(host->resource, axis, discrete);
+}
+#endif
+
+static const struct wl_pointer_listener xwl_pointer_listener = {
+    xwl_pointer_enter,
+    xwl_pointer_leave,
+    xwl_pointer_motion,
+    xwl_pointer_button,
+    xwl_pointer_axis,
+#ifdef WL_POINTER_FRAME_SINCE_VERSION
+    xwl_pointer_frame,
+#endif
+#ifdef WL_POINTER_AXIS_SOURCE_SINCE_VERSION
+    xwl_pointer_axis_source,
+#endif
+#ifdef WL_POINTER_AXIS_DISCRETE_SINCE_VERSION
+    xwl_pointer_axis_stop,
+#endif
+#ifdef WL_POINTER_AXIS_DISCRETE_SINCE_VERSION
+    xwl_pointer_axis_discrete
+#endif
+};
+
+static void
+xwl_host_keyboard_release(struct wl_client *client,
+                          struct wl_resource *resource)
+{
+    wl_resource_destroy(resource);
+}
+
+static const struct wl_keyboard_interface xwl_keyboard_implementation = {
+    xwl_host_keyboard_release
+};
+
+static void
+xwl_keyboard_keymap(void *data,
+                    struct wl_keyboard *keyboard,
+                    uint32_t format,
+                    int32_t fd,
+                    uint32_t size)
+{
+    struct xwl_host_keyboard *host = wl_keyboard_get_user_data(keyboard);
+
+    wl_keyboard_send_keymap(host->resource, format, fd, size);
+
+    close(fd);
+}
+
+static void
+xwl_keyboard_enter(void *data,
+                   struct wl_keyboard *keyboard,
+                   uint32_t serial,
+                   struct wl_surface *surface,
+                   struct wl_array *keys)
+{
+    struct xwl_host_keyboard *host = wl_keyboard_get_user_data(keyboard);
+    struct xwl_host_surface *host_surface = wl_surface_get_user_data(surface);
+    struct xwl *xwl = host->seat->xwl;
+    struct xwl_window *window;
+
+    wl_keyboard_send_enter(host->resource,
+                           serial,
+                           host_surface->resource,
+                           keys);
+
+    wl_list_for_each(window, &xwl->windows, link) {
+        uint32_t host_resource_id = wl_resource_get_id(host_surface->resource);
+        if (window->host_surface_id == host_resource_id) {
+            uint32_t values[1];
+
+            xwl->host_focus_window = window;
+
+            if (window->override_redirect)
+               return;
+
+            xcb_set_input_focus(xwl->connection,
+                                XCB_INPUT_FOCUS_NONE,
+                                window->id,
+                                XCB_CURRENT_TIME);
+            values[0] = XCB_STACK_MODE_ABOVE;
+            xcb_configure_window(xwl->connection,
+                                 window->id,
+                                 XCB_CONFIG_WINDOW_STACK_MODE,
+                                 values);
+            return;
+        }
+    }
+}
+
+static void
+xwl_keyboard_leave(void *data,
+                   struct wl_keyboard *keyboard,
+                   uint32_t serial,
+                   struct wl_surface *surface)
+{
+    struct xwl_host_keyboard *host = wl_keyboard_get_user_data(keyboard);
+    struct xwl_host_surface *host_surface =
+        surface ? wl_surface_get_user_data(surface) : NULL;
+    struct xwl *xwl = host->seat->xwl;
+
+    if (!host_surface)
+      return;
+
+    wl_keyboard_send_leave(host->resource, serial, host_surface->resource);
+
+    if (xwl->host_focus_window) {
+        uint32_t host_resource_id = wl_resource_get_id(host_surface->resource);
+        if (xwl->host_focus_window->host_surface_id == host_resource_id) {
+            xwl->host_focus_window = NULL;
+            xcb_set_input_focus(xwl->connection,
+                                XCB_INPUT_FOCUS_NONE,
+                                XCB_NONE,
+                                XCB_CURRENT_TIME);
+        }
+    }
+}
+
+static void
+xwl_keyboard_key(void *data,
+                 struct wl_keyboard *keyboard,
+                 uint32_t serial,
+                 uint32_t time,
+                 uint32_t key,
+                 uint32_t state)
+{
+    struct xwl_host_keyboard *host = wl_keyboard_get_user_data(keyboard);
+
+    wl_keyboard_send_key(host->resource,
+                         serial,
+                         time,
+                         key,
+                         state);
+}
+
+static void
+xwl_keyboard_modifiers(void *data,
+                       struct wl_keyboard *keyboard,
+                       uint32_t serial,
+                       uint32_t mods_depressed,
+                       uint32_t mods_latched,
+                       uint32_t mods_locked,
+                       uint32_t group)
+{
+    struct xwl_host_keyboard *host = wl_keyboard_get_user_data(keyboard);
+
+    wl_keyboard_send_modifiers(host->resource,
+                               serial,
+                               mods_depressed,
+                               mods_latched,
+                               mods_locked,
+                               group);
+}
+
+#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
+static void
+xwl_keyboard_repeat_info(void *data,
+                         struct wl_keyboard *keyboard,
+                         int32_t rate,
+                         int32_t delay)
+{
+    struct xwl_host_keyboard *host = wl_keyboard_get_user_data(keyboard);
+
+    wl_keyboard_send_repeat_info(host->resource, rate, delay);
+}
+#endif
+
+static const struct wl_keyboard_listener xwl_keyboard_listener = {
+    xwl_keyboard_keymap,
+    xwl_keyboard_enter,
+    xwl_keyboard_leave,
+    xwl_keyboard_key,
+    xwl_keyboard_modifiers,
+#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
+    xwl_keyboard_repeat_info
+#endif
+};
+
+static void
+xwl_host_touch_release(struct wl_client *client,
+                       struct wl_resource *resource)
+{
+    wl_resource_destroy(resource);
+}
+
+static const struct wl_touch_interface xwl_touch_implementation = {
+    xwl_host_touch_release
+};
+
+static void
+xwl_host_touch_down(void *data,
+                    struct wl_touch *touch,
+                    uint32_t serial,
+                    uint32_t time,
+                    struct wl_surface *surface,
+                    int32_t id,
+                    wl_fixed_t x,
+                    wl_fixed_t y)
+{
+    struct xwl_host_touch *host = wl_touch_get_user_data(touch);
+    struct xwl_host_surface *host_surface = wl_surface_get_user_data(surface);
+    int32_t scale = host->seat->xwl->scale;
+
+    wl_touch_send_down(host->resource,
+                       serial,
+                       time,
+                       host_surface->resource,
+                       id,
+                       x * scale,
+                       y * scale);
+}
+
+static void
+xwl_host_touch_up(void *data,
+                  struct wl_touch *touch,
+                  uint32_t serial,
+                  uint32_t time,
+                  int32_t id)
+{
+    struct xwl_host_touch *host = wl_touch_get_user_data(touch);
+
+    wl_touch_send_up(host->resource, serial, time, id);
+}
+
+static void
+xwl_host_touch_motion(void *data,
+                      struct wl_touch *touch,
+                      uint32_t time,
+                      int32_t id,
+                      wl_fixed_t x,
+                      wl_fixed_t y)
+{
+    struct xwl_host_touch *host = wl_touch_get_user_data(touch);
+    int32_t scale = host->seat->xwl->scale;
+
+    wl_touch_send_motion(host->resource, time, id, x * scale, y * scale);
+}
+
+static void
+xwl_host_touch_frame(void *data,
+                     struct wl_touch *touch)
+{
+    struct xwl_host_touch *host = wl_touch_get_user_data(touch);
+
+    wl_touch_send_frame(host->resource);
+}
+
+static void
+xwl_host_touch_cancel(void *data,
+                      struct wl_touch *touch)
+{
+    struct xwl_host_touch *host = wl_touch_get_user_data(touch);
+
+    wl_touch_send_cancel(host->resource);
+}
+
+static const struct wl_touch_listener xwl_touch_listener = {
+    xwl_host_touch_down,
+    xwl_host_touch_up,
+    xwl_host_touch_motion,
+    xwl_host_touch_frame,
+    xwl_host_touch_cancel
+};
+
+static void
+xwl_destroy_host_pointer(struct wl_resource *resource)
+{
+    struct xwl_host_pointer *host = wl_resource_get_user_data(resource);
+
+    wl_pointer_destroy(host->proxy);
+    wl_resource_set_user_data(resource, NULL);
+    free(host);
+}
+
+static void
+xwl_host_seat_get_host_pointer(struct wl_client *client,
+                               struct wl_resource *resource,
+                               uint32_t id)
+{
+    struct xwl_host_seat *host = wl_resource_get_user_data(resource);
+    struct xwl_host_pointer *host_pointer;
+
+    host_pointer = malloc(sizeof(*host_pointer));
+    assert(host_pointer);
+
+    host_pointer->seat = host->seat;
+    host_pointer->resource = wl_resource_create(
+        client,
+        &wl_pointer_interface,
+        wl_resource_get_version(resource),
+        id);
+    wl_resource_set_implementation(host_pointer->resource,
+                                   &xwl_pointer_implementation,
+                                   host_pointer,
+                                   xwl_destroy_host_pointer);
+    host_pointer->proxy = wl_seat_get_pointer(host->proxy);
+    wl_pointer_set_user_data(host_pointer->proxy, host_pointer);
+    wl_pointer_add_listener(host_pointer->proxy,
+                            &xwl_pointer_listener,
+                            host_pointer);
+}
+
+static void
+xwl_destroy_host_keyboard(struct wl_resource *resource)
+{
+    struct xwl_host_keyboard *host = wl_resource_get_user_data(resource);
+
+    wl_keyboard_destroy(host->proxy);
+    wl_resource_set_user_data(resource, NULL);
+    free(host);
+}
+
+static void
+xwl_host_seat_get_host_keyboard(struct wl_client *client,
+                                struct wl_resource *resource,
+                                uint32_t id)
+{
+    struct xwl_host_seat *host = wl_resource_get_user_data(resource);
+    struct xwl_host_keyboard *host_keyboard;
+
+    host_keyboard = malloc(sizeof(*host_keyboard));
+    assert(host_keyboard);
+
+    host_keyboard->seat = host->seat;
+    host_keyboard->resource = wl_resource_create(
+        client,
+        &wl_keyboard_interface,
+        wl_resource_get_version(resource),
+        id);
+    wl_resource_set_implementation(host_keyboard->resource,
+                                   &xwl_keyboard_implementation,
+                                   host_keyboard,
+                                   xwl_destroy_host_keyboard);
+    host_keyboard->proxy = wl_seat_get_keyboard(host->proxy);
+    wl_keyboard_set_user_data(host_keyboard->proxy, host_keyboard);
+    wl_keyboard_add_listener(host_keyboard->proxy,
+                             &xwl_keyboard_listener,
+                             host_keyboard);
+}
+
+static void
+xwl_destroy_host_touch(struct wl_resource *resource)
+{
+    struct xwl_host_touch *host = wl_resource_get_user_data(resource);
+
+    wl_touch_destroy(host->proxy);
+    wl_resource_set_user_data(resource, NULL);
+    free(host);
+}
+
+static void
+xwl_host_seat_get_host_touch(struct wl_client *client,
+                             struct wl_resource *resource,
+                             uint32_t id)
+{
+    struct xwl_host_seat *host = wl_resource_get_user_data(resource);
+    struct xwl_host_touch *host_touch;
+
+    host_touch = malloc(sizeof(*host_touch));
+    assert(host_touch);
+
+    host_touch->seat = host->seat;
+    host_touch->resource = wl_resource_create(client,
+                                              &wl_touch_interface,
+                                              wl_resource_get_version(resource),
+                                              id);
+    wl_resource_set_implementation(host_touch->resource,
+                                   &xwl_touch_implementation,
+                                   host_touch,
+                                   xwl_destroy_host_touch);
+    host_touch->proxy = wl_seat_get_touch(host->proxy);
+    wl_touch_set_user_data(host_touch->proxy, host_touch);
+    wl_touch_add_listener(host_touch->proxy, &xwl_touch_listener, host_touch);
+}
+
+#ifdef WL_SEAT_RELEASE_SINCE_VERSION
+static void
+xwl_host_seat_release(struct wl_client *client,
+                      struct wl_resource *resource)
+{
+    struct xwl_host_seat *host = wl_resource_get_user_data(resource);
+
+    wl_seat_release(host->proxy);
+}
+#endif
+
+static const struct wl_seat_interface xwl_seat_implementation = {
+    xwl_host_seat_get_host_pointer,
+    xwl_host_seat_get_host_keyboard,
+    xwl_host_seat_get_host_touch,
+#ifdef WL_SEAT_RELEASE_SINCE_VERSION
+    xwl_host_seat_release
+#endif
+};
+
+static void
+xwl_seat_capabilities(void *data,
+                      struct wl_seat *seat,
+                      uint32_t capabilities)
+{
+    struct xwl_host_seat *host = wl_seat_get_user_data(seat);
+
+    wl_seat_send_capabilities(host->resource, capabilities);
+}
+
+static void
+xwl_seat_name(void *data,
+              struct wl_seat *seat,
+              const char *name)
+{
+    struct xwl_host_seat *host = wl_seat_get_user_data(seat);
+
+    wl_seat_send_name(host->resource, name);
+}
+
+static const struct wl_seat_listener xwl_seat_listener = {
+    xwl_seat_capabilities,
+    xwl_seat_name
+};
+
+static void
+xwl_destroy_host_seat(struct wl_resource *resource)
+{
+    struct xwl_host_seat *host = wl_resource_get_user_data(resource);
+
+    wl_seat_destroy(host->proxy);
+    wl_resource_set_user_data(resource, NULL);
+    free(host);
+}
+
+static void
+xwl_bind_host_seat(struct wl_client *client,
+                   void *data,
+                   uint32_t version,
+                   uint32_t id)
+{
+    struct xwl_seat* seat = (struct xwl_seat *) data;
+    struct xwl_host_seat *host;
+
+    host = malloc(sizeof(*host));
+    assert(host);
+    host->seat = seat;
+    host->resource = wl_resource_create(client,
+                                        &wl_seat_interface,
+                                        MIN(version, seat->version),
+                                        id);
+    wl_resource_set_implementation(host->resource,
+                                   &xwl_seat_implementation,
+                                   host,
+                                   xwl_destroy_host_seat);
+    host->proxy = wl_registry_bind(wl_display_get_registry(seat->xwl->display),
+                                   seat->id,
+                                   &wl_seat_interface,
+                                   wl_resource_get_version(host->resource));
+    wl_seat_set_user_data(host->proxy, host);
+    wl_seat_add_listener(host->proxy, &xwl_seat_listener, host);
+}
+
+static void
+xwl_registry_handler(void* data,
+                     struct wl_registry *registry,
+                     uint32_t id,
+                     const char *interface,
+                     uint32_t version)
+{
+    struct xwl *xwl = (struct xwl *) data;
+
+    if (strcmp(interface, "wl_compositor") == 0) {
+        struct xwl_compositor *compositor =
+            malloc(sizeof(struct xwl_compositor));
+        assert(compositor);
+        compositor->xwl = xwl;
+        compositor->id = id;
+        assert(version >= 3);
+        compositor->version = 3;
+        compositor->host_global = wl_global_create(xwl->host_display,
+                                                   &wl_compositor_interface,
+                                                   compositor->version,
+                                                   compositor,
+                                                   xwl_bind_host_compositor);
+        compositor->internal = wl_registry_bind(registry,
+                                                id,
+                                                &wl_shell_interface,
+                                                compositor->version);
+        assert(!xwl->compositor);
+        xwl->compositor = compositor;
+    } else if (strcmp(interface, "wl_shm") == 0) {
+        struct xwl_shm *shm = malloc(sizeof(struct xwl_shm));
+        assert(shm);
+        shm->xwl = xwl;
+        shm->id = id;
+        shm->host_global = wl_global_create(xwl->host_display,
+                                            &wl_shm_interface,
+                                            1,
+                                            shm,
+                                            xwl_bind_host_shm);
+        assert(!xwl->shm);
+        xwl->shm = shm;
+    } else if (strcmp(interface, "wl_shell") == 0) {
+        struct xwl_shell *shell = malloc(sizeof(struct xwl_shell));
+        assert(shell);
+        shell->xwl = xwl;
+        shell->id = id;
+        shell->host_global = wl_global_create(xwl->host_display,
+                                              &wl_shell_interface,
+                                              1,
+                                              shell,
+                                              xwl_bind_host_shell);
+        shell->internal = wl_registry_bind(registry,
+                                           id,
+                                           &wl_shell_interface,
+                                           1);
+        assert(!xwl->shell);
+        xwl->shell = shell;
+    } else if (strcmp(interface, "wl_output") == 0) {
+        struct xwl_output *output = malloc(sizeof(struct xwl_output));
+        assert(output);
+        output->xwl = xwl;
+        output->id = id;
+        output->version = MIN(2, version);
+        output->host_global = wl_global_create(xwl->host_display,
+                                               &wl_output_interface,
+                                               output->version,
+                                               output,
+                                               xwl_bind_host_output);
+        wl_list_insert(&xwl->outputs, &output->link);
+    } else if (strcmp(interface, "wl_seat") == 0) {
+        struct xwl_seat *seat = malloc(sizeof(struct xwl_seat));
+        assert(seat);
+        seat->xwl = xwl;
+        seat->id = id;
+#ifdef WL_POINTER_FRAME_SINCE_VERSION
+        seat->version = MIN(5, version);
+#else
+        seat->version = MIN(3, version);
+#endif
+        seat->host_global = wl_global_create(xwl->host_display,
+                                             &wl_seat_interface,
+                                             seat->version,
+                                             seat,
+                                             xwl_bind_host_seat);
+        wl_list_insert(&xwl->seats, &seat->link);
+    }
+}
+
+static void
+xwl_registry_remover(void *data,
+                     struct wl_registry *registry,
+                     uint32_t id)
+{
+    struct xwl *xwl = (struct xwl *) data;
+    struct xwl_output *output;
+    struct xwl_seat *seat;
+
+    if (xwl->compositor && xwl->compositor->id == id) {
+        wl_global_destroy(xwl->compositor->host_global);
+        wl_compositor_destroy(xwl->compositor->internal);
+        free(xwl->compositor);
+        xwl->compositor = NULL;
+        return;
+    }
+    if (xwl->shm && xwl->shm->id == id) {
+        wl_global_destroy(xwl->shm->host_global);
+        free(xwl->shm);
+        xwl->shm = NULL;
+        return;
+    }
+    if (xwl->shell && xwl->shell->id == id) {
+        wl_global_destroy(xwl->shell->host_global);
+        wl_shell_destroy(xwl->shell->internal);
+        free(xwl->shell);
+        xwl->shell = NULL;
+        return;
+    }
+    wl_list_for_each(output, &xwl->outputs, link) {
+        if (output->id == id) {
+            wl_global_destroy(output->host_global);
+            wl_list_remove(&output->link);
+            free(output);
+            return;
+        }
+    }
+    wl_list_for_each(seat, &xwl->seats, link) {
+        if (seat->id == id) {
+            wl_global_destroy(seat->host_global);
+            wl_list_remove(&seat->link);
+            free(seat);
+            return;
+        }
+    }
+
+    /* Not reached */
+    assert(0);
+}
+
+static const struct wl_registry_listener xwl_registry_listener = {
+    xwl_registry_handler,
+    xwl_registry_remover
+};
+
+static int
+xwl_handle_event(int fd,
+                 uint32_t mask,
+                 void *data)
+{
+    struct xwl *xwl = (struct xwl *) data;
+    int count = 0;
+
+    if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR))
+        return 0;
+
+    if (mask & WL_EVENT_READABLE)
+        count = wl_display_dispatch(xwl->display);
+    if (mask & WL_EVENT_WRITABLE)
+        wl_display_flush(xwl->display);
+
+    if (mask == 0) {
+        count = wl_display_dispatch_pending(xwl->display);
+        wl_display_flush(xwl->display);
+    }
+
+    return count;
+}
+
+static struct xwl_window *
+xwl_lookup_window(struct xwl* xwl,
+                  xcb_window_t id)
+{
+    struct xwl_window *window;
+
+    wl_list_for_each(window, &xwl->windows, link) {
+        if (window->id == id)
+            return window;
+    }
+    wl_list_for_each(window, &xwl->unpaired_windows, link) {
+        if (window->id == id)
+            return window;
+    }
+    return NULL;
+}
+
+static void
+xwl_handle_create_notify(struct xwl *xwl,
+                         xcb_create_notify_event_t *event)
+{
+    struct xwl_window *window = malloc(sizeof(struct xwl_window));
+    assert(window);
+    window->xwl = xwl;
+    window->id = event->window;
+    window->host_surface_id = 0;
+    window->unpaired = 1;
+    window->x = event->x;
+    window->y = event->y;
+    window->mapped = 0;
+    window->override_redirect = event->override_redirect;
+    window->shell_surface = NULL;
+    wl_list_insert(&xwl->unpaired_windows, &window->link);
+    if (!event->override_redirect) {
+      uint32_t values[1];
+
+      values[0] = XCB_EVENT_MASK_FOCUS_CHANGE;
+      xcb_change_window_attributes(xwl->connection,
+                                   window->id,
+                                   XCB_CW_EVENT_MASK,
+                                   values);
+    }
+}
+
+static void
+xwl_handle_destroy_notify(struct xwl *xwl,
+                          xcb_destroy_notify_event_t *event)
+{
+    struct xwl_window *window = xwl_lookup_window(xwl, event->window);
+    if (window) {
+        if (xwl->host_focus_window == window)
+            xwl->host_focus_window = NULL;
+        if (xwl->focus_window == event->window)
+            xwl->focus_window = 0;
+        if (window->shell_surface)
+            wl_shell_surface_destroy(window->shell_surface);
+        wl_list_remove(&window->link);
+        free(window);
+    }
+}
+
+static void
+xwl_handle_map_request(struct xwl *xwl,
+                       xcb_map_request_event_t *event)
+{
+    xcb_map_window(xwl->connection, event->window);
+}
+
+static void
+xwl_handle_map_notify(struct xwl *xwl,
+                      xcb_map_notify_event_t *event)
+{
+    struct xwl_window *window = xwl_lookup_window(xwl, event->window);
+    if (window) {
+        assert(!window->mapped);
+        window->mapped = 1;
+        xwl_window_update(window);
+    }
+}
+
+static void
+xwl_handle_unmap_notify(struct xwl *xwl,
+                        xcb_unmap_notify_event_t *event)
+{
+    struct xwl_window *window = xwl_lookup_window(xwl, event->window);
+    if (window) {
+        assert(window->mapped);
+        window->mapped = 0;
+        xwl_window_update(window);
+    }
+}
+
+static void
+xwl_handle_configure_request(struct xwl *xwl,
+                             xcb_configure_request_event_t *event)
+{
+    uint32_t mask = 0, values[16];
+    int i = 0;
+
+    // Keep all managed windows centered horizontally.
+    if (event->value_mask & (XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_WIDTH)) {
+        values[i++] = xwl->screen->width_in_pixels / 2 - event->width / 2;
+        mask |= XCB_CONFIG_WINDOW_X;
+    }
+    // Keep all managed windows centered vertically.
+    if (event->value_mask & (XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_HEIGHT)) {
+        values[i++] = xwl->screen->height_in_pixels / 2 - event->height / 2;
+        mask |= XCB_CONFIG_WINDOW_Y;
+    }
+    if (event->value_mask & XCB_CONFIG_WINDOW_WIDTH) {
+        values[i++] = event->width;
+        mask |= XCB_CONFIG_WINDOW_WIDTH;
+    }
+    if (event->value_mask & XCB_CONFIG_WINDOW_HEIGHT) {
+        values[i++] = event->height;
+        mask |= XCB_CONFIG_WINDOW_HEIGHT;
+    }
+
+    xcb_configure_window(xwl->connection, event->window, mask, values);
+}
+
+static void
+xwl_handle_configure_notify(struct xwl *xwl,
+                            xcb_configure_notify_event_t *event)
+{
+    struct xwl_window *window = xwl_lookup_window(xwl, event->window);
+    if (window) {
+        window->x = event->x;
+        window->y = event->y;
+    }
+}
+
+static void
+xwl_handle_client_message(struct xwl *xwl,
+                          xcb_client_message_event_t *event)
+{
+    struct xwl_window *window;
+
+    if (event->type != xwl->atoms[ATOM_WL_SURFACE_ID].value)
+        return;
+
+    wl_list_for_each(window, &xwl->unpaired_windows, link) {
+        if (window->id == event->window) {
+            window->host_surface_id = event->data.data32[0];
+            xwl_window_update(window);
+            return;
+        }
+    }
+}
+
+static void
+xwl_handle_focus_in(struct xwl *xwl, xcb_focus_in_event_t *event)
+{
+    xwl->focus_window = event->event;
+}
+
+static void
+xwl_handle_focus_out(struct xwl *xwl, xcb_focus_out_event_t *event)
+{
+}
+
+static int
+xwl_handle_x_connection_event(int fd,
+                              uint32_t mask,
+                              void *data)
+{
+    struct xwl *xwl = (struct xwl *) data;
+    xcb_generic_event_t *event;
+    uint32_t count = 0;
+
+    if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR))
+        return 0;
+
+    while ((event = xcb_poll_for_event(xwl->connection))) {
+        switch (event->response_type & ~0x80) {
+            case XCB_CREATE_NOTIFY:
+                xwl_handle_create_notify(
+                    xwl, (xcb_create_notify_event_t *) event);
+                break;
+            case XCB_DESTROY_NOTIFY:
+                xwl_handle_destroy_notify(
+                    xwl, (xcb_destroy_notify_event_t *) event);
+                break;
+            case XCB_MAP_REQUEST:
+                xwl_handle_map_request(xwl,
+                                       (xcb_map_request_event_t *) event);
+                break;
+            case XCB_MAP_NOTIFY:
+                xwl_handle_map_notify(xwl,
+                                      (xcb_map_notify_event_t *) event);
+                break;
+            case XCB_UNMAP_NOTIFY:
+                xwl_handle_unmap_notify(xwl,
+                                        (xcb_unmap_notify_event_t *) event);
+                break;
+            case XCB_CONFIGURE_REQUEST:
+                xwl_handle_configure_request(
+                    xwl, (xcb_configure_request_event_t *) event);
+                break;
+            case XCB_CONFIGURE_NOTIFY:
+                xwl_handle_configure_notify(
+                    xwl, (xcb_configure_notify_event_t *) event);
+                break;
+            case XCB_CLIENT_MESSAGE:
+                xwl_handle_client_message(
+                    xwl, (xcb_client_message_event_t *) event);
+                break;
+            case XCB_FOCUS_IN:
+                xwl_handle_focus_in(xwl, (xcb_focus_in_event_t *) event);
+                break;
+            case XCB_FOCUS_OUT:
+                xwl_handle_focus_out(xwl, (xcb_focus_out_event_t *) event);
+                break;
+            default:
+                break;
+        }
+        free(event);
+        ++count;
+    }
+
+    if ((mask & ~WL_EVENT_WRITABLE) == 0)
+        xcb_flush(xwl->connection);
+
+    return count;
+}
+
+static void
+xwl_connect(struct xwl *xwl)
+{
+    const xcb_setup_t *setup;
+    xcb_screen_iterator_t screen_iterator;
+    uint32_t values[1];
+    xcb_void_cookie_t change_attributes_cookie, redirect_subwindows_cookie;
+    xcb_generic_error_t *error;
+    xcb_intern_atom_reply_t *atom_reply;
+    const xcb_query_extension_reply_t *composite_extension;
+    unsigned i;
+
+    xwl->connection = xcb_connect_to_fd(xwl->wm_fd, NULL);
+    assert(!xcb_connection_has_error(xwl->connection));
+
+    xcb_prefetch_extension_data(xwl->connection, &xcb_composite_id);
+
+    for (i = 0; i < ARRAY_SIZE(xwl->atoms); ++i) {
+        const char *name = xwl->atoms[i].name;
+        xwl->atoms[i].cookie = xcb_intern_atom(xwl->connection,
+                                               0,
+                                               strlen(name),
+                                               name);
+    }
+
+    setup = xcb_get_setup(xwl->connection);
+    screen_iterator = xcb_setup_roots_iterator(setup);
+    xwl->screen = screen_iterator.data;
+
+    /* Select for substructure redirect. */
+    values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
+                XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT;
+    change_attributes_cookie = xcb_change_window_attributes(xwl->connection,
+                                                            xwl->screen->root,
+                                                            XCB_CW_EVENT_MASK,
+                                                            values);
+
+    wl_event_loop_add_fd(wl_display_get_event_loop(xwl->host_display),
+                         xcb_get_file_descriptor(xwl->connection),
+                         WL_EVENT_READABLE,
+                         &xwl_handle_x_connection_event,
+                         xwl);
+
+    composite_extension = xcb_get_extension_data(xwl->connection,
+                                                 &xcb_composite_id);
+    assert(composite_extension->present);
+
+    redirect_subwindows_cookie = xcb_composite_redirect_subwindows_checked(
+        xwl->connection, xwl->screen->root, XCB_COMPOSITE_REDIRECT_MANUAL);
+
+    /* Another window manager should not be running */
+    error = xcb_request_check(xwl->connection, change_attributes_cookie);
+    assert(!error);
+
+    /* Redirecting subwindows of root for compositing should have succeeded */
+    error = xcb_request_check(xwl->connection, redirect_subwindows_cookie);
+    assert(!error);
+
+    xwl->window = xcb_generate_id(xwl->connection);
+    xcb_create_window(xwl->connection, 0, xwl->window, xwl->screen->root,
+                      0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY,
+                      XCB_COPY_FROM_PARENT, 0, NULL);
+
+    for (i = 0; i < ARRAY_SIZE(xwl->atoms); ++i) {
+        atom_reply = xcb_intern_atom_reply(xwl->connection,
+                                           xwl->atoms[i].cookie,
+                                           &error);
+        assert(!error);
+        xwl->atoms[i].value = atom_reply->atom;
+        free(atom_reply);
+    }
+
+    xcb_set_selection_owner(xwl->connection,
+                            xwl->window,
+                            xwl->atoms[ATOM_WM_S0].value,
+                            XCB_CURRENT_TIME);
+    xcb_set_input_focus(xwl->connection,
+                        XCB_INPUT_FOCUS_NONE,
+                        XCB_NONE,
+                        XCB_CURRENT_TIME);
+}
+
+static int
+xwl_handle_display_event(int fd,
+                         uint32_t mask,
+                         void *data)
+{
+    struct xwl *xwl = (struct xwl *) data;
+    char display_name[9];
+    int bytes_read = 0;
+
+    if (!(mask & WL_EVENT_READABLE))
+        return 0;
+
+    display_name[0] = ':';
+    do {
+      int bytes_left = sizeof(display_name) - bytes_read - 1;
+      int bytes;
+
+      if (!bytes_left)
+        break;
+
+      bytes = read(fd, &display_name[bytes_read + 1], bytes_left);
+      if (!bytes)
+        break;
+
+      bytes_read += bytes;
+    } while (display_name[bytes_read] != '\n');
+
+    display_name[bytes_read] = '\0';
+    setenv("DISPLAY", display_name, 1);
+
+    xwl_connect(xwl);
+
+    wl_event_source_remove(xwl->display_event_source);
+    xwl->display_event_source = NULL;
+    close(fd);
+
+    pthread_barrier_wait(xwl->barrier);
+    return 1;
+}
+
+void
+xwayland_run(pthread_barrier_t *barrier)
+{
+    struct xwl xwl = {
+        .barrier = barrier,
+        .display = NULL,
+        .host_display = NULL,
+        .client = NULL,
+        .compositor = NULL,
+        .shm = NULL,
+        .shell = NULL,
+        .display_event_source = NULL,
+        .connection = NULL,
+        .screen = NULL,
+        .window = 0,
+        .host_focus_window = NULL,
+        .focus_window = 0,
+        .scale = 1,
+        .atoms = {
+            [ATOM_WM_S0] = {"WM_S0"},
+            [ATOM_WM_PROTOCOLS] = {"WM_PROTOCOLS"},
+            [ATOM_WM_DELETE_WINDOW] = {"WM_DELETE_WINDOW"},
+            [ATOM_WL_SURFACE_ID] = {"WL_SURFACE_ID"},
+        }
+    };
+    struct wl_event_loop *event_loop;
+    int sv[2], ds[2], wm[2];
+    pid_t pid;
+    int rv;
+
+    char *scale_str = getenv("_AWT_XWAYLAND_SCALE");
+    if (scale_str != NULL) {
+      xwl.scale = atoi(scale_str);
+      assert(xwl.scale >= 1);
+    }
+
+    xwl.display = wl_display_connect(NULL);
+    assert(!xwl.display);
+
+    wl_list_init(&xwl.outputs);
+    wl_list_init(&xwl.seats);
+    wl_list_init(&xwl.windows);
+    wl_list_init(&xwl.unpaired_windows);
+
+    xwl.host_display = wl_display_create();
+    assert(xwl.host_display);
+
+    event_loop = wl_display_get_event_loop(xwl.host_display);
+
+    wl_event_loop_add_fd(event_loop,
+                         wl_display_get_fd(xwl.display),
+                         WL_EVENT_READABLE,
+                         xwl_handle_event,
+                         &xwl);
+
+    wl_registry_add_listener(wl_display_get_registry(xwl.display),
+                             &xwl_registry_listener,
+                             &xwl);
+
+    wl_display_roundtrip(xwl.display);
+
+    /* Wayland connection from Xwayland */
+    rv = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv);
+    assert(!rv);
+
+    xwl.client = wl_client_create(xwl.host_display, sv[0]);
+
+    /* Xwayland display ready socket */
+    rv = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ds);
+    assert(!rv);
+
+    xwl.display_event_source = wl_event_loop_add_fd(event_loop,
+                                                    ds[0],
+                                                    WL_EVENT_READABLE,
+                                                    xwl_handle_display_event,
+                                                    &xwl);
+
+    /* X connection to Xwayland */
+    rv = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, wm);
+    assert(!rv);
+
+    xwl.wm_fd = wm[0];
+
+    pid = fork();
+    assert(pid != -1);
+    if (pid == 0) {
+        char fd_str[8], display_fd_str[8], wm_fd_str[8];
+        int fd;
+
+        /* SOCK_CLOEXEC closes both ends, so we need to unset
+         * the flag on the client fd. */
+        fd = dup(sv[1]);
+        snprintf(fd_str, sizeof(fd_str), "%d", fd);
+        setenv("WAYLAND_SOCKET", fd_str, 1);
+        fd = dup(ds[1]);
+        snprintf(display_fd_str, sizeof(display_fd_str), "%d", fd);
+        fd = dup(wm[1]);
+        snprintf(wm_fd_str, sizeof(wm_fd_str), "%d", fd);
+
+        execlp("Xwayland", "Xwayland",
+               "-rootless",
+               "-terminate",
+               "-displayfd", display_fd_str,
+               "-wm", wm_fd_str,
+               NULL);
+        perror("Xwayland");
+        _exit(EXIT_FAILURE);
+    }
+
+    close(sv[1]);
+    close(wm[1]);
+
+    do {
+        wl_display_flush_clients(xwl.host_display);
+        if (xwl.connection)
+            xcb_flush(xwl.connection);
+        wl_display_flush(xwl.display);
+    } while (wl_event_loop_dispatch(event_loop, -1) != -1);
+}
diff --git a/src/solaris/native/sun/awt/xwayland.h b/src/solaris/native/sun/awt/xwayland.h
new file mode 100644
index 0000000..97bdf5a
--- /dev/null
+++ b/src/solaris/native/sun/awt/xwayland.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2016 The Chromium Authors. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <pthread.h>
+
+/* Initialize Xwayland session and run main loop efter waiting on barrier */
+void xwayland_run(pthread_barrier_t *barrier);