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