Merge tag jb8u242-b1644.3

Change-Id: Ia7492bb2a38c1c41216929de6ba6a0a553bd4338
diff --git a/LICENSE b/LICENSE
index 8b400c7..9b041b3 100644
--- a/LICENSE
+++ b/LICENSE
@@ -345,3 +345,175 @@
     you modify this library, you may extend this exception to your version of
     the library, but you are not obligated to do so.  If you do not wish to do
     so, delete this exception statement from your version.
+
+--------------------------------------------------------------------------------
+
+Copied from src/share/classes/sun/util/cldr/resources/21_0_1/LICENSE
+
+UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
+
+Unicode Data Files include all data files under the directories
+http://www.unicode.org/Public/, http://www.unicode.org/reports/, and
+http://www.unicode.org/cldr/data/. Unicode Data Files do not include PDF online
+code charts under the directory http://www.unicode.org/Public/. Software
+includes any source code published in the Unicode Standard or under the
+directories http://www.unicode.org/Public/, http://www.unicode.org/reports/,
+and http://www.unicode.org/cldr/data/.
+
+NOTICE TO USER: Carefully read the following legal agreement. BY DOWNLOADING,
+INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S DATA FILES ("DATA
+FILES"), AND/OR SOFTWARE ("SOFTWARE"), YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO
+BE BOUND BY, ALL OF THE TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT
+AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR
+SOFTWARE.
+
+    COPYRIGHT AND PERMISSION NOTICE
+
+Copyright © 1991-2012 Unicode, Inc. All rights reserved. Distributed under the
+Terms of Use in http://www.unicode.org/copyright.html.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+the Unicode data files and any associated documentation (the "Data Files") or
+Unicode software and any associated documentation (the "Software") to deal in
+the Data Files or Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, and/or sell copies
+of the Data Files or Software, and to permit persons to whom the Data Files or
+Software are furnished to do so, provided that (a) the above copyright notice(s)
+and this permission notice appear with all copies of the Data Files or
+Software, (b) both the above copyright notice(s) and this permission notice
+appear in associated documentation, and (c) there is clear notice in each
+modified Data File or in the Software as well as in the documentation
+associated with the Data File(s) or Software that the data or software has been
+modified.
+
+THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD
+PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
+THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
+DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA FILES OR
+SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder shall not be
+used in advertising or otherwise to promote the sale, use or other dealings in
+these Data Files or Software without prior written authorization of the
+copyright holder.
+
+--------------------------------------------------------------------------------
+
+Copied from src/share/native/sun/awt/libpng/LICENSE
+
+The PNG Reference Library is supplied "AS IS".  The Contributing Authors
+and Group 42, Inc. disclaim all warranties, expressed or implied,
+including, without limitation, the warranties of merchantability and of
+fitness for any purpose.  The Contributing Authors and Group 42, Inc.
+assume no liability for direct, indirect, incidental, special, exemplary,
+or consequential damages, which may result from the use of the PNG
+Reference Library, even if advised of the possibility of such damage.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+source code, or portions hereof, for any purpose, without fee, subject
+to the following restrictions:
+
+  1. The origin of this source code must not be misrepresented.
+
+  2. Altered versions must be plainly marked as such and must not
+     be misrepresented as being the original source.
+
+  3. This Copyright notice may not be removed or altered from any
+     source or altered source distribution.
+
+--------------------------------------------------------------------------------
+
+Copied from src/share/lib/fonts/FiraCode_LICENSE.txt
+Copied from src/share/lib/fonts/Inconsolata_LICENSE.txt
+Copied from src/share/lib/fonts/SourceCodePro_LICENSE.txt
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/MODULE_LICENSE_GPL b/MODULE_LICENSE_GPL
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_GPL
diff --git a/NOTICE b/NOTICE
new file mode 120000
index 0000000..7a694c9
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1 @@
+LICENSE
\ No newline at end of file
diff --git a/build.txt b/build.txt
new file mode 100644
index 0000000..58c76cf
--- /dev/null
+++ b/build.txt
@@ -0,0 +1 @@
+8u242-b1644.3
diff --git a/make/lib/Awt2dLibraries.gmk b/make/lib/Awt2dLibraries.gmk
index 975611a..75fb8e4 100644
--- a/make/lib/Awt2dLibraries.gmk
+++ b/make/lib/Awt2dLibraries.gmk
@@ -625,6 +625,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 82d7b24..b1bcd97 100644
--- a/src/macosx/native/sun/awt/AWTWindow.m
+++ b/src/macosx/native/sun/awt/AWTWindow.m
@@ -323,6 +323,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 43101fb..f5815da 100644
--- a/src/share/classes/java/lang/reflect/Executable.java
+++ b/src/share/classes/java/lang/reflect/Executable.java
@@ -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/java/nio/file/FileTreeWalker.java b/src/share/classes/java/nio/file/FileTreeWalker.java
index b0cf0d3..eae821c 100644
--- a/src/share/classes/java/nio/file/FileTreeWalker.java
+++ b/src/share/classes/java/nio/file/FileTreeWalker.java
@@ -25,6 +25,8 @@
 
 package java.nio.file;
 
+import java.nio.file.attribute.BasicFileAttributeView;
+import java.nio.file.attribute.BasicWithKeyFileAttributeView;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.io.Closeable;
 import java.io.IOException;
@@ -216,7 +218,11 @@
         // links then a link target might not exist so get attributes of link
         BasicFileAttributes attrs;
         try {
-            attrs = Files.readAttributes(file, BasicFileAttributes.class, linkOptions);
+            BasicFileAttributeView view = Files.getFileAttributeView(file, BasicWithKeyFileAttributeView.class, linkOptions);
+            if (view == null) {
+                view = Files.getFileAttributeView(file, BasicFileAttributeView.class, linkOptions);
+            }
+            attrs = view.readAttributes();
         } catch (IOException ioe) {
             if (!followLinks)
                 throw ioe;
diff --git a/src/share/classes/java/nio/file/attribute/BasicWithKeyFileAttributeView.java b/src/share/classes/java/nio/file/attribute/BasicWithKeyFileAttributeView.java
new file mode 100644
index 0000000..917284a
--- /dev/null
+++ b/src/share/classes/java/nio/file/attribute/BasicWithKeyFileAttributeView.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2007, 2011, 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 java.nio.file.attribute;
+
+import java.io.IOException;
+
+/**
+ * Similar to {@link BasicFileAttributeView} with a hint to implementors
+ * to retrieve a valid {@link BasicFileAttributes#fileKey()} if possible, even
+ * at a performance cost.
+ */
+
+public interface BasicWithKeyFileAttributeView
+    extends BasicFileAttributeView {
+}
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/com/sun/java/util/jar/pack/jni.cpp b/src/share/native/com/sun/java/util/jar/pack/jni.cpp
index e9109cb..f8ff76e 100644
--- a/src/share/native/com/sun/java/util/jar/pack/jni.cpp
+++ b/src/share/native/com/sun/java/util/jar/pack/jni.cpp
@@ -292,7 +292,7 @@
 
   if (uPtr->aborting()) {
     THROW_IOE(uPtr->get_abort_message());
-    return false;
+    return null;
   }
 
   // We have fetched all the files.
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);
diff --git a/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java b/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java
index cf4933e..f25bd94 100644
--- a/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java
+++ b/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java
@@ -41,16 +41,16 @@
 class WindowsDirectoryStream
     implements DirectoryStream<Path>
 {
+    private static final int NATIVE_BUFFER_SIZE = 8192;
+
     private final WindowsPath dir;
     private final DirectoryStream.Filter<? super Path> filter;
 
-    // handle to directory
-    private final long handle;
-    // first entry in the directory
-    private final String firstName;
+    // Query directory information data structure
+    private final QueryDirectoryInformation queryDirectoryInformation;
 
-    // buffer for WIN32_FIND_DATA structure that receives information about file
-    private final NativeBuffer findDataBuffer;
+    // Buffer used to receive file entries from NtQueryDirectoryInformation calls
+    private final NativeBuffer queryDirectoryInformationBuffer;
 
     private final Object closeLock = new Object();
 
@@ -65,21 +65,15 @@
         this.dir = dir;
         this.filter = filter;
 
+        this.queryDirectoryInformationBuffer = NativeBuffers.getNativeBuffer(NATIVE_BUFFER_SIZE);
         try {
-            // Need to append * or \* to match entries in directory.
+            // Open the directory for reading and read the first set of entries in the native buffer
             String search = dir.getPathForWin32Calls();
-            char last = search.charAt(search.length() -1);
-            if (last == ':' || last == '\\') {
-                search += "*";
-            } else {
-                search += "\\*";
-            }
-
-            FirstFile first = FindFirstFile(search);
-            this.handle = first.handle();
-            this.firstName = first.name();
-            this.findDataBuffer = WindowsFileAttributes.getBufferForFindData();
+            this.queryDirectoryInformation = OpenNtQueryDirectoryInformation(search, this.queryDirectoryInformationBuffer);
         } catch (WindowsException x) {
+            // Release the buffer, as this instance is not fully constructed
+            this.queryDirectoryInformationBuffer.release();
+
             if (x.lastError() == ERROR_DIRECTORY) {
                 throw new NotDirectoryException(dir.getPathForExceptionMessage());
             }
@@ -99,9 +93,9 @@
                 return;
             isOpen = false;
         }
-        findDataBuffer.release();
+        queryDirectoryInformationBuffer.release();
         try {
-            FindClose(handle);
+            CloseNtQueryDirectoryInformation(queryDirectoryInformation);
         } catch (WindowsException x) {
             x.rethrowAsIOException(dir);
         }
@@ -115,20 +109,20 @@
         synchronized (this) {
             if (iterator != null)
                 throw new IllegalStateException("Iterator already obtained");
-            iterator = new WindowsDirectoryIterator(firstName);
+            iterator = new WindowsDirectoryIterator();
             return iterator;
         }
     }
 
     private class WindowsDirectoryIterator implements Iterator<Path> {
         private boolean atEof;
-        private String first;
         private Path nextEntry;
         private String prefix;
+        private int nextOffset;
 
-        WindowsDirectoryIterator(String first) {
+        WindowsDirectoryIterator() {
             atEof = false;
-            this.first = first;
+            nextOffset = 0;
             if (dir.needsSlashWhenResolving()) {
                 prefix = dir.toString() + "\\";
             } else {
@@ -156,44 +150,35 @@
 
         // reads next directory entry
         private Path readNextEntry() {
-            // handle first element returned by search
-            if (first != null) {
-                nextEntry = isSelfOrParent(first) ? null : acceptEntry(first, null);
-                first = null;
-                if (nextEntry != null)
-                    return nextEntry;
-            }
-
             for (;;) {
-                String name = null;
+                String name;
                 WindowsFileAttributes attrs;
 
                 // synchronize on closeLock to prevent close while reading
                 synchronized (closeLock) {
-                    try {
-                        if (isOpen) {
-                            name = FindNextFile(handle, findDataBuffer.address());
+                    // Fetch next set of entries if we don't have anything available in buffer
+                    if (nextOffset < 0) {
+                        try {
+                            atEof = !NextNtQueryDirectoryInformation(queryDirectoryInformation, queryDirectoryInformationBuffer);
+                        } catch (WindowsException x) {
+                            IOException ioe = x.asIOException(dir);
+                            throw new DirectoryIteratorException(ioe);
                         }
-                    } catch (WindowsException x) {
-                        IOException ioe = x.asIOException(dir);
-                        throw new DirectoryIteratorException(ioe);
+                        if (atEof) {
+                            return null;
+                        }
+                        nextOffset = 0;
                     }
 
-                    // NO_MORE_FILES or stream closed
-                    if (name == null) {
-                        atEof = true;
-                        return null;
-                    }
-
-                    // ignore link to self and parent directories
-                    if (isSelfOrParent(name))
+                    long fullDirInformationAddress = queryDirectoryInformationBuffer.address() + nextOffset;
+                    int nextEntryOffset = WindowsFileAttributes.getNextOffsetFromFileIdFullDirInformation(fullDirInformationAddress);
+                    nextOffset = nextEntryOffset == 0 ? -1 : nextOffset + nextEntryOffset;
+                    name = WindowsFileAttributes.getFileNameFromFileIdFullDirInformation(fullDirInformationAddress);
+                    if (isSelfOrParent(name)) {
+                        // Skip "." and ".."
                         continue;
-
-                    // grab the attributes from the WIN32_FIND_DATA structure
-                    // (needs to be done while holding closeLock because close
-                    // will release the buffer)
-                    attrs = WindowsFileAttributes
-                        .fromFindData(findDataBuffer.address());
+                    }
+                    attrs = WindowsFileAttributes.fromFileIdFullDirInformation(fullDirInformationAddress, queryDirectoryInformation.volSerialNumber());
                 }
 
                 // return entry if accepted by filter
diff --git a/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java b/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java
index 737bbd7..78a81d5 100644
--- a/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java
+++ b/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java
@@ -150,6 +150,23 @@
         }
     }
 
+    private static class BasicWithKey extends Basic {
+        BasicWithKey(WindowsPath file, boolean followLinks) {
+            super(file, followLinks);
+        }
+
+        @Override
+        public WindowsFileAttributes readAttributes() throws IOException {
+            file.checkRead();
+            try {
+                return WindowsFileAttributes.getWithFileKey(file, followLinks);
+            } catch (WindowsException x) {
+                x.rethrowAsIOException(file);
+                return null;    // keep compiler happy
+            }
+        }
+    }
+
     static class Dos extends Basic implements DosFileAttributeView {
         private static final String READONLY_NAME = "readonly";
         private static final String ARCHIVE_NAME = "archive";
@@ -289,6 +306,10 @@
         return new Basic(file, followLinks);
     }
 
+    static Basic createBasicWithKeyView(WindowsPath file, boolean followLinks) {
+        return new BasicWithKey(file, followLinks);
+    }
+
     static Dos createDosView(WindowsPath file, boolean followLinks) {
         return new Dos(file, followLinks);
     }
diff --git a/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java b/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java
index 208435d..03b4882 100644
--- a/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java
+++ b/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java
@@ -109,6 +109,34 @@
     private static final short OFFSETOF_FIND_DATA_SIZELOW = 32;
     private static final short OFFSETOF_FIND_DATA_RESERVED0 = 36;
 
+    /**
+     * typedef struct _FILE_ID_FULL_DIR_INFORMATION {
+     *  ULONG         NextEntryOffset;  // offset = 0
+     *  ULONG         FileIndex;        // offset = 4
+     *  LARGE_INTEGER CreationTime;     // offset = 8
+     *  LARGE_INTEGER LastAccessTime;   // offset = 16
+     *  LARGE_INTEGER LastWriteTime;    // offset = 24
+     *  LARGE_INTEGER ChangeTime;       // offset = 32
+     *  LARGE_INTEGER EndOfFile;        // offset = 40
+     *  LARGE_INTEGER AllocationSize;   // offset = 48
+     *  ULONG         FileAttributes;   // offset = 56
+     *  ULONG         FileNameLength;   // offset = 60
+     *  ULONG         EaSize;           // offset = 64
+     *  LARGE_INTEGER FileId;           // offset = 72
+     *  WCHAR         FileName[1];      // offset = 80
+     * } FILE_ID_FULL_DIR_INFORMATION, *PFILE_ID_FULL_DIR_INFORMATION;
+     */
+    private static final int OFFSETOF_FULL_DIR_INFO_NEXT_ENTRY_OFFSET = 0;
+    private static final int OFFSETOF_FULL_DIR_INFO_CREATION_TIME = 8;
+    private static final int OFFSETOF_FULL_DIR_INFO_LAST_ACCESS_TIME = 16;
+    private static final int OFFSETOF_FULL_DIR_INFO_LAST_WRITE_TIME = 24;
+    private static final int OFFSETOF_FULL_DIR_INFO_END_OF_FILE = 40;
+    private static final int OFFSETOF_FULL_DIR_INFO_FILE_ATTRIBUTES = 56;
+    private static final int OFFSETOF_FULL_DIR_INFO_FILENAME_LENGTH = 60;
+    private static final int OFFSETOF_FULL_DIR_INFO_EA_SIZE = 64;
+    private static final int OFFSETOF_FULL_DIR_INFO_FILE_ID = 72;
+    private static final int OFFSETOF_FULL_DIR_INFO_FILENAME = 80;
+
     // used to adjust values between Windows and java epoch
     private static final long WINDOWS_EPOCH_IN_MICROSECONDS = -11644473600000000L;
 
@@ -134,6 +162,9 @@
     private final int fileIndexHigh;
     private final int fileIndexLow;
 
+    // created lazily
+    private volatile WindowsFileKey key;
+
     /**
      * Convert 64-bit value representing the number of 100-nanosecond intervals
      * since January 1, 1601 to a FileTime.
@@ -260,6 +291,47 @@
     }
 
     /**
+     * Create a WindowsFileAttributes from a FILE_ID_FULL_DIR_INFORMATION structure
+     */
+    static WindowsFileAttributes fromFileIdFullDirInformation(long address, int volSerialNumber) {
+        int fileAttrs = unsafe.getInt(address + OFFSETOF_FULL_DIR_INFO_FILE_ATTRIBUTES);
+        long creationTime = unsafe.getLong(address + OFFSETOF_FULL_DIR_INFO_CREATION_TIME);
+        long lastAccessTime = unsafe.getLong(address + OFFSETOF_FULL_DIR_INFO_LAST_ACCESS_TIME);
+        long lastWriteTime = unsafe.getLong(address + OFFSETOF_FULL_DIR_INFO_LAST_WRITE_TIME);
+        long size = unsafe.getLong(address + OFFSETOF_FULL_DIR_INFO_END_OF_FILE);
+        int reparseTag = isReparsePoint(fileAttrs) ?
+            unsafe.getInt(address + OFFSETOF_FULL_DIR_INFO_EA_SIZE) : 0;
+        int fileIndexLow = unsafe.getInt(address + OFFSETOF_FULL_DIR_INFO_FILE_ID);
+        int fileIndexHigh = unsafe.getInt(address + OFFSETOF_FULL_DIR_INFO_FILE_ID + 4);
+
+        return new WindowsFileAttributes(fileAttrs,
+                                         creationTime,
+                                         lastAccessTime,
+                                         lastWriteTime,
+                                         size,
+                                         reparseTag,
+                                         volSerialNumber,
+                                         fileIndexHigh,  // fileIndexHigh
+                                         fileIndexLow); // fileIndexLow
+    }
+
+    static int getNextOffsetFromFileIdFullDirInformation(long address) {
+        return unsafe.getInt(address + OFFSETOF_FULL_DIR_INFO_NEXT_ENTRY_OFFSET);
+    }
+
+    static String getFileNameFromFileIdFullDirInformation(long address) {
+        // copy the name
+        int nameLengthInBytes = unsafe.getInt(address + OFFSETOF_FULL_DIR_INFO_FILENAME_LENGTH);
+        if ((nameLengthInBytes % 2) != 0) {
+            throw new AssertionError("FileNameLength is not a multiple of 2");
+        }
+        char[] nameAsArray = new char[nameLengthInBytes/2];
+        unsafe.copyMemory(null, address + OFFSETOF_FULL_DIR_INFO_FILENAME, nameAsArray,
+            Unsafe.ARRAY_CHAR_BASE_OFFSET, nameLengthInBytes);
+        return new String(nameAsArray);
+    }
+
+    /**
      * Reads the attributes of an open file
      */
     static WindowsFileAttributes readAttributes(long handle)
@@ -349,6 +421,15 @@
         }
 
         // file is reparse point so need to open file to get attributes
+        return getWithFileKey(path, followLinks);
+    }
+
+    /**
+     * Returns attributes of given file.
+     */
+    static WindowsFileAttributes getWithFileKey(WindowsPath path, boolean followLinks)
+        throws WindowsException
+    {
         long handle = path.openForReadAttributeAccess(followLinks);
         try {
             return readAttributes(handle);
@@ -416,7 +497,17 @@
 
     @Override
     public Object fileKey() {
-        return null;
+        if (volSerialNumber == 0) {
+            return null;
+        }
+        if (key == null) {
+            synchronized (this) {
+                if (key == null) {
+                    key = new WindowsFileKey(volSerialNumber, ((long)fileIndexHigh << 32) + fileIndexLow);
+                }
+            }
+        }
+        return key;
     }
 
     // package private
diff --git a/src/windows/classes/sun/nio/fs/WindowsFileKey.java b/src/windows/classes/sun/nio/fs/WindowsFileKey.java
new file mode 100644
index 0000000..b61b4d2
--- /dev/null
+++ b/src/windows/classes/sun/nio/fs/WindowsFileKey.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2008, 2009, 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.nio.fs;
+
+/**
+ * Container for volume/file id to uniquely identify file.
+ */
+
+class WindowsFileKey {
+    private final int volSerialNumber;
+    private final long fileId;
+
+    WindowsFileKey(int volSerialNumber, long fileId) {
+        this.volSerialNumber = volSerialNumber;
+        this.fileId = fileId;
+    }
+
+    @Override
+    public int hashCode() {
+        return (int)(volSerialNumber ^ (volSerialNumber >>> 16)) +
+               (int)(fileId ^ (fileId >>> 32));
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this)
+            return true;
+        if (!(obj instanceof WindowsFileKey))
+            return false;
+        WindowsFileKey other = (WindowsFileKey)obj;
+        return (this.volSerialNumber == other.volSerialNumber) && (this.fileId == other.fileId);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("(volId=")
+          .append(Integer.toHexString(volSerialNumber))
+          .append(",fileId=")
+          .append(Long.toHexString(fileId))
+          .append(')');
+        return sb.toString();
+    }
+}
diff --git a/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java b/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java
index bd5f890..b33249a 100644
--- a/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java
+++ b/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java
@@ -162,6 +162,8 @@
         boolean followLinks = Util.followLinks(options);
         if (view == BasicFileAttributeView.class)
             return (V) WindowsFileAttributeViews.createBasicView(file, followLinks);
+        if (view == BasicWithKeyFileAttributeView.class)
+            return (V) WindowsFileAttributeViews.createBasicWithKeyView(file, followLinks);
         if (view == DosFileAttributeView.class)
             return (V) WindowsFileAttributeViews.createDosView(file, followLinks);
         if (view == AclFileAttributeView.class)
@@ -199,6 +201,8 @@
         boolean followLinks = Util.followLinks(options);
         if (name.equals("basic"))
             return WindowsFileAttributeViews.createBasicView(file, followLinks);
+        if (name.equals("basicwithkey"))
+            return WindowsFileAttributeViews.createBasicWithKeyView(file, followLinks);
         if (name.equals("dos"))
             return WindowsFileAttributeViews.createDosView(file, followLinks);
         if (name.equals("acl"))
diff --git a/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java b/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java
index 47d28f8..27036d1 100644
--- a/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java
+++ b/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java
@@ -275,6 +275,38 @@
      */
     static native void FindClose(long handle) throws WindowsException;
 
+    static QueryDirectoryInformation OpenNtQueryDirectoryInformation(String path, NativeBuffer buffer) throws WindowsException {
+        NativeBuffer pathBuffer = asNativeBuffer(path);
+        try {
+            QueryDirectoryInformation data = new QueryDirectoryInformation();
+            OpenNtQueryDirectoryInformation0(pathBuffer.address(), buffer.address(), buffer.size(), data);
+            return data;
+        } finally {
+            pathBuffer.release();
+        }
+    }
+    static class QueryDirectoryInformation {
+        private long handle;
+        private int volSerialNumber;
+
+        private QueryDirectoryInformation() { }
+        public long handle()         { return handle; }
+        public int volSerialNumber() { return volSerialNumber; }
+    }
+    private static native void OpenNtQueryDirectoryInformation0(long lpFileName, long buffer, int bufferSize, QueryDirectoryInformation obj)
+        throws WindowsException;
+
+    static boolean NextNtQueryDirectoryInformation(QueryDirectoryInformation data, NativeBuffer buffer) throws WindowsException {
+        return NextNtQueryDirectoryInformation0(data.handle(), buffer.address(), buffer.size());
+    }
+
+    private static native boolean NextNtQueryDirectoryInformation0(long handle, long buffer, int bufferSize)
+        throws WindowsException;
+
+    static void CloseNtQueryDirectoryInformation(QueryDirectoryInformation data) throws WindowsException {
+        CloseHandle(data.handle);
+    }
+
     /**
      * GetFileInformationByHandle(
      *   HANDLE hFile,
diff --git a/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c b/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c
index 0a18e0b..e20ebb7 100644
--- a/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c
+++ b/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c
@@ -42,6 +42,8 @@
 #include "jni_util.h"
 #include "jlong.h"
 
+#include "ntifs_min.h"
+
 #include "sun_nio_fs_WindowsNativeDispatcher.h"
 
 /**
@@ -54,6 +56,9 @@
 static jfieldID findStream_handle;
 static jfieldID findStream_name;
 
+static jfieldID queryDirectoryInformation_handle;
+static jfieldID queryDirectoryInformation_volSerialNumber;
+
 static jfieldID volumeInfo_fsName;
 static jfieldID volumeInfo_volName;
 static jfieldID volumeInfo_volSN;
@@ -76,7 +81,6 @@
 static jfieldID backupResult_bytesTransferred;
 static jfieldID backupResult_context;
 
-
 /**
  * Win32 APIs not available in Windows XP
  */
@@ -86,12 +90,19 @@
 typedef BOOLEAN (WINAPI* CreateSymbolicLinkProc) (LPCWSTR, LPCWSTR, DWORD);
 typedef BOOL (WINAPI* GetFinalPathNameByHandleProc) (HANDLE, LPWSTR, DWORD, DWORD);
 
+typedef NTSYSCALLAPI NTSTATUS (NTAPI *NtQueryDirectoryFile_Proc) (HANDLE, HANDLE, PIO_APC_ROUTINE,
+    PVOID, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS, BOOLEAN, PUNICODE_STRING, BOOLEAN);
+typedef ULONG (NTAPI *RtlNtStatusToDosError_Proc) (NTSTATUS);
+
 static FindFirstStream_Proc FindFirstStream_func;
 static FindNextStream_Proc FindNextStream_func;
 
 static CreateSymbolicLinkProc CreateSymbolicLink_func;
 static GetFinalPathNameByHandleProc GetFinalPathNameByHandle_func;
 
+static NtQueryDirectoryFile_Proc NtQueryDirectoryFile_func;
+static RtlNtStatusToDosError_Proc RtlNtStatusToDosError_func;
+
 static void throwWindowsException(JNIEnv* env, DWORD lastError) {
     jobject x = JNU_NewObjectByName(env, "sun/nio/fs/WindowsException",
         "(I)V", lastError);
@@ -126,6 +137,13 @@
     findStream_name = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;");
     CHECK_NULL(findStream_name);
 
+    clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$QueryDirectoryInformation");
+    CHECK_NULL(clazz);
+    queryDirectoryInformation_handle = (*env)->GetFieldID(env, clazz, "handle", "J");
+    CHECK_NULL(queryDirectoryInformation_handle);
+    queryDirectoryInformation_volSerialNumber = (*env)->GetFieldID(env, clazz, "volSerialNumber", "I");;
+    CHECK_NULL(queryDirectoryInformation_volSerialNumber);
+
     clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$VolumeInformation");
     CHECK_NULL(clazz);
     volumeInfo_fsName = (*env)->GetFieldID(env, clazz, "fileSystemName", "Ljava/lang/String;");
@@ -193,6 +211,17 @@
         GetFinalPathNameByHandle_func =
             (GetFinalPathNameByHandleProc)GetProcAddress(h, "GetFinalPathNameByHandleW");
     }
+
+    // get handle to ntdll
+    if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+                           L"ntdll.dll", &h) != 0)
+    {
+        NtQueryDirectoryFile_func =
+            (NtQueryDirectoryFile_Proc)GetProcAddress(h, "NtQueryDirectoryFile");
+        RtlNtStatusToDosError_func =
+            (RtlNtStatusToDosError_Proc)GetProcAddress(h, "RtlNtStatusToDosError");
+    }
+
 }
 
 JNIEXPORT jlong JNICALL
@@ -460,6 +489,118 @@
 
 
 JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_OpenNtQueryDirectoryInformation0(JNIEnv* env, jclass this,
+    jlong address, jlong bufferAddress, jint bufferSize, jobject obj)
+{
+    LPCWSTR lpFileName = jlong_to_ptr(address);
+    BOOL ok;
+    BY_HANDLE_FILE_INFORMATION info;
+    HANDLE handle;
+    NTSTATUS status;
+    ULONG win32ErrorCode;
+    IO_STATUS_BLOCK ioStatusBlock;
+
+    if ((NtQueryDirectoryFile_func == NULL) || (RtlNtStatusToDosError_func == NULL)) {
+        JNU_ThrowInternalError(env, "Should not get here");
+        return;
+    }
+
+    handle = CreateFileW(lpFileName, FILE_LIST_DIRECTORY,
+            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+            NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+    if (handle == INVALID_HANDLE_VALUE) {
+        throwWindowsException(env, GetLastError());
+        return;
+    }
+
+    status = NtQueryDirectoryFile_func(
+        handle, // FileHandle
+        NULL, // Event
+        NULL, // ApcRoutine
+        NULL, // ApcContext
+        &ioStatusBlock, // IoStatusBlock
+        jlong_to_ptr(bufferAddress), // FileInformation
+        bufferSize, // Length
+        FileIdFullDirectoryInformation, // FileInformationClass
+        FALSE, // ReturnSingleEntry
+        NULL, // FileName
+        FALSE); // RestartScan
+
+    if (!NT_SUCCESS(status)) {
+        /*
+        * NtQueryDirectoryFile returns STATUS_INVALID_PARAMETER when
+        * asked to enumerate an invalid directory (ie it is a file
+        * instead of a directory).  Verify that is the actual cause
+        * of the error.
+        */
+        if (status == STATUS_INVALID_PARAMETER) {
+            DWORD attributes = GetFileAttributesW(lpFileName);
+            if ((attributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
+                status = STATUS_NOT_A_DIRECTORY;
+            }
+        }
+
+        win32ErrorCode = RtlNtStatusToDosError_func(status);
+        throwWindowsException(env, win32ErrorCode);
+        CloseHandle(handle);
+        return;
+    }
+
+    // This call allows retrieving the volume ID of this directory (and all its entries)
+    ok = GetFileInformationByHandle(handle, &info);
+    if (!ok) {
+        throwWindowsException(env, GetLastError());
+        CloseHandle(handle);
+        return;
+    }
+
+    (*env)->SetLongField(env, obj, queryDirectoryInformation_handle, ptr_to_jlong(handle));
+    (*env)->SetIntField(env, obj, queryDirectoryInformation_volSerialNumber, info.dwVolumeSerialNumber);
+}
+
+JNIEXPORT jboolean JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_NextNtQueryDirectoryInformation0(JNIEnv* env, jclass this,
+    jlong handle, jlong address, jint size)
+{
+    HANDLE h = (HANDLE)jlong_to_ptr(handle);
+    ULONG win32ErrorCode;
+    IO_STATUS_BLOCK ioStatusBlock;
+    NTSTATUS status;
+
+    if ((NtQueryDirectoryFile_func == NULL) || (RtlNtStatusToDosError_func == NULL)) {
+        JNU_ThrowInternalError(env, "Should not get here");
+        return JNI_FALSE;
+    }
+
+    status = NtQueryDirectoryFile_func(
+        h, // FileHandle
+        NULL, // Event
+        NULL, // ApcRoutine
+        NULL, // ApcContext
+        &ioStatusBlock, // IoStatusBlock
+        jlong_to_ptr(address), // FileInformation
+        size, // Length
+        FileIdFullDirectoryInformation, // FileInformationClass
+        FALSE, // ReturnSingleEntry
+        NULL, // FileName
+        FALSE); // RestartScan
+
+    if (NT_SUCCESS(status)) {
+        return JNI_TRUE;
+    }
+
+    // Normal completion: no more files in directory
+    if (status == STATUS_NO_MORE_FILES) {
+        return JNI_FALSE;
+    }
+
+    win32ErrorCode = RtlNtStatusToDosError_func(status);
+    throwWindowsException(env, win32ErrorCode);
+    return JNI_FALSE;
+}
+
+
+JNIEXPORT void JNICALL
 Java_sun_nio_fs_WindowsNativeDispatcher_GetFileInformationByHandle(JNIEnv* env, jclass this,
     jlong handle, jlong address)
 {
diff --git a/src/windows/native/sun/nio/fs/ntifs_min.h b/src/windows/native/sun/nio/fs/ntifs_min.h
new file mode 100644
index 0000000..0a895f3
--- /dev/null
+++ b/src/windows/native/sun/nio/fs/ntifs_min.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2008, 2018, 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.
+ */
+
+#ifndef _NTIFS_MIN_
+#define _NTIFS_MIN_
+
+/*
+ * Copy necessary structures and definitions out of the Windows DDK
+ * to enable calling NtQueryDirectoryFile()
+ */
+
+typedef LONG NTSTATUS;
+#define NT_SUCCESS(Status)  (((NTSTATUS)(Status)) >= 0)
+
+typedef struct _UNICODE_STRING {
+    USHORT Length;
+    USHORT MaximumLength;
+    PWCH   Buffer;
+} UNICODE_STRING;
+typedef UNICODE_STRING *PUNICODE_STRING;
+typedef const UNICODE_STRING *PCUNICODE_STRING;
+
+typedef enum _FILE_INFORMATION_CLASS {
+    FileDirectoryInformation = 1,
+    FileFullDirectoryInformation,
+    FileBothDirectoryInformation,
+    FileBasicInformation,
+    FileStandardInformation,
+    FileInternalInformation,
+    FileEaInformation,
+    FileAccessInformation,
+    FileNameInformation,
+    FileRenameInformation,
+    FileLinkInformation,
+    FileNamesInformation,
+    FileDispositionInformation,
+    FilePositionInformation,
+    FileFullEaInformation,
+    FileModeInformation,
+    FileAlignmentInformation,
+    FileAllInformation,
+    FileAllocationInformation,
+    FileEndOfFileInformation,
+    FileAlternateNameInformation,
+    FileStreamInformation,
+    FilePipeInformation,
+    FilePipeLocalInformation,
+    FilePipeRemoteInformation,
+    FileMailslotQueryInformation,
+    FileMailslotSetInformation,
+    FileCompressionInformation,
+    FileObjectIdInformation,
+    FileCompletionInformation,
+    FileMoveClusterInformation,
+    FileQuotaInformation,
+    FileReparsePointInformation,
+    FileNetworkOpenInformation,
+    FileAttributeTagInformation,
+    FileTrackingInformation,
+    FileIdBothDirectoryInformation,
+    FileIdFullDirectoryInformation,
+    FileValidDataLengthInformation,
+    FileShortNameInformation,
+    FileIoCompletionNotificationInformation,
+    FileIoStatusBlockRangeInformation,
+    FileIoPriorityHintInformation,
+    FileSfioReserveInformation,
+    FileSfioVolumeInformation,
+    FileHardLinkInformation,
+    FileProcessIdsUsingFileInformation,
+    FileNormalizedNameInformation,
+    FileNetworkPhysicalNameInformation,
+    FileIdGlobalTxDirectoryInformation,
+    FileIsRemoteDeviceInformation,
+    FileAttributeCacheInformation,
+    FileNumaNodeInformation,
+    FileStandardLinkInformation,
+    FileRemoteProtocolInformation,
+    FileMaximumInformation
+} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
+
+typedef struct _FILE_ID_FULL_DIR_INFORMATION {
+    ULONG         NextEntryOffset;
+    ULONG         FileIndex;
+    LARGE_INTEGER CreationTime;
+    LARGE_INTEGER LastAccessTime;
+    LARGE_INTEGER LastWriteTime;
+    LARGE_INTEGER ChangeTime;
+    LARGE_INTEGER EndOfFile;
+    LARGE_INTEGER AllocationSize;
+    ULONG         FileAttributes;
+    ULONG         FileNameLength;
+    ULONG         EaSize;
+    LARGE_INTEGER FileId;
+    WCHAR         FileName[1];
+} FILE_ID_FULL_DIR_INFORMATION, *PFILE_ID_FULL_DIR_INFORMATION;
+
+typedef struct _IO_STATUS_BLOCK {
+    union {
+        NTSTATUS Status;
+        PVOID Pointer;
+    } u;
+    ULONG_PTR Information;
+} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
+
+typedef VOID
+(NTAPI *PIO_APC_ROUTINE)(
+    IN PVOID ApcContext,
+    IN PIO_STATUS_BLOCK IoStatusBlock,
+    IN ULONG Reserved);
+
+NTSYSCALLAPI
+NTSTATUS
+NTAPI
+NtQueryDirectoryFile(
+    _In_ HANDLE FileHandle,
+    _In_opt_ HANDLE Event,
+    _In_opt_ PIO_APC_ROUTINE ApcRoutine,
+    _In_opt_ PVOID ApcContext,
+    _Out_ PIO_STATUS_BLOCK IoStatusBlock,
+    _Out_ PVOID FileInformation,
+    _In_ ULONG Length,
+    _In_ FILE_INFORMATION_CLASS FileInformationClass,
+    _In_ BOOLEAN ReturnSingleEntry,
+    _In_opt_ PUNICODE_STRING FileName,
+    _In_ BOOLEAN RestartScan
+);
+
+ULONG
+NTAPI
+RtlNtStatusToDosError(
+    NTSTATUS Status
+);
+
+#define STATUS_NO_MORE_FILES             ((NTSTATUS)0x80000006L)
+#define STATUS_NOT_A_DIRECTORY           ((NTSTATUS)0xC0000103L)
+
+#endif  // _NTIFS_MIN_