mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-06 17:39:40 +01:00
Compare commits
21 Commits
openjdk
...
pure_wl_to
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b462fd783 | ||
|
|
453aaeadd3 | ||
|
|
0bc3e25676 | ||
|
|
3d2576cc49 | ||
|
|
e706d20764 | ||
|
|
36d8ecfae9 | ||
|
|
2e925c692b | ||
|
|
a9993e87ae | ||
|
|
7eeac2c3c2 | ||
|
|
8d71f8e9e7 | ||
|
|
dd34f02b33 | ||
|
|
862304dbb8 | ||
|
|
405158823d | ||
|
|
f9eaffb0ce | ||
|
|
66bbb5bf1d | ||
|
|
fed863d607 | ||
|
|
f5a01cfafb | ||
|
|
825ce1ff18 | ||
|
|
16ea04bd4f | ||
|
|
67259058bd | ||
|
|
f698505867 |
53
README.md
53
README.md
@@ -1,5 +1,58 @@
|
||||
# Welcome to the JDK!
|
||||
|
||||
## Wakefield
|
||||
This is a temporary section created to host information on the
|
||||
[Wakefield](https://wiki.openjdk.java.net/display/wakefield) project.
|
||||
|
||||
### Building
|
||||
There are two addition `configure` arguments:
|
||||
```
|
||||
--with-wayland specify prefix directory for the wayland package
|
||||
(expecting the headers under PATH/include)
|
||||
--with-wayland-include specify directory for the wayland include files
|
||||
```
|
||||
As usual, there should be no need to specify those explicitly unless you're doing
|
||||
something tricky.
|
||||
However, a variant of `libwayland-dev` needs to be installed on the build system.
|
||||
|
||||
### Running
|
||||
Make sure your system is configured such that `libwayland` can find the socket to connect to;
|
||||
usually this means that the environment variable `WAYLAND_DISPLAY` is set to something
|
||||
sensible. Then add this argument to `java`
|
||||
```
|
||||
-Dawt.toolkit.name=WLToolkit
|
||||
```
|
||||
|
||||
### Testing
|
||||
Testing that involves `Robot` is done inside a [Weston](https://gitlab.freedesktop.org/wayland/weston/)
|
||||
instance with a special module loaded called `libwakefield`
|
||||
that provides the necessary functionality. The Wayland-specific tests are therefore executed with a dedicated test driver
|
||||
`test/jdk/java/awt/wakefield/WakefieldTestDriver.java`. The driver also provides an easy
|
||||
way to run the test in several configurations with a different size and even number
|
||||
of "outputs" (monitors).
|
||||
|
||||
To run the Wayland-specific tests, perform these steps:
|
||||
* Install Weston version 9 (earlier versions are known NOT to work).
|
||||
* Obtain `libwakefield.so` either by building from source (available under
|
||||
`src/java.desktop/share/native/libwakefield` and not integrated into the rest of the
|
||||
build infrastructure; see `README.md` there)
|
||||
or by fetching the latest pre-built `x64` binary
|
||||
```
|
||||
wget https://github.com/mkartashev/wakefield/raw/main/libwakefield.so
|
||||
```
|
||||
* Set `LIBWAKEFIELD` environment variable to the full path to `libwakefield.so`
|
||||
```
|
||||
export LIBWAKEFIELD=/tmp/wakefield-testing/libwakefield.so
|
||||
```
|
||||
* Run `jtreg` like so
|
||||
```
|
||||
jtreg -e:XDG_RUNTIME_DIR -e:LIBWAKEFIELD -testjdk:... test/jdk/java/awt/wakefield/
|
||||
```
|
||||
|
||||
This was verified to work in `Ubuntu 21.10`.
|
||||
This does NOT work in `Ubuntu 21.04` or `Fedora 34`.
|
||||
|
||||
## Generic Info (not Wakefield-specific)
|
||||
For build instructions please see the
|
||||
[online documentation](https://openjdk.java.net/groups/build/doc/building.html),
|
||||
or either of these files:
|
||||
|
||||
91
make/autoconf/lib-wayland.m4
Normal file
91
make/autoconf/lib-wayland.m4
Normal file
@@ -0,0 +1,91 @@
|
||||
#
|
||||
# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2021, JetBrains s.r.o.. 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.
|
||||
#
|
||||
|
||||
################################################################################
|
||||
# Setup wayland
|
||||
################################################################################
|
||||
AC_DEFUN_ONCE([LIB_SETUP_WAYLAND],
|
||||
[
|
||||
AC_ARG_WITH(wayland, [AS_HELP_STRING([--with-wayland],
|
||||
[specify prefix directory for the wayland package
|
||||
(expecting the headers under PATH/include)])])
|
||||
AC_ARG_WITH(wayland-include, [AS_HELP_STRING([--with-wayland-include],
|
||||
[specify directory for the wayland include files])])
|
||||
|
||||
if test "x$NEEDS_LIB_WAYLAND" = xfalse; then
|
||||
if (test "x${with_wayland}" != x && test "x${with_wayland}" != xno) || \
|
||||
(test "x${with_wayland_include}" != x && test "x${with_wayland_include}" != xno); then
|
||||
AC_MSG_WARN([[wayland not used, so --with-wayland[-*] is ignored]])
|
||||
fi
|
||||
WAYLAND_CFLAGS=
|
||||
WAYLAND_LIBS=
|
||||
else
|
||||
WAYLAND_FOUND=no
|
||||
|
||||
if test "x${with_wayland}" = xno || test "x${with_wayland_include}" = xno; then
|
||||
AC_MSG_ERROR([It is not possible to disable the use of wayland. Remove the --without-wayland option.])
|
||||
fi
|
||||
|
||||
if test "x${with_wayland}" != x; then
|
||||
AC_MSG_CHECKING([for wayland headers])
|
||||
if test -s "${with_wayland}/include/wayland-client.h"; then
|
||||
WAYLAND_CFLAGS="-I${with_wayland}/include"
|
||||
WAYLAND_LIBS="-L${with_wayland}/lib -lwayland-client"
|
||||
|
||||
WAYLAND_FOUND=yes
|
||||
AC_MSG_RESULT([$WAYLAND_FOUND])
|
||||
else
|
||||
AC_MSG_ERROR([Can't find 'include/wayland-client.h' under ${with_wayland} given with the --with-wayland option.])
|
||||
fi
|
||||
fi
|
||||
if test "x${with_wayland_include}" != x; then
|
||||
AC_MSG_CHECKING([for wayland headers])
|
||||
if test -s "${with_wayland_include}/wayland-client.h"; then
|
||||
WAYLAND_CFLAGS="-I${with_wayland_include}"
|
||||
WAYLAND_FOUND=yes
|
||||
AC_MSG_RESULT([$WAYLAND_FOUND])
|
||||
else
|
||||
AC_MSG_ERROR([Can't find 'wayland-client.h' under ${with_wayland_include} given with the --with-wayland-include option.])
|
||||
fi
|
||||
fi
|
||||
if test "x$WAYLAND_FOUND" = xno; then
|
||||
# Are the wayland headers installed in the default /usr/include location?
|
||||
AC_CHECK_HEADERS([wayland-client.h], [
|
||||
WAYLAND_FOUND=yes
|
||||
WAYLAND_CFLAGS=
|
||||
WAYLAND_LIBS="-lwayland-client"
|
||||
DEFAULT_WAYLAND=yes
|
||||
])
|
||||
fi
|
||||
if test "x$WAYLAND_FOUND" = xno; then
|
||||
HELP_MSG_MISSING_DEPENDENCY([wayland])
|
||||
AC_MSG_ERROR([Could not find wayland! $HELP_MSG ])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(WAYLAND_CFLAGS)
|
||||
AC_SUBST(WAYLAND_LIBS)
|
||||
])
|
||||
@@ -35,20 +35,27 @@ m4_include([lib-std.m4])
|
||||
m4_include([lib-x11.m4])
|
||||
|
||||
m4_include([lib-tests.m4])
|
||||
m4_include([lib-wayland.m4])
|
||||
|
||||
################################################################################
|
||||
# Determine which libraries are needed for this configuration
|
||||
################################################################################
|
||||
AC_DEFUN_ONCE([LIB_DETERMINE_DEPENDENCIES],
|
||||
[
|
||||
# Check if X11 is needed
|
||||
# Check if X11 and wayland is needed
|
||||
if test "x$OPENJDK_TARGET_OS" = xwindows || test "x$OPENJDK_TARGET_OS" = xmacosx; then
|
||||
# No X11 support on windows or macosx
|
||||
# No X11 and wayland support on windows or macosx
|
||||
NEEDS_LIB_X11=false
|
||||
NEEDS_LIB_WAYLAND=false
|
||||
elif test "x$ENABLE_HEADLESS_ONLY" = xtrue; then
|
||||
# No X11 support needed when building headless only
|
||||
NEEDS_LIB_X11=false
|
||||
NEEDS_LIB_WAYLAND=false
|
||||
else
|
||||
# All other instances need X11, even if building headless only, libawt still
|
||||
# All other instances need X11 and wayland, even if building headless only, libawt still
|
||||
# needs X11 headers.
|
||||
NEEDS_LIB_X11=true
|
||||
NEEDS_LIB_WAYLAND=true
|
||||
fi
|
||||
|
||||
# Check if fontconfig is needed
|
||||
@@ -104,6 +111,7 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES],
|
||||
LIB_SETUP_HSDIS
|
||||
LIB_SETUP_LIBFFI
|
||||
LIB_SETUP_MISC_LIBS
|
||||
LIB_SETUP_WAYLAND
|
||||
LIB_SETUP_X11
|
||||
|
||||
LIB_TESTS_SETUP_GTEST
|
||||
|
||||
@@ -453,7 +453,8 @@ endif
|
||||
# Necessary additional compiler flags to compile X11
|
||||
X_CFLAGS:=@X_CFLAGS@
|
||||
X_LIBS:=@X_LIBS@
|
||||
|
||||
WAYLAND_CFLAGS:=@WAYLAND_CFLAGS@
|
||||
WAYLAND_LIBS:=@WAYLAND_LIBS@
|
||||
# The lowest required version of macosx
|
||||
MACOSX_VERSION_MIN=@MACOSX_VERSION_MIN@
|
||||
# The highest allowed version of macosx
|
||||
|
||||
@@ -191,7 +191,7 @@ ifeq ($(call isTargetOs, windows macosx), false)
|
||||
common/font \
|
||||
#
|
||||
|
||||
LIBAWT_XAWT_EXCLUDES := medialib debug
|
||||
LIBAWT_XAWT_EXCLUDES := medialib debug wl
|
||||
|
||||
LIBAWT_XAWT_EXTRA_HEADER_DIRS := \
|
||||
$(LIBAWT_DEFAULT_HEADER_DIRS) \
|
||||
@@ -263,6 +263,83 @@ endif
|
||||
|
||||
################################################################################
|
||||
|
||||
ifeq ($(call isTargetOs, windows macosx), false)
|
||||
ifeq ($(ENABLE_HEADLESS_ONLY), false)
|
||||
|
||||
LIBAWT_WLAWT_EXTRA_SRC := \
|
||||
common/awt \
|
||||
common/java2d \
|
||||
common/font \
|
||||
#
|
||||
|
||||
LIBAWT_WLAWT_EXCLUDES := medialib debug opengl x11
|
||||
LIBAWT_WLAWT_EXCLUDE_FILES := common/awt/X11Color.c common/awt/awt_Font.c
|
||||
|
||||
LIBAWT_WLAWT_EXTRA_HEADER_DIRS := \
|
||||
$(LIBAWT_DEFAULT_HEADER_DIRS) \
|
||||
libawt_wlawt/awt \
|
||||
include \
|
||||
common/awt/debug \
|
||||
common/awt/systemscale \
|
||||
common/font \
|
||||
common/java2d/wl \
|
||||
#
|
||||
|
||||
# Enable 'wakefield' extension for java.awt.Robot support
|
||||
WAKEFIELD_ROBOT_CFLAGS=-DWAKEFIELD_ROBOT
|
||||
|
||||
LIBAWT_WLAWT_CFLAGS += -DWLAWT \
|
||||
$(WAKEFIELD_ROBOT_CFLAGS) \
|
||||
$(FONTCONFIG_CFLAGS) \
|
||||
$(CUPS_CFLAGS)
|
||||
|
||||
LIBAWT_WLAWT_LIBS := $(LIBM) -lawt $(WAYLAND_LIBS) $(LIBDL) -ljava -ljvm -lrt
|
||||
|
||||
ifeq ($(call isTargetOs, linux), true)
|
||||
LIBAWT_WLAWT_LIBS += -lpthread
|
||||
endif
|
||||
|
||||
ifeq ($(TOOLCHAIN_TYPE), gcc)
|
||||
# Turn off all warnings for the following files since they contain warnings
|
||||
# that cannot be turned of individually.
|
||||
# redefining a macro
|
||||
BUILD_LIBAWT_WLAWT_awt_Font.c_CFLAGS := -w
|
||||
# initializing a declared 'extern'
|
||||
BUILD_LIBAWT_WLAWT_debug_mem.c_CFLAGS := -w
|
||||
endif
|
||||
|
||||
$(eval $(call SetupJdkLibrary, BUILD_LIBAWT_WLAWT, \
|
||||
NAME := awt_wlawt, \
|
||||
EXCLUDE_FILES := $(LIBAWT_WLAWT_EXCLUDE_FILES), \
|
||||
EXTRA_SRC := $(LIBAWT_WLAWT_EXTRA_SRC), \
|
||||
EXTRA_HEADER_DIRS := $(LIBAWT_WLAWT_EXTRA_HEADER_DIRS), \
|
||||
EXCLUDES := $(LIBAWT_WLAWT_EXCLUDES), \
|
||||
OPTIMIZATION := LOW, \
|
||||
CFLAGS := $(CFLAGS_JDKLIB) $(LIBAWT_WLAWT_CFLAGS), \
|
||||
WARNINGS_AS_ERRORS_xlc := false, \
|
||||
DISABLED_WARNINGS_gcc := type-limits pointer-to-int-cast \
|
||||
unused-result maybe-uninitialized format \
|
||||
format-security int-to-pointer-cast parentheses \
|
||||
implicit-fallthrough undef unused-function, \
|
||||
DISABLED_WARNINGS_clang := parentheses format undef \
|
||||
logical-op-parentheses format-nonliteral int-conversion, \
|
||||
LDFLAGS := $(LDFLAGS_JDKLIB) \
|
||||
$(call SET_SHARED_LIBRARY_ORIGIN) \
|
||||
-L$(INSTALL_LIBRARIES_HERE), \
|
||||
LIBS := $(LIBAWT_WLAWT_LIBS), \
|
||||
))
|
||||
|
||||
$(BUILD_LIBAWT_WLAWT): $(call FindLib, java.base, java)
|
||||
|
||||
$(BUILD_LIBAWT_WLAWT): $(BUILD_LIBAWT)
|
||||
|
||||
TARGETS += $(BUILD_LIBAWT_WLAWT)
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
|
||||
# The fast floor code loses precision.
|
||||
LCMS_CFLAGS=-DCMS_DONT_USE_FAST_FLOOR
|
||||
|
||||
@@ -493,13 +570,9 @@ ifneq ($(filter $(TOOLCHAIN_TYPE), gcc clang), )
|
||||
endif
|
||||
|
||||
ifeq ($(call isTargetOs, windows), true)
|
||||
LIBFONTMANAGER_EXCLUDE_FILES += X11FontScaler.c \
|
||||
X11TextRenderer.c
|
||||
LIBFONTMANAGER_OPTIMIZATION := HIGHEST
|
||||
else ifeq ($(call isTargetOs, macosx), true)
|
||||
LIBFONTMANAGER_EXCLUDE_FILES += X11FontScaler.c \
|
||||
X11TextRenderer.c \
|
||||
fontpath.c \
|
||||
LIBFONTMANAGER_EXCLUDE_FILES += fontpath.c \
|
||||
lcdglyph.c
|
||||
else
|
||||
LIBFONTMANAGER_EXCLUDE_FILES += fontpath.c \
|
||||
@@ -524,7 +597,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBFONTMANAGER, \
|
||||
EXTRA_HEADER_DIRS := $(LIBFONTMANAGER_EXTRA_HEADER_DIRS), \
|
||||
EXTRA_SRC := $(LIBFONTMANAGER_EXTRA_SRC), \
|
||||
WARNINGS_AS_ERRORS_xlc := false, \
|
||||
DISABLED_WARNINGS_gcc := $(HARFBUZZ_DISABLED_WARNINGS_gcc), \
|
||||
DISABLED_WARNINGS_gcc := $(HARFBUZZ_DISABLED_WARNINGS_gcc) unused-result, \
|
||||
DISABLED_WARNINGS_CXX_gcc := $(HARFBUZZ_DISABLED_WARNINGS_CXX_gcc), \
|
||||
DISABLED_WARNINGS_clang := $(HARFBUZZ_DISABLED_WARNINGS_clang), \
|
||||
DISABLED_WARNINGS_microsoft := $(HARFBUZZ_DISABLED_WARNINGS_microsoft), \
|
||||
@@ -554,6 +627,51 @@ TARGETS += $(BUILD_LIBFONTMANAGER)
|
||||
|
||||
################################################################################
|
||||
|
||||
ifeq ($(call isTargetOs, windows macosx), false)
|
||||
ifeq ($(ENABLE_HEADLESS_ONLY), false)
|
||||
|
||||
LIBFONTMANAGER_XAWT_EXCLUDE_FILES := $(LIBFONTMANAGER_EXCLUDE_FILES)
|
||||
LIBFONTMANAGER_XAWT_CFLAGS := $(LIBFONTMANAGER_CFLAGS)
|
||||
LIBFONTMANAGER_XAWT_OPTIMIZATION := $(LIBFONTMANAGER_OPTIMIZATION)
|
||||
LIBFONTMANAGER_XAWT_EXTRA_HEADER_DIRS := $(LIBFONTMANAGER_EXTRA_HEADER_DIRS) \
|
||||
libfontmanager
|
||||
LIBFONTMANAGER_XAWT_EXTRA_SRC :=
|
||||
|
||||
$(eval $(call SetupJdkLibrary, BUILD_LIBFONTMANAGER_XAWT, \
|
||||
NAME := fontmanager_xawt, \
|
||||
EXCLUDE_FILES := $(LIBFONTMANAGER_XAWT_EXCLUDE_FILES) \
|
||||
AccelGlyphCache.c, \
|
||||
TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
|
||||
CFLAGS := $(CFLAGS_JDKLIB) $(LIBFONTMANAGER_XAWT_CFLAGS), \
|
||||
CXXFLAGS := $(CXXFLAGS_JDKLIB) $(LIBFONTMANAGER_XAWT_CFLAGS), \
|
||||
OPTIMIZATION := $(LIBFONTMANAGER_XAWT_OPTIMIZATION), \
|
||||
CFLAGS_windows = -DCC_NOEX, \
|
||||
EXTRA_HEADER_DIRS := $(LIBFONTMANAGER_XAWT_EXTRA_HEADER_DIRS), \
|
||||
EXTRA_SRC := $(LIBFONTMANAGER_XAWT_EXTRA_SRC), \
|
||||
WARNINGS_AS_ERRORS_xlc := false, \
|
||||
DISABLED_WARNINGS_gcc := $(HARFBUZZ_DISABLED_WARNINGS_gcc), \
|
||||
DISABLED_WARNINGS_CXX_gcc := $(HARFBUZZ_DISABLED_WARNINGS_CXX_gcc), \
|
||||
DISABLED_WARNINGS_clang := $(HARFBUZZ_DISABLED_WARNINGS_clang), \
|
||||
DISABLED_WARNINGS_microsoft := $(HARFBUZZ_DISABLED_WARNINGS_microsoft), \
|
||||
LDFLAGS := $(subst -Xlinker -z -Xlinker defs,, \
|
||||
$(subst -Wl$(COMMA)-z$(COMMA)defs,,$(LDFLAGS_JDKLIB))) $(LDFLAGS_CXX_JDK) \
|
||||
$(call SET_SHARED_LIBRARY_ORIGIN), \
|
||||
LDFLAGS_unix := -L$(INSTALL_LIBRARIES_HERE), \
|
||||
LDFLAGS_aix := -Wl$(COMMA)-berok, \
|
||||
LIBS := $(BUILD_LIBFONTMANAGER_FONTLIB), \
|
||||
LIBS_unix := -lfontmanager -lawt -ljava -ljvm $(LIBM) $(LIBCXX), \
|
||||
))
|
||||
|
||||
$(BUILD_LIBFONTMANAGER_XAWT): $(BUILD_LIBFONTMANAGER)
|
||||
$(BUILD_LIBFONTMANAGER_XAWT): $(BUILD_LIBAWT_XAWT)
|
||||
|
||||
TARGETS += $(BUILD_LIBFONTMANAGER_XAWT)
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
|
||||
ifeq ($(call isTargetOs, windows), true)
|
||||
|
||||
LIBJAWT_CFLAGS := -EHsc -DUNICODE -D_UNICODE
|
||||
|
||||
@@ -86,6 +86,7 @@ typedef struct FontManagerNativeIDs {
|
||||
but we need access method to use it from separate rasterizer lib */
|
||||
extern FontManagerNativeIDs sunFontIDs;
|
||||
JNIEXPORT FontManagerNativeIDs getSunFontIDs(JNIEnv* env);
|
||||
JNIEXPORT const FontManagerNativeIDs* getSunFontIDsPtr(JNIEnv* env);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -50,8 +50,8 @@
|
||||
#define FLOOR_ASSIGN(l, r)\
|
||||
if ((r)<0) (l) = ((int)floor(r)); else (l) = ((int)(r))
|
||||
|
||||
GlyphBlitVector* setupBlitVector(JNIEnv *env, jobject glyphlist,
|
||||
jint fromGlyph, jint toGlyph) {
|
||||
JNIEXPORT GlyphBlitVector* setupBlitVector(JNIEnv *env, jobject glyphlist,
|
||||
jint fromGlyph, jint toGlyph) {
|
||||
|
||||
int g;
|
||||
size_t bytesNeeded;
|
||||
@@ -140,7 +140,7 @@ GlyphBlitVector* setupBlitVector(JNIEnv *env, jobject glyphlist,
|
||||
return gbv;
|
||||
}
|
||||
|
||||
jint RefineBounds(GlyphBlitVector *gbv, SurfaceDataBounds *bounds) {
|
||||
JNIEXPORT jint RefineBounds(GlyphBlitVector *gbv, SurfaceDataBounds *bounds) {
|
||||
int index;
|
||||
jint dx1, dy1, dx2, dy2;
|
||||
ImageRef glyphImage;
|
||||
@@ -487,8 +487,8 @@ Java_sun_java2d_loops_DrawGlyphListLCD_DrawGlyphListLCD
|
||||
* rendered fractional metrics, there's typically more space between the
|
||||
* glyphs. Perhaps disabling X-axis grid-fitting will help with that.
|
||||
*/
|
||||
GlyphBlitVector* setupLCDBlitVector(JNIEnv *env, jobject glyphlist,
|
||||
jint fromGlyph, jint toGlyph) {
|
||||
JNIEXPORT GlyphBlitVector* setupLCDBlitVector(JNIEnv *env, jobject glyphlist,
|
||||
jint fromGlyph, jint toGlyph) {
|
||||
|
||||
int g;
|
||||
size_t bytesNeeded;
|
||||
|
||||
@@ -39,11 +39,11 @@ typedef struct {
|
||||
ImageRef *glyphs;
|
||||
} GlyphBlitVector;
|
||||
|
||||
extern jint RefineBounds(GlyphBlitVector *gbv, SurfaceDataBounds *bounds);
|
||||
extern GlyphBlitVector* setupBlitVector(JNIEnv *env, jobject glyphlist,
|
||||
jint fromGlyph, jint toGlyph);
|
||||
extern GlyphBlitVector* setupLCDBlitVector(JNIEnv *env, jobject glyphlist,
|
||||
JNIEXPORT jint RefineBounds(GlyphBlitVector *gbv, SurfaceDataBounds *bounds);
|
||||
JNIEXPORT GlyphBlitVector* setupBlitVector(JNIEnv *env, jobject glyphlist,
|
||||
jint fromGlyph, jint toGlyph);
|
||||
JNIEXPORT GlyphBlitVector* setupLCDBlitVector(JNIEnv *env, jobject glyphlist,
|
||||
jint fromGlyph, jint toGlyph);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -207,6 +207,12 @@ JNIEXPORT FontManagerNativeIDs getSunFontIDs(JNIEnv *env) {
|
||||
return sunFontIDs;
|
||||
}
|
||||
|
||||
JNIEXPORT const FontManagerNativeIDs* getSunFontIDsPtr(JNIEnv* env) {
|
||||
|
||||
initFontIDs(env);
|
||||
return &sunFontIDs;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_font_StrikeCache
|
||||
* Method: freeIntPointer
|
||||
|
||||
97
src/java.desktop/share/native/libwakefield/CMakeLists.txt
Normal file
97
src/java.desktop/share/native/libwakefield/CMakeLists.txt
Normal file
@@ -0,0 +1,97 @@
|
||||
#
|
||||
# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2022, JetBrains s.r.o.. 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.
|
||||
#
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(wakefield C)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
|
||||
set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
find_program(WAYLAND_SCANNER wayland-scanner)
|
||||
if (NOT WAYLAND_SCANNER)
|
||||
message(FATAL_ERROR "wayland-scanner not found")
|
||||
endif ()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT wakefield-server-protocol.h
|
||||
COMMAND ${WAYLAND_SCANNER} server-header ${CMAKE_CURRENT_SOURCE_DIR}/protocol/wakefield.xml wakefield-server-protocol.h
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/protocol/wakefield.xml
|
||||
VERBATIM)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT wakefield-server-protocol.c
|
||||
COMMAND ${WAYLAND_SCANNER} private-code ${CMAKE_CURRENT_SOURCE_DIR}/protocol/wakefield.xml wakefield-server-protocol.c
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/protocol/wakefield.xml
|
||||
VERBATIM)
|
||||
|
||||
find_path(
|
||||
WESTON_INCLUDES
|
||||
weston/weston.h
|
||||
/usr/include /usr/local/include)
|
||||
|
||||
if (NOT WESTON_INCLUDES)
|
||||
message(FATAL_ERROR "weston/weston.h not found")
|
||||
endif ()
|
||||
|
||||
find_path(
|
||||
LIBWESTON_INCLUDES
|
||||
libweston/libweston.h
|
||||
/usr/include /usr/local/include
|
||||
PATH_SUFFIXES libweston-9)
|
||||
|
||||
if (NOT LIBWESTON_INCLUDES)
|
||||
message(FATAL_ERROR "libweston/libweston.h not found")
|
||||
endif ()
|
||||
|
||||
find_path(
|
||||
PIXMAN_INCLUDES
|
||||
pixman.h
|
||||
/usr/include /usr/local/include
|
||||
PATH_SUFFIXES pixman-1)
|
||||
|
||||
if (NOT PIXMAN_INCLUDES)
|
||||
message(FATAL_ERROR "pixman.h not found")
|
||||
endif ()
|
||||
|
||||
add_library(wakefield SHARED src/wakefield.c wakefield-server-protocol.c wakefield-server-protocol.h)
|
||||
target_include_directories(wakefield PUBLIC
|
||||
${WESTON_INCLUDES} ${LIBWESTON_INCLUDES} ${PIXMAN_INCLUDES}
|
||||
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
install(TARGETS wakefield DESTINATION .)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT wakefield-client-protocol.h
|
||||
COMMAND ${WAYLAND_SCANNER} client-header ${CMAKE_CURRENT_SOURCE_DIR}/protocol/wakefield.xml wakefield-client-protocol.h
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/protocol/wakefield.xml
|
||||
VERBATIM)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT wakefield-client-protocol.c
|
||||
COMMAND ${WAYLAND_SCANNER} code ${CMAKE_CURRENT_SOURCE_DIR}/protocol/wakefield.xml wakefield-client-protocol.c
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/protocol/wakefield.xml
|
||||
VERBATIM)
|
||||
|
||||
add_custom_target(client ALL DEPENDS wakefield-client-protocol.h wakefield-client-protocol.c)
|
||||
43
src/java.desktop/share/native/libwakefield/README.md
Normal file
43
src/java.desktop/share/native/libwakefield/README.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Wakefield Protocol
|
||||
This is a [Weston](https://github.com/wayland-project/weston) protocol extension
|
||||
created to satisfy the requirements of the
|
||||
[Wakefield](https://openjdk.java.net/projects/wakefield/) project *testing*.
|
||||
|
||||
## Rationale
|
||||
Many of `java.awt.Robot` capabilities contradict the basic principles of
|
||||
[Wayland](https://openjdk.java.net/projects/wakefield/). The examples include
|
||||
obtaining the color of a pixel at specified coordinates by automated tests.
|
||||
This extension aims to help in implementation of those capabilities for the use
|
||||
in test environment *only*.
|
||||
|
||||
## Prerequisites
|
||||
On Ubuntu 21.04 (in addition to the usual C development environment):
|
||||
```bash
|
||||
$ sudo apt install cmake libwayland-dev wayland-protocols \
|
||||
libweston-9-0 libweston-9-dev weston libpixman-1-dev libpixman-1-0
|
||||
```
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
$ mkdir build && cd build
|
||||
$ cmake .../src/java.desktop/share/native/libwakefield/
|
||||
$ make
|
||||
```
|
||||
This should build `libwakefield.so` in the current (build) directory.
|
||||
|
||||
## Smoke test
|
||||
|
||||
```bash
|
||||
$ PWD=`pwd` && \
|
||||
weston --socket=wayland-test --width=800 --height=600 --use-pixman --socket=wayland-42 \
|
||||
--modules="$PWD/libwakefield.so"
|
||||
```
|
||||
This will create a new Weston compositor instance with the Wayland socket
|
||||
named `wayland-42`.
|
||||
Now you can verify that a new global has been published by running this command:
|
||||
```bash
|
||||
$ WAYLAND_DISPLAY=wayland-42 weston-info | grep wakefield
|
||||
interface: 'wakefield', version: 1, name: 21
|
||||
```
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<protocol name="wakefield">
|
||||
<copyright>
|
||||
Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
Copyright (c) 2022, JetBrains s.r.o.. 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.
|
||||
</copyright>
|
||||
|
||||
<interface name="wakefield" version="1">
|
||||
<description summary="provides capabilities necessary to for java.awt.Robot and such"></description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
</request>
|
||||
|
||||
<request name="move_surface">
|
||||
<description summary="facilitates implementation of Frame.setLocation()">
|
||||
This instructs the window manager to position the given wl_surface
|
||||
at the given absolute coordinates. The subsequent get_surface_location
|
||||
request will return these coordinates unless the surface was moved by
|
||||
a third party.
|
||||
</description>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
<arg name="x" type="int"/>
|
||||
<arg name="y" type="int"/>
|
||||
</request>
|
||||
|
||||
<request name="get_surface_location">
|
||||
<description summary="facilitates implementation of Frame.getLocation()">
|
||||
This requests a surface_location event for the given surface.
|
||||
</description>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
</request>
|
||||
|
||||
<event name="surface_location">
|
||||
<description summary="facilitates implementation of Frame.getLocation()">
|
||||
This event reveals the absolute coordinates of the surface if error_code is zero.
|
||||
If error_code is non-zero, (x, y) are undefined.
|
||||
The surface argument always correspond to that of the get_surface_location request.
|
||||
</description>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
<arg name="x" type="int"/>
|
||||
<arg name="y" type="int"/>
|
||||
<arg name="error_code" type="uint" enum="error"/>
|
||||
</event>
|
||||
|
||||
<request name="get_pixel_color">
|
||||
<description summary="facilitates implementation of Robot.getPixelColor()">
|
||||
This requests a pixel_color event at the given absolute coordinates.
|
||||
</description>
|
||||
<arg name="x" type="int"/>
|
||||
<arg name="y" type="int"/>
|
||||
</request>
|
||||
|
||||
<event name="pixel_color">
|
||||
<description summary="facilitates implementation of Robot.getPixelColor()">
|
||||
This event shows the color (24-bit, format r8g8b8) of the pixel with the given
|
||||
absolute coordinates.
|
||||
The (x, y) arguments correspond to that of the get_pixel_color request.
|
||||
If error_code is non-zero, the rgb argument is undefined and the error_code argument
|
||||
contains a code from the error enum.
|
||||
</description>
|
||||
<arg name="x" type="int"/>
|
||||
<arg name="y" type="int"/>
|
||||
<arg name="rgb" type="uint"/>
|
||||
<arg name="error_code" type="uint" enum="error"/>
|
||||
</event>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="no_error" value="0" summary="error code 0 reserved for the absence of error"/>
|
||||
<entry name="invalid_coordinates" value="1" summary="supplied absolute coordinates point
|
||||
outside of any output"/>
|
||||
<entry name="out_of_memory" value="2" summary="the request could not be fulfilled due to memory allocation error"/>
|
||||
<entry name="internal" value="3" summary="a generic error code for internal errors"/>
|
||||
<entry name="format" value="4" summary="(temporary?) color cannot be converted to RGB format"/>
|
||||
</enum>
|
||||
|
||||
<request name="capture_create">
|
||||
<arg name="buffer" type="object" interface="wl_buffer" summary="shall be an instance by the wl_shm factory"/>
|
||||
<arg name="x" type="int"/>
|
||||
<arg name="y" type="int"/>
|
||||
<!--
|
||||
<arg name="capture_pointer" type="int" summary="0 to exclude the mouse pointer surface from the capture"/>
|
||||
-->
|
||||
</request>
|
||||
|
||||
<event name="capture_ready">
|
||||
<arg name="buffer" type="object" interface="wl_buffer"/>
|
||||
<arg name="error_code" type="uint" enum="error"/>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
</protocol>
|
||||
546
src/java.desktop/share/native/libwakefield/src/wakefield.c
Normal file
546
src/java.desktop/share/native/libwakefield/src/wakefield.c
Normal file
@@ -0,0 +1,546 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, JetBrains s.r.o.. 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.
|
||||
*/
|
||||
|
||||
#include <weston/weston.h>
|
||||
#include <libweston/weston-log.h>
|
||||
|
||||
#include <pixman.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "wakefield-server-protocol.h"
|
||||
|
||||
#ifndef container_of
|
||||
#define container_of(ptr, type, member) ({ \
|
||||
const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \
|
||||
(type *)( (char *)__mptr - offsetof(type,member) );})
|
||||
#endif
|
||||
|
||||
struct wakefield {
|
||||
struct weston_compositor *compositor;
|
||||
struct wl_listener destroy_listener;
|
||||
|
||||
struct weston_log_scope *log;
|
||||
};
|
||||
|
||||
static struct weston_output*
|
||||
get_output_for_point(struct wakefield* wakefield, int32_t x, int32_t y)
|
||||
{
|
||||
struct weston_output *o;
|
||||
wl_list_for_each(o, &wakefield->compositor->output_list, link) {
|
||||
if (o->destroying)
|
||||
continue;
|
||||
|
||||
if (pixman_region32_contains_point(&o->region, x, y, NULL)) {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
wakefield_get_pixel_color(struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
int32_t x,
|
||||
int32_t y)
|
||||
{
|
||||
struct wakefield *wakefield = wl_resource_get_user_data(resource);
|
||||
struct weston_compositor *compositor = wakefield->compositor;
|
||||
|
||||
weston_log_scope_printf(wakefield->log, "WAKEFIELD: get_pixel_color at (%d, %d)\n", x, y);
|
||||
|
||||
const unsigned int byte_per_pixel = (PIXMAN_FORMAT_BPP(compositor->read_format) / 8);
|
||||
uint32_t pixel = 0;
|
||||
if (byte_per_pixel > sizeof(pixel)) {
|
||||
weston_log_scope_printf(wakefield->log,
|
||||
"WAKEFIELD: compositor pixel format (%d) exceeds allocated storage (%d > %ld)\n",
|
||||
compositor->read_format,
|
||||
byte_per_pixel,
|
||||
sizeof(pixel));
|
||||
wakefield_send_pixel_color(resource, x, y, 0, WAKEFIELD_ERROR_FORMAT);
|
||||
return;
|
||||
}
|
||||
|
||||
struct weston_output *output = get_output_for_point(wakefield, x, y);
|
||||
if (output == NULL) {
|
||||
weston_log_scope_printf(wakefield->log,
|
||||
"WAKEFIELD: pixel location (%d, %d) doesn't map to any output\n", x, y);
|
||||
wakefield_send_pixel_color(resource, x, y, 0, WAKEFIELD_ERROR_INVALID_COORDINATES);
|
||||
return;
|
||||
}
|
||||
|
||||
const int output_x = x - output->x;
|
||||
const int output_y = y - output->y;
|
||||
weston_log_scope_printf(wakefield->log,
|
||||
"WAKEFIELD: reading pixel color at (%d, %d) of '%s'\n",
|
||||
output_x, output_y, output->name);
|
||||
compositor->renderer->read_pixels(output,
|
||||
compositor->read_format, &pixel,
|
||||
output_x, output_y, 1, 1);
|
||||
|
||||
uint32_t rgb = 0;
|
||||
switch (compositor->read_format) {
|
||||
case PIXMAN_a8r8g8b8:
|
||||
case PIXMAN_x8r8g8b8:
|
||||
case PIXMAN_r8g8b8:
|
||||
rgb = pixel & 0x00ffffffu;
|
||||
break;
|
||||
|
||||
default:
|
||||
weston_log_scope_printf(wakefield->log,
|
||||
"WAKEFIELD: compositor pixel format %d (see pixman.h) not supported\n",
|
||||
compositor->read_format);
|
||||
wakefield_send_pixel_color(resource, x, y, 0, WAKEFIELD_ERROR_FORMAT);
|
||||
return;
|
||||
}
|
||||
weston_log_scope_printf(wakefield->log, "WAKEFIELD: color is 0x%08x\n", rgb);
|
||||
|
||||
wakefield_send_pixel_color(resource, x, y, rgb, WAKEFIELD_ERROR_NO_ERROR);
|
||||
}
|
||||
|
||||
static void
|
||||
wakefield_get_surface_location(struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *surface_resource)
|
||||
{
|
||||
// See also weston-test.c`move_surface() and the corresponding protocol
|
||||
|
||||
struct wakefield *wakefield = wl_resource_get_user_data(resource);
|
||||
struct weston_surface *surface = wl_resource_get_user_data(surface_resource);
|
||||
struct weston_view *view = container_of(surface->views.next, struct weston_view, surface_link);
|
||||
|
||||
if (!view) {
|
||||
weston_log_scope_printf(wakefield->log, "WAKEFIELD: get_location error\n");
|
||||
wakefield_send_surface_location(resource, surface_resource, 0, 0,
|
||||
WAKEFIELD_ERROR_INTERNAL);
|
||||
return;
|
||||
}
|
||||
|
||||
float fx;
|
||||
float fy;
|
||||
weston_view_to_global_float(view, 0, 0, &fx, &fy);
|
||||
const int32_t x = (int32_t)fx;
|
||||
const int32_t y = (int32_t)fy;
|
||||
weston_log_scope_printf(wakefield->log, "WAKEFIELD: get_location: %d, %d\n", x, y);
|
||||
|
||||
wakefield_send_surface_location(resource, surface_resource, x, y,
|
||||
WAKEFIELD_ERROR_NO_ERROR);
|
||||
}
|
||||
|
||||
static void
|
||||
wakefield_move_surface(struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *surface_resource,
|
||||
int32_t x,
|
||||
int32_t y)
|
||||
{
|
||||
struct wakefield *wakefield = wl_resource_get_user_data(resource);
|
||||
struct weston_surface *surface = wl_resource_get_user_data(surface_resource);
|
||||
struct weston_view *view = container_of(surface->views.next, struct weston_view, surface_link);
|
||||
|
||||
if (!view) {
|
||||
weston_log_scope_printf(wakefield->log, "WAKEFIELD: move_surface error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
weston_view_set_position(view, (float)x, (float)y);
|
||||
weston_view_update_transform(view);
|
||||
|
||||
weston_log_scope_printf(wakefield->log, "WAKEFIELD: move_surface to (%d, %d)\n", x, y);
|
||||
}
|
||||
|
||||
static pixman_format_code_t
|
||||
wl_shm_format_to_pixman(uint32_t wl_shm_format)
|
||||
{
|
||||
pixman_format_code_t rc;
|
||||
|
||||
switch (wl_shm_format) {
|
||||
case WL_SHM_FORMAT_ARGB8888:
|
||||
rc = PIXMAN_a8r8g8b8;
|
||||
break;
|
||||
case WL_SHM_FORMAT_XRGB8888:
|
||||
rc = PIXMAN_x8r8g8b8;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of pixels in the given non-empty region.
|
||||
*/
|
||||
static uint64_t
|
||||
size_in_pixels(pixman_region32_t *region)
|
||||
{
|
||||
const pixman_box32_t * const e = pixman_region32_extents(region);
|
||||
assert (e->x2 >= e->x1);
|
||||
assert (e->y2 >= e->y1);
|
||||
|
||||
return ((uint64_t)(e->x2 - e->x1))*(e->y2 - e->y1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of pixels of the largest portion that the given region occupies on
|
||||
* any of the compositor's outputs.
|
||||
*
|
||||
* @param fits_entirely (OUT) set to true iff the entire region fits as a whole on just one output
|
||||
* @return largest area size in pixels (could be zero).
|
||||
*/
|
||||
static uint64_t
|
||||
get_largest_area_in_one_output(struct weston_compositor *compositor, pixman_region32_t *region, bool *fits_entirely)
|
||||
{
|
||||
uint64_t area = 0; // in pixels
|
||||
*fits_entirely = false;
|
||||
|
||||
pixman_region32_t region_in_output;
|
||||
pixman_region32_init(®ion_in_output);
|
||||
|
||||
struct weston_output *output;
|
||||
wl_list_for_each(output, &compositor->output_list, link) {
|
||||
if (output->destroying)
|
||||
continue;
|
||||
|
||||
pixman_region32_intersect(®ion_in_output, region, &output->region);
|
||||
if (pixman_region32_not_empty(®ion_in_output)) {
|
||||
const uint64_t this_area = size_in_pixels(®ion_in_output);
|
||||
if (this_area > area) {
|
||||
area = this_area;
|
||||
}
|
||||
if (pixman_region32_equal(®ion_in_output, region)) {
|
||||
*fits_entirely = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pixman_region32_fini(®ion_in_output);
|
||||
|
||||
return area;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets every pixel in the given buffer to 0.
|
||||
*/
|
||||
static void
|
||||
clear_buffer(struct wl_shm_buffer *buffer)
|
||||
{
|
||||
const int32_t height = wl_shm_buffer_get_height(buffer);
|
||||
const size_t stride = wl_shm_buffer_get_stride(buffer);
|
||||
const size_t buffer_byte_size = height*stride;
|
||||
|
||||
wl_shm_buffer_begin_access(buffer);
|
||||
{
|
||||
uint32_t *data = wl_shm_buffer_get_data(buffer);
|
||||
memset(data, 0, buffer_byte_size);
|
||||
}
|
||||
wl_shm_buffer_end_access(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies 4-byte pixels from the given array to the given buffer
|
||||
* at the given offset into the buffer.
|
||||
*
|
||||
* @param buffer target buffer (format is assumed to be 4 byte per pixel)
|
||||
* @param data array of 4-byte pixels of size (width*height)
|
||||
* @param target_x horizontal coordinate of the top-left corner in the buffer
|
||||
* where the given data should be placed
|
||||
* @param target_y vertical coordinate of the top-left corner in the buffer
|
||||
* where the given data should be placed
|
||||
* @param width the source image width in pixels
|
||||
* @param height the source image height in pixels
|
||||
*/
|
||||
static void
|
||||
copy_pixels_to_shm_buffer(struct wl_shm_buffer *buffer, uint32_t *data,
|
||||
int32_t target_x, int32_t target_y,
|
||||
int32_t width, int32_t height)
|
||||
{
|
||||
assert (target_x >= 0 && target_y >= 0);
|
||||
assert (data);
|
||||
|
||||
const int32_t buffer_width = wl_shm_buffer_get_width(buffer);
|
||||
|
||||
wl_shm_buffer_begin_access(buffer);
|
||||
{
|
||||
uint32_t * const buffer_data = wl_shm_buffer_get_data(buffer);
|
||||
assert (buffer_data);
|
||||
|
||||
for (int32_t y = 0; y < height; y++) {
|
||||
const uint32_t * const src_line = &data[y*width];
|
||||
uint32_t * const dst_line = &buffer_data[(target_y + y)*buffer_width];
|
||||
for (int32_t x = 0; x < width; x++) {
|
||||
dst_line[target_x + x] = src_line[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
wl_shm_buffer_end_access(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the given buffer format is supported and sends the "capture ready" event
|
||||
* with the appropriate error code if it wasn't.
|
||||
*/
|
||||
static bool
|
||||
check_buffer_format_supported(struct wakefield *wakefield, struct wl_resource *resource,
|
||||
struct wl_resource *buffer_resource, uint32_t buffer_format)
|
||||
{
|
||||
if (buffer_format != WL_SHM_FORMAT_ARGB8888
|
||||
&& buffer_format != WL_SHM_FORMAT_XRGB8888) {
|
||||
weston_log_scope_printf(wakefield->log,
|
||||
"WAKEFIELD: buffer for image capture has unsupported format %d, "
|
||||
"check codes in enum 'format' in wayland.xml\n",
|
||||
buffer_format);
|
||||
wakefield_send_capture_ready(resource, buffer_resource, WAKEFIELD_ERROR_FORMAT);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the given buffer type is shm and sends the "capture ready" event
|
||||
* with the appropriate error code if it wasn't.
|
||||
*/
|
||||
static bool
|
||||
check_buffer_type_supported(struct wakefield *wakefield, struct wl_resource *resource,
|
||||
struct wl_resource *buffer_resource)
|
||||
{
|
||||
struct wl_shm_buffer *buffer = wl_shm_buffer_get(buffer_resource);
|
||||
|
||||
if (!buffer) {
|
||||
weston_log_scope_printf(wakefield->log, "WAKEFIELD: buffer for image capture not from wl_shm\n");
|
||||
wakefield_send_capture_ready(resource, buffer_resource, WAKEFIELD_ERROR_INTERNAL);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the given capture area is not empty and sends the successful "capture ready" event
|
||||
* if it was.
|
||||
*/
|
||||
static bool
|
||||
capture_is_empty(struct wakefield *wakefield, struct wl_resource *resource,
|
||||
struct wl_resource *buffer_resource, uint64_t largest_capture_area)
|
||||
{
|
||||
if (largest_capture_area == 0) {
|
||||
// All outputs might've just disappeared
|
||||
weston_log_scope_printf(wakefield->log,
|
||||
"WAKEFIELD: captured area size on all outputs is zero.\n");
|
||||
wakefield_send_capture_ready(resource, buffer_resource, WAKEFIELD_ERROR_NO_ERROR);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
wakefield_capture_create(struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *buffer_resource,
|
||||
int32_t x,
|
||||
int32_t y)
|
||||
{
|
||||
struct wakefield *wakefield = wl_resource_get_user_data(resource);
|
||||
|
||||
if (!check_buffer_type_supported(wakefield, resource, buffer_resource)) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wl_shm_buffer *buffer = wl_shm_buffer_get(buffer_resource);
|
||||
assert (buffer); // actually, verified earlier
|
||||
const uint32_t buffer_format = wl_shm_buffer_get_format(buffer);
|
||||
if (!check_buffer_format_supported(wakefield, resource, buffer_resource, buffer_format)) {
|
||||
return;
|
||||
}
|
||||
|
||||
clear_buffer(buffer); // in case some outputs disappear mid-flight or a part of the capture is out of screen
|
||||
|
||||
const int32_t width = wl_shm_buffer_get_width(buffer);
|
||||
const int32_t height = wl_shm_buffer_get_height(buffer);
|
||||
|
||||
pixman_region32_t region_global; // capture region in global coordinates
|
||||
pixman_region32_t region_in_output; // capture region in a particular output in that output's coordinates
|
||||
|
||||
pixman_region32_init_rect(®ion_global, x, y, width, height);
|
||||
pixman_region32_init(®ion_in_output);
|
||||
|
||||
bool fits_entirely;
|
||||
const uint64_t largest_capture_area = get_largest_area_in_one_output(wakefield->compositor, ®ion_global, &fits_entirely);
|
||||
if (capture_is_empty(wakefield, resource, buffer_resource, largest_capture_area)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t bpp = 4; // byte-per-pixel
|
||||
void *per_output_buffer = NULL;
|
||||
if (!fits_entirely) {
|
||||
// Can't read screen pixels directly into the resulting buffer, have to use an intermediate storage.
|
||||
per_output_buffer = malloc(largest_capture_area * bpp);
|
||||
if (per_output_buffer == NULL) {
|
||||
weston_log_scope_printf(wakefield->log,
|
||||
"WAKEFIELD: failed to allocate %ld bytes for temporary capture buffer.\n",
|
||||
largest_capture_area);
|
||||
wakefield_send_capture_ready(resource, buffer_resource, WAKEFIELD_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const pixman_format_code_t buffer_format_pixman = wl_shm_format_to_pixman(buffer_format);
|
||||
struct weston_output *output;
|
||||
wl_list_for_each(output, &wakefield->compositor->output_list, link) {
|
||||
if (output->destroying)
|
||||
continue;
|
||||
|
||||
pixman_region32_intersect(®ion_in_output, ®ion_global, &output->region);
|
||||
if (pixman_region32_not_empty(®ion_in_output)) {
|
||||
const pixman_box32_t * const e = pixman_region32_extents(®ion_in_output);
|
||||
|
||||
const int32_t region_x_in_global = e->x1;
|
||||
const int32_t region_y_in_global = e->y1;
|
||||
const int32_t width_in_output = e->x2 - e->x1;
|
||||
const int32_t height_in_output = e->y2 - e->y1;
|
||||
weston_log_scope_printf(wakefield->log, "WAKEFIELD: output '%s' has a chunk of the image at (%d, %d) sized (%d, %d)\n",
|
||||
output->name,
|
||||
e->x1, e->y1,
|
||||
width_in_output, height_in_output);
|
||||
|
||||
// Better, but not available in the current libweston:
|
||||
// weston_output_region_from_global(output, ®ion_in_output);
|
||||
|
||||
// Now convert region_in_output from global to output-local coordinates.
|
||||
pixman_region32_translate(®ion_in_output, -output->x, -output->y);
|
||||
|
||||
const pixman_box32_t * const e_in_output = pixman_region32_extents(®ion_in_output);
|
||||
const int32_t x_in_output = e_in_output->x1;
|
||||
const int32_t y_in_output = e_in_output->y1;
|
||||
|
||||
weston_log_scope_printf(wakefield->log,
|
||||
"WAKEFIELD: grabbing pixels at (%d, %d) of size %dx%d, format %s\n",
|
||||
x_in_output, y_in_output,
|
||||
width_in_output, height_in_output,
|
||||
buffer_format_pixman == PIXMAN_a8r8g8b8 ? "ARGB8888" : "XRGB8888");
|
||||
|
||||
if (per_output_buffer) {
|
||||
wakefield->compositor->renderer->read_pixels(output,
|
||||
buffer_format_pixman, // TODO: may not work with all renderers, check screenshooter_frame_notify() in libweston
|
||||
per_output_buffer,
|
||||
x_in_output, y_in_output,
|
||||
width_in_output, height_in_output);
|
||||
|
||||
copy_pixels_to_shm_buffer(buffer, per_output_buffer,
|
||||
region_x_in_global - x, region_y_in_global - y,
|
||||
width_in_output, height_in_output);
|
||||
} else {
|
||||
wl_shm_buffer_begin_access(buffer);
|
||||
{
|
||||
void *data = wl_shm_buffer_get_data(buffer);
|
||||
wakefield->compositor->renderer->read_pixels(output,
|
||||
buffer_format_pixman,
|
||||
data,
|
||||
x_in_output, y_in_output,
|
||||
width, height);
|
||||
}
|
||||
wl_shm_buffer_end_access(buffer);
|
||||
// This is the case of the entire region located on just one output,
|
||||
// and we have just processed it, so can exit immediately.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pixman_region32_fini(®ion_in_output);
|
||||
pixman_region32_fini(®ion_global);
|
||||
}
|
||||
|
||||
if (per_output_buffer) {
|
||||
free(per_output_buffer);
|
||||
}
|
||||
|
||||
wakefield_send_capture_ready(resource, buffer_resource, WAKEFIELD_ERROR_NO_ERROR);
|
||||
}
|
||||
|
||||
static const struct wakefield_interface wakefield_implementation = {
|
||||
.get_surface_location = wakefield_get_surface_location,
|
||||
.move_surface = wakefield_move_surface,
|
||||
.get_pixel_color = wakefield_get_pixel_color,
|
||||
.capture_create = wakefield_capture_create
|
||||
};
|
||||
|
||||
static void
|
||||
wakefield_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
|
||||
{
|
||||
struct wakefield *wakefield = data;
|
||||
|
||||
struct wl_resource *resource = wl_resource_create(client, &wakefield_interface, 1, id);
|
||||
if (resource) {
|
||||
wl_resource_set_implementation(resource, &wakefield_implementation, wakefield, NULL);
|
||||
}
|
||||
|
||||
weston_log_scope_printf(wakefield->log, "WAKEFIELD: bind\n");
|
||||
}
|
||||
|
||||
static void
|
||||
wakefield_destroy(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct wakefield *wakefield = container_of(listener, struct wakefield, destroy_listener);
|
||||
|
||||
weston_log_scope_printf(wakefield->log, "WAKEFIELD: destroy\n");
|
||||
|
||||
wl_list_remove(&wakefield->destroy_listener.link);
|
||||
|
||||
weston_log_scope_destroy(wakefield->log);
|
||||
free(wakefield);
|
||||
}
|
||||
|
||||
WL_EXPORT int
|
||||
wet_module_init(struct weston_compositor *wc, int *argc, char *argv[])
|
||||
{
|
||||
struct wakefield *wakefield = zalloc(sizeof(struct wakefield));
|
||||
if (wakefield == NULL)
|
||||
return -1;
|
||||
|
||||
if (!weston_compositor_add_destroy_listener_once(wc, &wakefield->destroy_listener,
|
||||
wakefield_destroy)) {
|
||||
free(wakefield);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
wakefield->compositor = wc;
|
||||
// Log scope; add this to weston option list to subscribe: `--logger-scopes=wakefield`
|
||||
// See https://wayland.pages.freedesktop.org/weston/toc/libweston/log.html for more info.
|
||||
wakefield->log = weston_compositor_add_log_scope(wc, "wakefield",
|
||||
"wakefield plugin own actions",
|
||||
NULL, NULL, NULL);
|
||||
|
||||
if (wl_global_create(wc->wl_display, &wakefield_interface,
|
||||
1, wakefield, wakefield_bind) == NULL) {
|
||||
wl_list_remove(&wakefield->destroy_listener.link);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -28,17 +28,51 @@ package sun.awt;
|
||||
import java.io.File;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.Toolkit;
|
||||
import java.lang.annotation.Native;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
import sun.awt.wl.WLGraphicsEnvironment;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
public class PlatformGraphicsInfo {
|
||||
@Native
|
||||
public static final int TK_UNDEF = 0;
|
||||
@Native
|
||||
public static final int TK_X11 = 1;
|
||||
@Native
|
||||
public static final int TK_WAYLAND = 2;
|
||||
|
||||
private static int toolkitID = TK_UNDEF;
|
||||
|
||||
private static int getToolkitID() {
|
||||
if (toolkitID == TK_UNDEF) {
|
||||
@SuppressWarnings("removal")
|
||||
String name = AccessController.doPrivileged(
|
||||
new GetPropertyAction("awt.toolkit.name"));
|
||||
if ("XToolkit".equals(name)) {
|
||||
toolkitID = TK_X11;
|
||||
} if ("WLToolkit".equals(name)) {
|
||||
toolkitID = TK_WAYLAND;
|
||||
} else {
|
||||
toolkitID = TK_X11;
|
||||
}
|
||||
}
|
||||
return toolkitID;
|
||||
}
|
||||
|
||||
public static GraphicsEnvironment createGE() {
|
||||
return new X11GraphicsEnvironment();
|
||||
return (getToolkitID() == TK_X11)?
|
||||
new X11GraphicsEnvironment() :
|
||||
new WLGraphicsEnvironment();
|
||||
}
|
||||
|
||||
public static Toolkit createToolkit() {
|
||||
return new sun.awt.X11.XToolkit();
|
||||
return (getToolkitID() == TK_X11)?
|
||||
new sun.awt.X11.XToolkit() :
|
||||
new sun.awt.wl.WLToolkit();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,8 +86,26 @@ public class PlatformGraphicsInfo {
|
||||
boolean noDisplay =
|
||||
AccessController.doPrivileged((PrivilegedAction<Boolean>) () -> {
|
||||
|
||||
final String display = System.getenv("DISPLAY");
|
||||
return display == null || display.trim().isEmpty();
|
||||
if (getToolkitID() == TK_X11) {
|
||||
final String display = System.getenv("DISPLAY");
|
||||
return display == null || display.trim().isEmpty();
|
||||
} else {
|
||||
// This code needs to be in sync with what wl_display_connect() does
|
||||
// in WLToolkit.initIDs().
|
||||
final String wl_display = System.getenv("WAYLAND_DISPLAY");
|
||||
if (wl_display != null && !wl_display.trim().isEmpty()) {
|
||||
return false; // not headless
|
||||
}
|
||||
|
||||
// Check $XDG_RUNTIME_DIR/wayland-0.
|
||||
final String socketDir = System.getenv("XDG_RUNTIME_DIR");
|
||||
if (socketDir != null && !socketDir.trim().isEmpty()) {
|
||||
final Path defaultSocketPath = Path.of(socketDir).resolve("wayland-0");
|
||||
return !Files.isReadable(defaultSocketPath);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (noDisplay) {
|
||||
return true;
|
||||
|
||||
79
src/java.desktop/unix/classes/sun/awt/wl/WLButtonPeer.java
Normal file
79
src/java.desktop/unix/classes/sun/awt/wl/WLButtonPeer.java
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, JetBrains s.r.o.. 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.wl;
|
||||
|
||||
import java.awt.Button;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.peer.ButtonPeer;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
public class WLButtonPeer extends WLComponentPeer implements ButtonPeer {
|
||||
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.wl.WLButtonPeer");
|
||||
String label;
|
||||
|
||||
|
||||
public WLButtonPeer(Button target) {
|
||||
super(target);
|
||||
label = target.getLabel();
|
||||
}
|
||||
|
||||
public boolean isFocusable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLabel(String label) {
|
||||
log.info("Not implemented: WLButtonPeer.setLabel(String)");
|
||||
}
|
||||
|
||||
public void setBackground(Color c) {
|
||||
super.setBackground(c);
|
||||
}
|
||||
|
||||
public void focusGained(FocusEvent e) {
|
||||
super.focusGained(e);
|
||||
log.info("Not implemented: WLButtonPeer.focusGained(FocusEvent)");
|
||||
}
|
||||
|
||||
public void focusLost(FocusEvent e) {
|
||||
super.focusLost(e);
|
||||
log.info("Not implemented: WLButtonPeer.focusLost(FocusEvent)");
|
||||
}
|
||||
|
||||
@Override
|
||||
void paintPeer(Graphics g) {
|
||||
super.paintPeer(g);
|
||||
log.info("Not implemented: WLButtonPeer.paintPeer(Graphics)");
|
||||
}
|
||||
|
||||
public Dimension getMinimumSize() {
|
||||
log.info("Not implemented: WLButtonPeer.getMinimumSize()");
|
||||
return new Dimension(0, 0);
|
||||
}
|
||||
}
|
||||
70
src/java.desktop/unix/classes/sun/awt/wl/WLCanvasPeer.java
Normal file
70
src/java.desktop/unix/classes/sun/awt/wl/WLCanvasPeer.java
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, JetBrains s.r.o.. 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.wl;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.peer.CanvasPeer;
|
||||
|
||||
class WLCanvasPeer extends WLComponentPeer implements CanvasPeer {
|
||||
|
||||
private boolean eraseBackgroundDisabled;
|
||||
|
||||
|
||||
WLCanvasPeer(Component target) {
|
||||
super(target);
|
||||
}
|
||||
|
||||
|
||||
public GraphicsConfiguration getAppropriateGraphicsConfiguration(
|
||||
GraphicsConfiguration gc)
|
||||
{
|
||||
if (graphicsConfig == null || gc == null) {
|
||||
return gc;
|
||||
}
|
||||
|
||||
graphicsConfig = (WLGraphicsConfig) GraphicsEnvironment.
|
||||
getLocalGraphicsEnvironment().
|
||||
getScreenDevices()[0].
|
||||
getDefaultConfiguration();
|
||||
|
||||
|
||||
return graphicsConfig;
|
||||
}
|
||||
|
||||
protected boolean shouldFocusOnClick() {
|
||||
// Canvas should always be able to be focused by mouse clicks.
|
||||
return true;
|
||||
}
|
||||
|
||||
public void disableBackgroundErase() {
|
||||
eraseBackgroundDisabled = true;
|
||||
}
|
||||
protected boolean doEraseBackground() {
|
||||
return !eraseBackgroundDisabled;
|
||||
}
|
||||
}
|
||||
553
src/java.desktop/unix/classes/sun/awt/wl/WLComponentPeer.java
Normal file
553
src/java.desktop/unix/classes/sun/awt/wl/WLComponentPeer.java
Normal file
@@ -0,0 +1,553 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2022, JetBrains s.r.o.. 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.wl;
|
||||
|
||||
import static sun.awt.wl.WLToolkit.postEvent;
|
||||
|
||||
import java.awt.AWTEvent;
|
||||
import java.awt.AWTException;
|
||||
import java.awt.BufferCapabilities;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Image;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.SystemColor;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.InputMethodEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseWheelEvent;
|
||||
import java.awt.event.PaintEvent;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.VolatileImage;
|
||||
import java.awt.peer.ComponentPeer;
|
||||
import java.awt.peer.ContainerPeer;
|
||||
import java.util.Objects;
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.AWTAccessor.ComponentAccessor;
|
||||
import sun.awt.PaintEventDispatcher;
|
||||
import sun.awt.SunToolkit;
|
||||
import sun.awt.event.IgnorePaintEvent;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.java2d.wl.WLSurfaceData;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
import sun.util.logging.PlatformLogger.Level;
|
||||
|
||||
|
||||
public class WLComponentPeer implements ComponentPeer
|
||||
{
|
||||
private long nativePtr;
|
||||
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.wl.WLComponentPeer");
|
||||
protected final Component target;
|
||||
protected WLGraphicsConfig graphicsConfig;
|
||||
protected Color background;
|
||||
SurfaceData surfaceData;
|
||||
WLRepaintArea paintArea;
|
||||
boolean paintPending = false;
|
||||
boolean isLayouting = false;
|
||||
boolean visible = false;
|
||||
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
// used to check if we need to re-create surfaceData.
|
||||
int oldWidth = -1;
|
||||
int oldHeight = -1;
|
||||
|
||||
static {
|
||||
initIDs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard peer constructor, with corresponding Component
|
||||
*/
|
||||
WLComponentPeer(Component target) {
|
||||
this.target = target;
|
||||
this.background = target.getBackground();
|
||||
initGraphicsConfiguration();
|
||||
this.surfaceData = graphicsConfig.createSurfaceData(this);
|
||||
this.nativePtr = nativeCreateFrame();
|
||||
paintArea = new WLRepaintArea();
|
||||
Rectangle bounds = target.getBounds();
|
||||
x = bounds.x;
|
||||
y = bounds.y;
|
||||
width = bounds.width;
|
||||
height = bounds.height;
|
||||
log.info("WLComponentPeer: target=" + target + " x=" + x + " y=" + y +
|
||||
" width=" + width + " height=" + height);
|
||||
// TODO
|
||||
// setup parent window for target
|
||||
}
|
||||
|
||||
int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public final void repaint(int x, int y, int width, int height) {
|
||||
if (!isVisible() || getWidth() == 0 || getHeight() == 0) {
|
||||
return;
|
||||
}
|
||||
Graphics g = getGraphics();
|
||||
if (g != null) {
|
||||
try {
|
||||
g.setClip(x, y, width, height);
|
||||
if (SunToolkit.isDispatchThreadForAppContext(getTarget())) {
|
||||
paint(g); // The native and target will be painted in place.
|
||||
} else {
|
||||
paintPeer(g);
|
||||
postPaintEvent(target, x, y, width, height);
|
||||
}
|
||||
} finally {
|
||||
g.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void postPaintEvent(Component target, int x, int y, int w, int h) {
|
||||
PaintEvent event = PaintEventDispatcher.getPaintEventDispatcher().
|
||||
createPaintEvent(target, x, y, w, h);
|
||||
if (event != null) {
|
||||
postEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void postPaintEvent() {
|
||||
if (isVisible()) {
|
||||
PaintEvent pe = new PaintEvent(target, PaintEvent.PAINT,
|
||||
new Rectangle(0, 0, width, height));
|
||||
postEvent(pe);
|
||||
}
|
||||
}
|
||||
|
||||
boolean isVisible() {
|
||||
return visible;
|
||||
}
|
||||
|
||||
void repaint() {
|
||||
repaint(0, 0, getWidth(), getHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reparent(ContainerPeer newContainer) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReparentSupported() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isObscured() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDetermineObscurity() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void focusGained(FocusEvent e) {
|
||||
log.info("Not implemented: WLComponentPeer.isObscured()");
|
||||
}
|
||||
|
||||
public void focusLost(FocusEvent e) {
|
||||
log.info("Not implemented: WLComponentPeer.focusLost(FocusEvent)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFocusable() {
|
||||
log.info("Not implemented: WLComponentPeer.isFocusable()");
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean requestFocus(Component lightweightChild, boolean temporary,
|
||||
boolean focusedWindowChangeAllowed, long time,
|
||||
FocusEvent.Cause cause)
|
||||
{
|
||||
log.info("Not implemented: WLComponentPeer.focusLost(FocusEvent)");
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void wlSetVisible(boolean v) {
|
||||
this.visible = v;
|
||||
if (this.visible) {
|
||||
nativeShowComponent(nativePtr, getParentNativePtr(target), target.getX(), target.getY());
|
||||
((WLSurfaceData)surfaceData).initSurface(this, background != null ? background.getRGB() : 0, target.getWidth(), target.getHeight());
|
||||
PaintEvent event = PaintEventDispatcher.getPaintEventDispatcher().
|
||||
createPaintEvent(target, 0, 0, target.getWidth(), target.getHeight());
|
||||
if (event != null) {
|
||||
WLToolkit.postEvent(WLToolkit.targetToAppContext(event.getSource()), event);
|
||||
}
|
||||
} else {
|
||||
nativeHideFrame(nativePtr);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean v) {
|
||||
wlSetVisible(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ComponentPeer
|
||||
*/
|
||||
public void setEnabled(final boolean value) {
|
||||
log.info("Not implemented: WLComponentPeer.setEnabled(boolean)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(final Graphics g) {
|
||||
paintPeer(g);
|
||||
target.paint(g);
|
||||
}
|
||||
|
||||
void paintPeer(final Graphics g) {
|
||||
log.info("Not implemented: WLComponentPeer.paintPeer(Graphics)");
|
||||
}
|
||||
|
||||
Graphics getGraphics(SurfaceData surfData, Color afore, Color aback, Font afont) {
|
||||
if (surfData == null) return null;
|
||||
|
||||
Color bgColor = aback;
|
||||
if (bgColor == null) {
|
||||
bgColor = SystemColor.window;
|
||||
}
|
||||
Color fgColor = afore;
|
||||
if (fgColor == null) {
|
||||
fgColor = SystemColor.windowText;
|
||||
}
|
||||
Font font = afont;
|
||||
if (font == null) {
|
||||
font = new Font(Font.DIALOG, Font.PLAIN, 12);
|
||||
}
|
||||
return new SunGraphics2D(surfData, fgColor, bgColor, font);
|
||||
}
|
||||
|
||||
public Graphics getGraphics() {
|
||||
return getGraphics(surfaceData,
|
||||
target.getForeground(),
|
||||
target.getBackground(),
|
||||
target.getFont());
|
||||
}
|
||||
|
||||
public Component getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
public void print(Graphics g) {
|
||||
log.info("Not implemented: WLComponentPeer.print(Graphics)");
|
||||
}
|
||||
|
||||
public void setBounds(int x, int y, int width, int height, int op) {
|
||||
if (this.x != x || this.y != y) {
|
||||
WLRobotPeer.setLocationOfWLSurface(getWLSurface(), x, y);
|
||||
}
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
validateSurface();
|
||||
layout();
|
||||
}
|
||||
|
||||
void validateSurface() {
|
||||
if ((width != oldWidth) || (height != oldHeight)) {
|
||||
doValidateSurface();
|
||||
|
||||
oldWidth = width;
|
||||
oldHeight = height;
|
||||
}
|
||||
}
|
||||
|
||||
final void doValidateSurface() {
|
||||
SurfaceData oldData = surfaceData;
|
||||
if (oldData != null) {
|
||||
surfaceData = graphicsConfig.createSurfaceData(this);
|
||||
oldData.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void coalescePaintEvent(PaintEvent e) {
|
||||
Rectangle r = e.getUpdateRect();
|
||||
if (!(e instanceof IgnorePaintEvent)) {
|
||||
|
||||
paintArea.add(r, e.getID());
|
||||
}
|
||||
if (true) {
|
||||
switch(e.getID()) {
|
||||
case PaintEvent.UPDATE:
|
||||
if (log.isLoggable(Level.INFO)) {
|
||||
log.info("WLCP coalescePaintEvent : UPDATE : add : x = " +
|
||||
r.x + ", y = " + r.y + ", width = " + r.width + ",height = " + r.height);
|
||||
}
|
||||
return;
|
||||
case PaintEvent.PAINT:
|
||||
if (log.isLoggable(Level.INFO)) {
|
||||
log.info("WLCP coalescePaintEvent : PAINT : add : x = " +
|
||||
r.x + ", y = " + r.y + ", width = " + r.width + ",height = " + r.height);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Point getLocationOnScreen() {
|
||||
final long wlSurfacePtr = getWLSurface();
|
||||
if (wlSurfacePtr != 0) {
|
||||
return WLRobotPeer.getLocationOfWLSurface(wlSurfacePtr);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("getLocationOnScreen() not supported without wayland surface");
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("fallthrough")
|
||||
public void handleEvent(AWTEvent e) {
|
||||
if ((e instanceof InputEvent) && !((InputEvent) e).isConsumed() && target.isEnabled()) {
|
||||
if (e instanceof MouseEvent) {
|
||||
if (e instanceof MouseWheelEvent) {
|
||||
log.info("Not implemented: WLComponentPeer.handleEvent(AWTEvent): MouseWheelEvent");
|
||||
} else
|
||||
log.info("Not implemented: WLComponentPeer.handleEvent(AWTEvent): MouseEvent");
|
||||
} else if (e instanceof KeyEvent) {
|
||||
log.info("Not implemented: WLComponentPeer.handleEvent(AWTEvent): handleF10JavaKeyEvent");
|
||||
log.info("Not implemented: WLComponentPeer.handleEvent(AWTEvent): handleJavaKeyEvent");
|
||||
}
|
||||
} else if (e instanceof KeyEvent && !((InputEvent) e).isConsumed()) {
|
||||
// even if target is disabled.
|
||||
log.info("Not implemented: WLComponentPeer.handleEvent(AWTEvent): handleF10JavaKeyEvent");
|
||||
} else if (e instanceof InputMethodEvent) {
|
||||
log.info("Not implemented: WLComponentPeer.handleEvent(AWTEvent): handleJavaInputMethodEvent");
|
||||
}
|
||||
|
||||
int id = e.getID();
|
||||
|
||||
switch (id) {
|
||||
case PaintEvent.PAINT:
|
||||
// Got native painting
|
||||
paintPending = false;
|
||||
// Fallthrough to next statement
|
||||
case PaintEvent.UPDATE:
|
||||
log.info("WLComponentPeer.handleEvent(AWTEvent): UPDATE " + this);
|
||||
// Skip all painting while layouting and all UPDATEs
|
||||
// while waiting for native paint
|
||||
if (!isLayouting && !paintPending) {
|
||||
paintArea.paint(target, false);
|
||||
}
|
||||
return;
|
||||
case FocusEvent.FOCUS_LOST:
|
||||
case FocusEvent.FOCUS_GAINED:
|
||||
log.info("Not implemented: WLComponentPeer.handleEvent(AWTEvent): handleJavaFocusEvent");
|
||||
break;
|
||||
case WindowEvent.WINDOW_LOST_FOCUS:
|
||||
case WindowEvent.WINDOW_GAINED_FOCUS:
|
||||
log.info("Not implemented: WLComponentPeer.handleEvent(AWTEvent): handleJavaWindowFocusEvent");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void beginLayout() {
|
||||
// Skip all painting till endLayout
|
||||
isLayouting = true;
|
||||
|
||||
}
|
||||
|
||||
public void endLayout() {
|
||||
log.info("WLComponentPeer.endLayout(): paintArea.isEmpty() " + paintArea.isEmpty());
|
||||
if (!paintPending && !paintArea.isEmpty()
|
||||
&& !AWTAccessor.getComponentAccessor().getIgnoreRepaint(target))
|
||||
{
|
||||
// if not waiting for native painting repaint damaged area
|
||||
postEvent(new PaintEvent(target, PaintEvent.PAINT,
|
||||
new Rectangle()));
|
||||
}
|
||||
isLayouting = false;
|
||||
}
|
||||
|
||||
public Dimension getMinimumSize() {
|
||||
return target.getSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorModel getColorModel() {
|
||||
if (graphicsConfig != null) {
|
||||
return graphicsConfig.getColorModel ();
|
||||
}
|
||||
else {
|
||||
return Toolkit.getDefaultToolkit().getColorModel();
|
||||
}
|
||||
}
|
||||
|
||||
public Dimension getPreferredSize() {
|
||||
return getMinimumSize();
|
||||
}
|
||||
|
||||
public void layout() {}
|
||||
|
||||
@Override
|
||||
public void setBackground(Color c) {
|
||||
if (Objects.equals(background, c)) {
|
||||
return;
|
||||
}
|
||||
background = c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setForeground(Color c) {
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
log.fine("Set foreground to " + c);
|
||||
}
|
||||
log.info("Not implemented: WLComponentPeer.setForeground(Color)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FontMetrics getFontMetrics(Font font) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
nativeDisposeFrame(nativePtr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFont(Font f) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Font getFont() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void updateCursorImmediately() {
|
||||
log.info("Not implemented: WLComponentPeer.updateCursorImmediately()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image createImage(int width, int height) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VolatileImage createVolatileImage(int width, int height) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
protected void initGraphicsConfiguration() {
|
||||
graphicsConfig = (WLGraphicsConfig) target.getGraphicsConfiguration();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsConfiguration getGraphicsConfiguration() {
|
||||
if (graphicsConfig == null) {
|
||||
initGraphicsConfiguration();
|
||||
}
|
||||
return graphicsConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handlesWheelScrolling() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createBuffers(int numBuffers, BufferCapabilities caps) throws AWTException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flip(int x1, int y1, int x2, int y2, BufferCapabilities.FlipContents flipAction) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getBackBuffer() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyBuffers() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setZOrder(ComponentPeer above) {
|
||||
log.info("Not implemented: WLComponentPeer.setZOrder(ComponentPeer)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyShape(Region shape) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateGraphicsData(GraphicsConfiguration gc) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
private static native void initIDs();
|
||||
|
||||
protected native long nativeCreateFrame();
|
||||
|
||||
protected native void nativeShowComponent(long ptr, long parentPtr, int x, int y);
|
||||
|
||||
protected native void nativeHideFrame(long ptr);
|
||||
|
||||
protected native void nativeDisposeFrame(long ptr);
|
||||
|
||||
private native long getWLSurface();
|
||||
|
||||
static long getParentNativePtr(Component target) {
|
||||
Component parent = target.getParent();
|
||||
if (parent == null) return 0;
|
||||
|
||||
final ComponentAccessor acc = AWTAccessor.getComponentAccessor();
|
||||
ComponentPeer peer = acc.getPeer(parent);
|
||||
|
||||
return ((WLComponentPeer)peer).nativePtr;
|
||||
}
|
||||
}
|
||||
188
src/java.desktop/unix/classes/sun/awt/wl/WLFramePeer.java
Normal file
188
src/java.desktop/unix/classes/sun/awt/wl/WLFramePeer.java
Normal file
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, JetBrains s.r.o.. 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.wl;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Window;
|
||||
import java.awt.Dialog;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Insets;
|
||||
import java.awt.MenuBar;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.peer.ComponentPeer;
|
||||
import java.awt.peer.FramePeer;
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.AWTAccessor.ComponentAccessor;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
public class WLFramePeer extends WLComponentPeer implements FramePeer {
|
||||
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.wl.WLFramePeer");
|
||||
|
||||
public WLFramePeer(Frame target) {
|
||||
super(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void wlSetVisible(boolean v) {
|
||||
super.wlSetVisible(v);
|
||||
final ComponentAccessor acc = AWTAccessor.getComponentAccessor();
|
||||
for (Component c : ((Frame)target).getComponents()) {
|
||||
ComponentPeer cPeer = acc.getPeer(c);
|
||||
if (cPeer instanceof WLComponentPeer) {
|
||||
((WLComponentPeer) cPeer).wlSetVisible(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static native void initIDs();
|
||||
|
||||
@Override
|
||||
public Insets getInsets() {
|
||||
return new Insets(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginValidate() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endValidate() {
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void beginLayout() {
|
||||
// log.info("Not implemented: WLFramePeer.beginLayout()");
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void endLayout() {
|
||||
// log.info("Not implemented: WLFramePeer.endLayout()");
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void setTitle(String title) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMenuBar(MenuBar mb) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResizable(boolean resizeable) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setState(int state) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getState() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaximizedBounds(Rectangle bounds) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBoundsPrivate(int x, int y, int width, int height) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle getBoundsPrivate() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emulateActivation(boolean activate) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toFront() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBack() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAlwaysOnTopState() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFocusableWindowState() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModalBlocked(Dialog blocker, boolean blocked) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateMinimumSize() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateIconImages() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOpacity(float opacity) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOpaque(boolean isOpaque) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateWindow() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void repositionSecurityWarning() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
// called from native code
|
||||
private void postWindowClosing() {
|
||||
WLToolkit.postEvent(new WindowEvent((Window) target, WindowEvent.WINDOW_CLOSING));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, JetBrains s.r.o.. 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.wl;
|
||||
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.DirectColorModel;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import sun.java2d.wl.WLSurfaceData;
|
||||
|
||||
public class WLGraphicsConfig extends GraphicsConfiguration {
|
||||
private final WLGraphicsDevice device;
|
||||
private final Rectangle bounds = new Rectangle(800, 600);
|
||||
|
||||
public WLGraphicsConfig(WLGraphicsDevice device) {
|
||||
this.device = device;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WLGraphicsDevice getDevice() {
|
||||
return device;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorModel getColorModel() {
|
||||
return new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorModel getColorModel(int transparency) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AffineTransform getDefaultTransform() {
|
||||
double scale = getScale();
|
||||
return AffineTransform.getScaleInstance(scale, scale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AffineTransform getNormalizingTransform() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle getBounds() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
public SurfaceType getSurfaceType() {
|
||||
return SurfaceType.IntArgb;
|
||||
}
|
||||
|
||||
public SurfaceData createSurfaceData(WLComponentPeer peer) {
|
||||
return WLSurfaceData.createData(peer);
|
||||
}
|
||||
|
||||
public double getScale() {
|
||||
return getDevice().getScaleFactor();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2022, JetBrains s.r.o.. 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.wl;
|
||||
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsDevice;
|
||||
|
||||
public class WLGraphicsDevice extends GraphicsDevice {
|
||||
private double scale = 1.0;
|
||||
|
||||
private final WLGraphicsConfig config = new WLGraphicsConfig(this);
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return TYPE_RASTER_SCREEN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIDstring() {
|
||||
return "WLGraphicsDevice";
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsConfiguration[] getConfigurations() {
|
||||
return new GraphicsConfiguration[] {config};
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsConfiguration getDefaultConfiguration() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public double getScaleFactor() {
|
||||
return scale;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2022, JetBrains s.r.o.. 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.wl;
|
||||
|
||||
import java.awt.GraphicsDevice;
|
||||
import sun.java2d.SunGraphicsEnvironment;
|
||||
import sun.java2d.SurfaceManagerFactory;
|
||||
import sun.java2d.UnixSurfaceManagerFactory;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
public class WLGraphicsEnvironment extends SunGraphicsEnvironment {
|
||||
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.wl.WLComponentPeer");
|
||||
static {
|
||||
SurfaceManagerFactory.setInstance(new UnixSurfaceManagerFactory());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getNumScreens() {
|
||||
log.info("Not implemented: WLGraphicsEnvironment.getNumScreens()");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GraphicsDevice makeScreenDevice(int screennum) {
|
||||
log.info("Not implemented: WLGraphicsEnvironment.makeScreenDevice(int)");
|
||||
return new WLGraphicsDevice();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisplayLocal() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package sun.awt.wl;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Window;
|
||||
import java.awt.peer.KeyboardFocusManagerPeer;
|
||||
|
||||
public class WLKeyboardFocusManagerPeer implements KeyboardFocusManagerPeer {
|
||||
private static final WLKeyboardFocusManagerPeer instance = new WLKeyboardFocusManagerPeer();
|
||||
|
||||
public static WLKeyboardFocusManagerPeer getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentFocusedWindow(Window win) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Window getCurrentFocusedWindow() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentFocusOwner(Component comp) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getCurrentFocusOwner() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearGlobalFocusOwner(Window activeWindow) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, JetBrains s.r.o.. 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.wl;
|
||||
|
||||
import java.awt.Graphics;
|
||||
import sun.awt.LightweightFrame;
|
||||
import sun.awt.OverrideNativeWindowHandle;
|
||||
import sun.swing.JLightweightFrame;
|
||||
import sun.swing.SwingAccessor;
|
||||
|
||||
public class WLLightweightFramePeer extends WLFramePeer implements OverrideNativeWindowHandle {
|
||||
|
||||
WLLightweightFramePeer(LightweightFrame target) {
|
||||
super(target);
|
||||
}
|
||||
|
||||
private LightweightFrame getLwTarget() {
|
||||
return (LightweightFrame)target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Graphics getGraphics() {
|
||||
return getLwTarget().getGraphics();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateCursorImmediately() {
|
||||
SwingAccessor.getJLightweightFrameAccessor().updateCursor((JLightweightFrame)getLwTarget());
|
||||
}
|
||||
|
||||
private volatile long overriddenWindowHandle;
|
||||
|
||||
@Override
|
||||
public void overrideWindowHandle(final long handle) {
|
||||
overriddenWindowHandle = handle;
|
||||
}
|
||||
|
||||
public long getOverriddenWindowHandle() {
|
||||
return overriddenWindowHandle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void wlSetVisible(boolean visible) {
|
||||
this.visible = visible;
|
||||
}
|
||||
}
|
||||
70
src/java.desktop/unix/classes/sun/awt/wl/WLRepaintArea.java
Normal file
70
src/java.desktop/unix/classes/sun/awt/wl/WLRepaintArea.java
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, JetBrains s.r.o.. 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.wl;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.RepaintArea;
|
||||
import sun.awt.X11.XComponentPeer;
|
||||
|
||||
/**
|
||||
* The {@code RepaintArea} is a geometric construct created for the
|
||||
* purpose of holding the geometry of several coalesced paint events.
|
||||
* This geometry is accessed synchronously, although it is written such
|
||||
* that painting may still be executed asynchronously.
|
||||
*
|
||||
* @author Eric Hawkes
|
||||
*/
|
||||
final class WLRepaintArea extends RepaintArea {
|
||||
|
||||
/**
|
||||
* Calls {@code Component.update(Graphics)} with given Graphics.
|
||||
*/
|
||||
protected void updateComponent(Component comp, Graphics g) {
|
||||
if (comp != null) {
|
||||
// We don't call peer.paintPeer() here, because we shouldn't paint
|
||||
// native component when processing UPDATE events.
|
||||
super.updateComponent(comp, g);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls {@code Component.paint(Graphics)} with given Graphics.
|
||||
*/
|
||||
protected void paintComponent(Component comp, Graphics g) {
|
||||
if (comp != null) {
|
||||
final WLComponentPeer peer = AWTAccessor.getComponentAccessor()
|
||||
.getPeer(comp);
|
||||
if (peer != null) {
|
||||
peer.paintPeer(g);
|
||||
}
|
||||
super.paintComponent(comp, g);
|
||||
}
|
||||
}
|
||||
}
|
||||
142
src/java.desktop/unix/classes/sun/awt/wl/WLRobotPeer.java
Normal file
142
src/java.desktop/unix/classes/sun/awt/wl/WLRobotPeer.java
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, JetBrains s.r.o.. 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.wl;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.peer.RobotPeer;
|
||||
|
||||
public class WLRobotPeer implements RobotPeer {
|
||||
private final WLGraphicsConfig wgc;
|
||||
|
||||
static {
|
||||
initIDs();
|
||||
}
|
||||
|
||||
public WLRobotPeer(WLGraphicsDevice gd) {
|
||||
wgc = (WLGraphicsConfig) gd.getDefaultConfiguration();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMove(int x, int y) {
|
||||
throw new UnsupportedOperationException("Not implemented: WLRobotPeer.mouseMove()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePress(int buttons) {
|
||||
throw new UnsupportedOperationException("Not implemented: WLRobotPeer.mousePress()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseRelease(int buttons) {
|
||||
throw new UnsupportedOperationException("Not implemented: WLRobotPeer.mouseRelease()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseWheel(int wheelAmt) {
|
||||
throw new UnsupportedOperationException("Not implemented: WLRobotPeer.mouseWheel()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPress(int keycode) {
|
||||
throw new UnsupportedOperationException("Not implemented: WLRobotPeer.keyPress()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyRelease(int keycode) {
|
||||
throw new UnsupportedOperationException("Not implemented: WLRobotPeer.keyRelease()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRGBPixel(int x, int y) {
|
||||
checkExtensionPresent();
|
||||
|
||||
// The native implementation allows for just one such request at a time
|
||||
synchronized(WLRobotPeer.class) {
|
||||
return getRGBPixelImpl(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int [] getRGBPixels(Rectangle bounds) {
|
||||
checkExtensionPresent();
|
||||
|
||||
// The native implementation allows for just one such request at a time
|
||||
synchronized(WLRobotPeer.class) {
|
||||
return getRGBPixelsImpl(bounds.x, bounds.y, bounds.width, bounds.height);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the location in absolute coordinates of the Wayland
|
||||
* surface pointed to by the argument.
|
||||
* Throws UnsupportedOperationException if the Wayland extension
|
||||
* that implements this wasn't loaded on the server side.
|
||||
*
|
||||
* @param wlSurfacePtr a pointer to struct wl_surface
|
||||
* @return location of the surface in absolute coordinates
|
||||
*/
|
||||
static Point getLocationOfWLSurface(long wlSurfacePtr) {
|
||||
checkExtensionPresent();
|
||||
|
||||
// The native implementation allows for just one such request at a time
|
||||
synchronized(WLRobotPeer.class) {
|
||||
return getLocationOfWLSurfaceImpl(wlSurfacePtr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the screen location of the given Wayland surface to the given
|
||||
* absolute coordinates.
|
||||
* Does nothing if the Wayland extension that supports this functionality
|
||||
* was not loaded by the server.
|
||||
*
|
||||
* @param wlSurfacePtr a pointer to struct wl_surface
|
||||
* @param x the absolute x-coordinate
|
||||
* @param y the absolute y-coordinate
|
||||
*/
|
||||
static void setLocationOfWLSurface(long wlSurfacePtr, int x, int y) {
|
||||
if (isRobotExtensionPresent) {
|
||||
setLocationOfWLSurfaceImpl(wlSurfacePtr, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkExtensionPresent() {
|
||||
if (!isRobotExtensionPresent) {
|
||||
throw new UnsupportedOperationException("WLRobotPeer: wakefield extension not present in Wayland instance");
|
||||
}
|
||||
}
|
||||
|
||||
private static final boolean isRobotExtensionPresent = isRobotExtensionPresentImpl();
|
||||
|
||||
private static native void initIDs();
|
||||
|
||||
private static native boolean isRobotExtensionPresentImpl();
|
||||
private static native int getRGBPixelImpl(int x, int y);
|
||||
private static native int[] getRGBPixelsImpl(int x, int y, int width, int height);
|
||||
private static native Point getLocationOfWLSurfaceImpl(long wlSurfacePtr);
|
||||
private static native void setLocationOfWLSurfaceImpl(long wlSurfacePtr, int x, int y);
|
||||
}
|
||||
662
src/java.desktop/unix/classes/sun/awt/wl/WLToolkit.java
Normal file
662
src/java.desktop/unix/classes/sun/awt/wl/WLToolkit.java
Normal file
@@ -0,0 +1,662 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2022, JetBrains s.r.o.. 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.wl;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.Clipboard;
|
||||
import java.awt.dnd.DragGestureEvent;
|
||||
import java.awt.dnd.DragGestureListener;
|
||||
import java.awt.dnd.DragGestureRecognizer;
|
||||
import java.awt.dnd.DragSource;
|
||||
import java.awt.dnd.InvalidDnDOperationException;
|
||||
import java.awt.dnd.peer.DragSourceContextPeer;
|
||||
import java.awt.font.TextAttribute;
|
||||
import java.awt.im.InputMethodHighlight;
|
||||
import java.awt.im.spi.InputMethodDescriptor;
|
||||
import java.awt.peer.ButtonPeer;
|
||||
import java.awt.peer.CanvasPeer;
|
||||
import java.awt.peer.CheckboxMenuItemPeer;
|
||||
import java.awt.peer.CheckboxPeer;
|
||||
import java.awt.peer.ChoicePeer;
|
||||
import java.awt.peer.DesktopPeer;
|
||||
import java.awt.peer.DialogPeer;
|
||||
import java.awt.peer.FileDialogPeer;
|
||||
import java.awt.peer.FontPeer;
|
||||
import java.awt.peer.FramePeer;
|
||||
import java.awt.peer.KeyboardFocusManagerPeer;
|
||||
import java.awt.peer.LabelPeer;
|
||||
import java.awt.peer.ListPeer;
|
||||
import java.awt.peer.MenuBarPeer;
|
||||
import java.awt.peer.MenuItemPeer;
|
||||
import java.awt.peer.MenuPeer;
|
||||
import java.awt.peer.MouseInfoPeer;
|
||||
import java.awt.peer.PanelPeer;
|
||||
import java.awt.peer.PopupMenuPeer;
|
||||
import java.awt.peer.RobotPeer;
|
||||
import java.awt.peer.ScrollPanePeer;
|
||||
import java.awt.peer.ScrollbarPeer;
|
||||
import java.awt.peer.SystemTrayPeer;
|
||||
import java.awt.peer.TaskbarPeer;
|
||||
import java.awt.peer.TextAreaPeer;
|
||||
import java.awt.peer.TextFieldPeer;
|
||||
import java.awt.peer.TrayIconPeer;
|
||||
import java.awt.peer.WindowPeer;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import sun.awt.*;
|
||||
import sun.awt.datatransfer.DataTransferer;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
/**
|
||||
* On events handling: the WLToolkit class creates a thread named "AWT-Wayland"
|
||||
* where the communication with the Wayland server is chiefly carried on such
|
||||
* as sending requests over and receiving events from the server.
|
||||
* For "system" events that are not meant to trigger any user code, a separate
|
||||
* thread is utilized called "AWT-Wayland-system-dispatcher". It is the only
|
||||
* thread where such events are handled. For other events, such as mouse click
|
||||
* events, the Wayland handlers are supposed to "transfer" themselves to
|
||||
* "AWT-EventThread" by means of SunToolkit.postEvent(). See the implementation
|
||||
* of run() method for more comments.
|
||||
*/
|
||||
public class WLToolkit extends UNIXToolkit implements Runnable {
|
||||
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.wl.WLToolkit");
|
||||
|
||||
/**
|
||||
* Maximum wait time in ms between attempts to receive more data (events)
|
||||
* from the Wayland server on the toolkit thread.
|
||||
*/
|
||||
private static final int WAYLAND_DISPLAY_INTERACTION_TIMEOUT_MS = 50;
|
||||
|
||||
/**
|
||||
* Returned by readEvents() to signify the presence of new events
|
||||
* on the default Wayland display queue that have not been dispatched yet.
|
||||
*/
|
||||
private static final int READ_RESULT_FINISHED_WITH_EVENTS = 0;
|
||||
|
||||
/**
|
||||
* Returned by readEvents() to signify the total absence of events
|
||||
* on any of the Wayland display queues.
|
||||
*/
|
||||
private static final int READ_RESULT_FINISHED_NO_EVENTS = 1;
|
||||
|
||||
/**
|
||||
* Returned by readEvents() to signify the absence of *new* events
|
||||
* on the default Wayland display queue. The existing events
|
||||
* should better be dispatched prior to calling readEvents() again.
|
||||
*/
|
||||
private static final int READ_RESULT_NO_NEW_EVENTS = 2;
|
||||
|
||||
/**
|
||||
* Returned by readEvents() in case of an error condition like
|
||||
* disappearing of the Wayland display. Errors not specifically
|
||||
* related to Wayland are reported via an exception.
|
||||
*/
|
||||
private static final int READ_RESULT_ERROR = 3;
|
||||
|
||||
private static native void initIDs();
|
||||
|
||||
static {
|
||||
if (!GraphicsEnvironment.isHeadless()) {
|
||||
initIDs();
|
||||
}
|
||||
}
|
||||
|
||||
public WLToolkit() {
|
||||
Thread toolkitThread = new Thread(this, "AWT-Wayland");
|
||||
toolkitThread.setDaemon(true);
|
||||
toolkitThread.start();
|
||||
|
||||
final Thread toolkitSystemThread = new Thread(this::dispatchNonDefaultQueues, "AWT-Wayland-system-dispatcher");
|
||||
toolkitSystemThread.setDaemon(true);
|
||||
toolkitSystemThread.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ButtonPeer createButton(Button target) {
|
||||
ButtonPeer peer = new WLButtonPeer(target);
|
||||
targetCreatedPeer(target, peer);
|
||||
return peer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FramePeer createLightweightFrame(LightweightFrame target) {
|
||||
FramePeer peer = new WLLightweightFramePeer(target);
|
||||
targetCreatedPeer(target, peer);
|
||||
return peer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FramePeer createFrame(Frame target) {
|
||||
FramePeer peer = new WLFramePeer(target);
|
||||
targetCreatedPeer(target, peer);
|
||||
return peer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wayland events coming to queues other that the default are handled here.
|
||||
* The code is executed on a separate thread and must not call any user code.
|
||||
*/
|
||||
private void dispatchNonDefaultQueues() {
|
||||
dispatchNonDefaultQueuesImpl(); // does not return until error or server disconnect
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while(true) {
|
||||
int result = readEvents();
|
||||
// TODO: the result of the very first call can theoretically be READ_RESULT_NO_NEW_EVENTS
|
||||
// and that assumes we already have a dispatcher queued, which is initially not so.
|
||||
// Can be solved by queueing dispatch once in the very beginning (?)
|
||||
|
||||
// There's also a problem where we can start waiting in the READ_RESULT_NO_NEW_EVENTS branch,
|
||||
// but at the same time dispatch has just completed. So on the one hand we are ready for
|
||||
// more events, but on the other we will wait for 50ms before getting them. This may hinder
|
||||
// the responsiveness.
|
||||
|
||||
if (result == READ_RESULT_ERROR) {
|
||||
// TODO: display disconnect handling here?
|
||||
break;
|
||||
} else if (result == READ_RESULT_FINISHED_WITH_EVENTS) {
|
||||
SunToolkit.postEvent(AppContext.getAppContext(),
|
||||
new PeerEvent(this, () -> {
|
||||
dispatchEventsOnEDT();
|
||||
synchronized (WLToolkit.this) {
|
||||
// Finally, processed the entire events queue, can ask for more now.
|
||||
WLToolkit.this.notifyAll();
|
||||
}
|
||||
}, PeerEvent.ULTIMATE_PRIORITY_EVENT));
|
||||
} else if (result == READ_RESULT_NO_NEW_EVENTS) {
|
||||
synchronized (WLToolkit.this) {
|
||||
try {
|
||||
// Give the EDT an opportunity to process the current event queue
|
||||
// (see above) before requesting yet another dispatch
|
||||
// on the very next loop iteration. That iteration may exit with
|
||||
// the same READ_RESULT_NO_NEW_EVENTS thus creating a busy loop
|
||||
// until EDT finally gets around to dispatching the existing queue.
|
||||
WLToolkit.this.wait(WAYLAND_DISPLAY_INTERACTION_TIMEOUT_MS);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RobotPeer createRobot(GraphicsDevice screen) throws AWTException {
|
||||
if (screen instanceof WLGraphicsDevice) {
|
||||
return new WLRobotPeer((WLGraphicsDevice) screen);
|
||||
}
|
||||
return super.createRobot(screen);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDynamicLayout(boolean b) {
|
||||
log.info("Not implemented: WLToolkit.setDynamicLayout()");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isDynamicLayoutSet() {
|
||||
log.info("Not implemented: WLToolkit.isDynamicLayoutSet()");
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean isDynamicLayoutSupported() {
|
||||
log.info("Not implemented: WLToolkit.isDynamicLayoutSupported()");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDynamicLayoutActive() {
|
||||
return isDynamicLayoutSupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FontPeer getFontPeer(String name, int style){
|
||||
log.info("Not implemented: WLToolkit.getFontPeer()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException {
|
||||
log.info("Not implemented: WLToolkit.createDragSourceContextPeer()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends DragGestureRecognizer> T
|
||||
createDragGestureRecognizer(Class<T> recognizerClass,
|
||||
DragSource ds,
|
||||
Component c,
|
||||
int srcActions,
|
||||
DragGestureListener dgl)
|
||||
{
|
||||
log.info("Not implemented: WLToolkit.createDragGestureRecognizer()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target) {
|
||||
log.info("Not implemented: WLToolkit.createCheckboxMenuItem()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuItemPeer createMenuItem(MenuItem target) {
|
||||
log.info("Not implemented: WLToolkit.createMenuItem()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextFieldPeer createTextField(TextField target) {
|
||||
log.info("Not implemented: WLToolkit.createTextField()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LabelPeer createLabel(Label target) {
|
||||
log.info("Not implemented: WLToolkit.createLabel()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListPeer createList(java.awt.List target) {
|
||||
log.info("Not implemented: WLToolkit.createList()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CheckboxPeer createCheckbox(Checkbox target) {
|
||||
log.info("Not implemented: WLToolkit.createCheckbox()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScrollbarPeer createScrollbar(Scrollbar target) {
|
||||
log.info("Not implemented: WLToolkit.createScrollbar()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScrollPanePeer createScrollPane(ScrollPane target) {
|
||||
log.info("Not implemented: WLToolkit.createScrollPane()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextAreaPeer createTextArea(TextArea target) {
|
||||
log.info("Not implemented: WLToolkit.createTextArea()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChoicePeer createChoice(Choice target) {
|
||||
log.info("Not implemented: WLToolkit.createChoice()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CanvasPeer createCanvas(Canvas target) {
|
||||
WLCanvasPeer peer = new WLCanvasPeer(target);
|
||||
targetCreatedPeer(target, peer);
|
||||
return peer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PanelPeer createPanel(Panel target) {
|
||||
log.info("Not implemented: WLToolkit.createPanel()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindowPeer createWindow(Window target) {
|
||||
log.info("Not implemented: WLToolkit.createWindow()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialogPeer createDialog(Dialog target) {
|
||||
log.info("Not implemented: WLToolkit.createDialog()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileDialogPeer createFileDialog(FileDialog target) {
|
||||
log.info("Not implemented: WLToolkit.createFileDialog()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuBarPeer createMenuBar(MenuBar target) {
|
||||
log.info("Not implemented: WLToolkit.createMenuBar()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuPeer createMenu(Menu target) {
|
||||
log.info("Not implemented: WLToolkit.createMenu()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PopupMenuPeer createPopupMenu(PopupMenu target) {
|
||||
log.info("Not implemented: WLToolkit.createPopupMenu()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized MouseInfoPeer getMouseInfoPeer() {
|
||||
log.info("Not implemented: WLToolkit.getMouseInfoPeer()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyboardFocusManagerPeer getKeyboardFocusManagerPeer() throws HeadlessException {
|
||||
return WLKeyboardFocusManagerPeer.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new custom cursor.
|
||||
*/
|
||||
@Override
|
||||
public Cursor createCustomCursor(Image cursor, Point hotSpot, String name)
|
||||
throws IndexOutOfBoundsException {
|
||||
log.info("Not implemented: WLToolkit.createCustomCursor()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrayIconPeer createTrayIcon(TrayIcon target)
|
||||
throws HeadlessException
|
||||
{
|
||||
log.info("Not implemented: WLToolkit.createTrayIcon()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SystemTrayPeer createSystemTray(SystemTray target) throws HeadlessException {
|
||||
log.info("Not implemented: WLToolkit.createSystemTray()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTraySupported() {
|
||||
log.info("Not implemented: WLToolkit.isTraySupported()");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTransferer getDataTransferer() {
|
||||
log.info("Not implemented: WLToolkit.getDataTransferer()");
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the supported cursor size
|
||||
*/
|
||||
@Override
|
||||
public Dimension getBestCursorSize(int preferredWidth, int preferredHeight) {
|
||||
log.info("Not implemented: WLToolkit.getBestCursorSize()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumCursorColors() {
|
||||
return 2; // Black and white.
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<TextAttribute, ?> mapInputMethodHighlight( InputMethodHighlight highlight) {
|
||||
log.info("Not implemented: WLToolkit.mapInputMethodHighlight()");
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public boolean getLockingKeyState(int key) {
|
||||
log.info("Not implemented: WLToolkit.getLockingKeyState()");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Clipboard getSystemClipboard() {
|
||||
log.info("Not implemented: WLToolkit.getSystemClipboard()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Clipboard getSystemSelection() {
|
||||
log.info("Not implemented: WLToolkit.getSystemSelection()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beep() {
|
||||
log.info("Not implemented: WLToolkit.beep()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrintJob getPrintJob(final Frame frame, final String doctitle,
|
||||
final Properties props) {
|
||||
log.info("Not implemented: WLToolkit.getPrintJob()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrintJob getPrintJob(final Frame frame, final String doctitle,
|
||||
final JobAttributes jobAttributes,
|
||||
final PageAttributes pageAttributes)
|
||||
{
|
||||
log.info("Not implemented: WLToolkit.getPrintJob()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getScreenResolution() {
|
||||
log.info("Not implemented: WLToolkit.getScreenResolution()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new input method adapter descriptor for native input methods.
|
||||
*/
|
||||
@Override
|
||||
public InputMethodDescriptor getInputMethodAdapterDescriptor() {
|
||||
log.info("Not implemented: WLToolkit.getInputMethodAdapterDescriptor()");
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether enableInputMethods should be set to true for peered
|
||||
* TextComponent instances on this platform. True by default.
|
||||
*/
|
||||
@Override
|
||||
public boolean enableInputMethodsForTextComponent() {
|
||||
log.info("Not implemented: WLToolkit.enableInputMethodsForTextComponent()");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isFrameStateSupported(int state)
|
||||
throws HeadlessException
|
||||
{
|
||||
log.info("Not implemented: WLToolkit.isFrameStateSupported()");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initializeDesktopProperties() {
|
||||
log.info("Not implemented: WLToolkit.initializeDesktopProperties()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumberOfButtons(){
|
||||
log.info("Not implemented: WLToolkit.getNumberOfButtons()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object lazilyLoadDesktopProperty(String name) {
|
||||
log.info("Not implemented: WLToolkit.lazilyLoadDesktopProperty()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void addPropertyChangeListener(String name, PropertyChangeListener pcl) {
|
||||
log.info("Not implemented: WLToolkit.addPropertyChangeListener()");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see SunToolkit#needsXEmbedImpl
|
||||
*/
|
||||
@Override
|
||||
protected boolean needsXEmbedImpl() {
|
||||
log.info("Not implemented: WLToolkit.needsXEmbedImpl()");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModalityTypeSupported(Dialog.ModalityType modalityType) {
|
||||
log.info("Not implemented: WLToolkit.isModalityTypeSupported()");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModalExclusionTypeSupported(Dialog.ModalExclusionType exclusionType) {
|
||||
log.info("Not implemented: WLToolkit.isModalExclusionTypeSupported()");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlwaysOnTopSupported() {
|
||||
log.info("Not implemented: WLToolkit.isAlwaysOnTopSupported()");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useBufferPerWindow() {
|
||||
log.info("Not implemented: WLToolkit.useBufferPerWindow()");
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
protected boolean syncNativeQueue(long timeout) {
|
||||
log.info("Not implemented: WLToolkit.syncNativeQueue()");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void grab(Window w) {
|
||||
log.info("Not implemented: WLToolkit.grab()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ungrab(Window w) {
|
||||
log.info("Not implemented: WLToolkit.ungrab()");
|
||||
}
|
||||
/**
|
||||
* Returns if the java.awt.Desktop class is supported on the current
|
||||
* desktop.
|
||||
* <p>
|
||||
* The methods of java.awt.Desktop class are supported on the Gnome desktop.
|
||||
* Check if the running desktop is Gnome by checking the window manager.
|
||||
*/
|
||||
@Override
|
||||
public boolean isDesktopSupported(){
|
||||
log.info("Not implemented: WLToolkit.isDesktopSupported()");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DesktopPeer createDesktopPeer(Desktop target){
|
||||
log.info("Not implemented: WLToolkit.createDesktopPeer()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTaskbarSupported(){
|
||||
log.info("Not implemented: WLToolkit.isTaskbarSupported()");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskbarPeer createTaskbarPeer(Taskbar target){
|
||||
log.info("Not implemented: WLToolkit.createTaskbarPeer()");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areExtraMouseButtonsEnabled() throws HeadlessException {
|
||||
log.info("Not implemented: WLToolkit.areExtraMouseButtonsEnabled()");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWindowOpacitySupported() {
|
||||
log.info("Not implemented: WLToolkit.isWindowOpacitySupported()");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWindowShapingSupported() {
|
||||
log.info("Not implemented: WLToolkit.isWindowShapingSupported()");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWindowTranslucencySupported() {
|
||||
log.info("Not implemented: WLToolkit.isWindowTranslucencySupported()");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTranslucencyCapable(GraphicsConfiguration gc) {
|
||||
log.info("Not implemented: WLToolkit.isWindowTranslucencySupported()");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sync() {
|
||||
flushImpl();
|
||||
}
|
||||
|
||||
private native int readEvents();
|
||||
private native void dispatchEventsOnEDT();
|
||||
private native void flushImpl();
|
||||
private native void dispatchNonDefaultQueuesImpl();
|
||||
|
||||
protected static void targetDisposedPeer(Object target, Object peer) {
|
||||
SunToolkit.targetDisposedPeer(target, peer);
|
||||
}
|
||||
|
||||
static void postEvent(AWTEvent event) {
|
||||
SunToolkit.postEvent(AppContext.getAppContext(), event);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2022, 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
|
||||
@@ -28,10 +28,12 @@ package sun.java2d;
|
||||
|
||||
import java.awt.GraphicsConfiguration;
|
||||
|
||||
import sun.awt.X11GraphicsConfig;
|
||||
import sun.awt.image.SunVolatileImage;
|
||||
import sun.awt.image.VolatileSurfaceManager;
|
||||
import sun.java2d.opengl.GLXGraphicsConfig;
|
||||
import sun.java2d.opengl.GLXVolatileSurfaceManager;
|
||||
import sun.java2d.wl.WLVolatileSurfaceManager;
|
||||
import sun.java2d.x11.X11VolatileSurfaceManager;
|
||||
import sun.java2d.xr.*;
|
||||
|
||||
@@ -60,8 +62,10 @@ public class UnixSurfaceManagerFactory extends SurfaceManagerFactory {
|
||||
return new GLXVolatileSurfaceManager(vImg, context);
|
||||
} else if(gc instanceof XRGraphicsConfig) {
|
||||
return new XRVolatileSurfaceManager(vImg, context);
|
||||
}else {
|
||||
} else if (gc instanceof X11GraphicsConfig){
|
||||
return new X11VolatileSurfaceManager(vImg, context);
|
||||
} else {
|
||||
return new WLVolatileSurfaceManager(vImg, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
123
src/java.desktop/unix/classes/sun/java2d/wl/WLSurfaceData.java
Normal file
123
src/java.desktop/unix/classes/sun/java2d/wl/WLSurfaceData.java
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2022, JetBrains s.r.o.. 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.java2d.wl;
|
||||
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.Raster;
|
||||
import sun.awt.image.SunVolatileImage;
|
||||
import sun.awt.wl.WLComponentPeer;
|
||||
import sun.awt.wl.WLGraphicsConfig;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
public class WLSurfaceData extends SurfaceData {
|
||||
|
||||
private static final PlatformLogger log = PlatformLogger.getLogger("sun.java2d.wl.WLSurfaceData");
|
||||
private final WLComponentPeer peer;
|
||||
private final WLGraphicsConfig graphicsConfig;
|
||||
private final int depth;
|
||||
|
||||
|
||||
public native void initSurface(WLComponentPeer peer, int rgb, int width, int height);
|
||||
protected native void initOps(WLComponentPeer peer, WLGraphicsConfig gc, int depth);
|
||||
|
||||
protected WLSurfaceData(WLComponentPeer peer,
|
||||
WLGraphicsConfig gc,
|
||||
SurfaceType sType,
|
||||
ColorModel cm)
|
||||
{
|
||||
super(sType, cm);
|
||||
this.peer = peer;
|
||||
this.graphicsConfig = gc;
|
||||
this.depth = cm.getPixelSize();
|
||||
initOps(peer, graphicsConfig, depth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for instantiating a Window SurfaceData
|
||||
*/
|
||||
public static WLSurfaceData createData(WLComponentPeer peer) {
|
||||
WLGraphicsConfig gc = getGC(peer);
|
||||
return new WLSurfaceData(peer, gc, gc.getSurfaceType(), peer.getColorModel());
|
||||
}
|
||||
|
||||
|
||||
public static WLGraphicsConfig getGC(WLComponentPeer peer) {
|
||||
if (peer != null) {
|
||||
return (WLGraphicsConfig) peer.getGraphicsConfiguration();
|
||||
} else {
|
||||
GraphicsEnvironment env =
|
||||
GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
GraphicsDevice gd = env.getDefaultScreenDevice();
|
||||
return (WLGraphicsConfig)gd.getDefaultConfiguration();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public SurfaceData getReplacement() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsConfiguration getDeviceConfiguration() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Raster getRaster(int x, int y, int w, int h) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle getBounds() {
|
||||
Rectangle r = peer.getTarget().getBounds();
|
||||
r.x = r.y = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getDestination() {
|
||||
return peer.getTarget();
|
||||
}
|
||||
|
||||
public static boolean isAccelerationEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static SurfaceData createData(WLGraphicsConfig gc, int width, int height, ColorModel cm,
|
||||
SunVolatileImage vImg, long drawable, int opaque,
|
||||
boolean b) {
|
||||
log.info("Not implemented: WLSurfaceData.createData(WLGraphicsConfig,int,int,ColorModel," +
|
||||
"SunVolatileImage,long,int,boolean)");
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, JetBrains s.r.o.. 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.java2d.wl;
|
||||
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.ImageCapabilities;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.image.ColorModel;
|
||||
import sun.awt.wl.WLGraphicsConfig;
|
||||
import sun.awt.image.SunVolatileImage;
|
||||
import sun.awt.image.VolatileSurfaceManager;
|
||||
import sun.java2d.SurfaceData;
|
||||
|
||||
/**
|
||||
* X11 platform implementation of the VolatileSurfaceManager class.
|
||||
* The class attempts to create and use a pixmap-based SurfaceData
|
||||
* object (X11PixmapSurfaceData).
|
||||
* If this object cannot be created or re-created as necessary, the
|
||||
* class falls back to a system memory based SurfaceData object
|
||||
* (BufImgSurfaceData) that will be used until the accelerated
|
||||
* SurfaceData can be restored.
|
||||
*/
|
||||
public class WLVolatileSurfaceManager extends VolatileSurfaceManager {
|
||||
|
||||
private boolean accelerationEnabled;
|
||||
|
||||
public WLVolatileSurfaceManager(SunVolatileImage vImg, Object context) {
|
||||
super(vImg, context);
|
||||
|
||||
// We only accelerated opaque vImages currently
|
||||
accelerationEnabled = WLSurfaceData.isAccelerationEnabled() &&
|
||||
(vImg.getTransparency() == Transparency.OPAQUE);
|
||||
|
||||
if ((context != null) && !accelerationEnabled) {
|
||||
// if we're wrapping a backbuffer drawable, we must ensure that
|
||||
// the accelerated surface is initialized up front, regardless
|
||||
// of whether acceleration is enabled. But we need to set
|
||||
// the accelerationEnabled field to true to reflect that this
|
||||
// SM is actually accelerated.
|
||||
accelerationEnabled = true;
|
||||
sdAccel = initAcceleratedSurface();
|
||||
sdCurrent = sdAccel;
|
||||
|
||||
if (sdBackup != null) {
|
||||
// release the system memory backup surface, as we won't be
|
||||
// needing it in this case
|
||||
sdBackup = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isAccelerationEnabled() {
|
||||
return accelerationEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a pixmap-based SurfaceData object
|
||||
*/
|
||||
protected SurfaceData initAcceleratedSurface() {
|
||||
SurfaceData sData;
|
||||
|
||||
try {
|
||||
WLGraphicsConfig gc = (WLGraphicsConfig)vImg.getGraphicsConfig();
|
||||
ColorModel cm = gc.getColorModel();
|
||||
long drawable = 0;
|
||||
if (context instanceof Long) {
|
||||
drawable = ((Long)context).longValue();
|
||||
}
|
||||
sData = WLSurfaceData.createData(gc,
|
||||
vImg.getWidth(),
|
||||
vImg.getHeight(),
|
||||
cm, vImg, drawable,
|
||||
Transparency.OPAQUE,
|
||||
false);
|
||||
} catch (NullPointerException ex) {
|
||||
sData = null;
|
||||
} catch (OutOfMemoryError er) {
|
||||
sData = null;
|
||||
}
|
||||
|
||||
return sData;
|
||||
}
|
||||
|
||||
protected boolean isConfigValid(GraphicsConfiguration gc) {
|
||||
// REMIND: we might be too paranoid here, requiring that
|
||||
// the GC be exactly the same as the original one. The
|
||||
// real answer is one that guarantees that pixmap copies
|
||||
// will be correct (which requires like bit depths and
|
||||
// formats).
|
||||
return ((gc == null) || (gc == vImg.getGraphicsConfig()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Need to override the default behavior because Pixmaps-based
|
||||
* images are accelerated but not volatile.
|
||||
*/
|
||||
@Override
|
||||
public ImageCapabilities getCapabilities(GraphicsConfiguration gc) {
|
||||
if (isConfigValid(gc) && isAccelerationEnabled()) {
|
||||
// accelerated but not volatile
|
||||
return new ImageCapabilities(true);
|
||||
}
|
||||
// neither accelerated nor volatile
|
||||
return new ImageCapabilities(false);
|
||||
}
|
||||
}
|
||||
@@ -96,7 +96,7 @@ typedef struct {
|
||||
int num;
|
||||
} fDirRecord, *fDirRecordPtr;
|
||||
|
||||
#ifndef HEADLESS
|
||||
#ifdef XAWT
|
||||
|
||||
/*
|
||||
* Returns True if display is local, False of it's remote.
|
||||
@@ -194,7 +194,7 @@ static char **getX11FontPath ()
|
||||
}
|
||||
|
||||
|
||||
#endif /* !HEADLESS */
|
||||
#endif /* XAWT */
|
||||
|
||||
#if defined(__linux__)
|
||||
/* from awt_LoadLibrary.c */
|
||||
@@ -334,7 +334,7 @@ static char *getPlatformFontPathChars(JNIEnv *env, jboolean noType1, jboolean is
|
||||
* this code could throw an exception and the fontpath would fail to
|
||||
* be initialised.
|
||||
*/
|
||||
#ifndef HEADLESS
|
||||
#ifdef XAWT
|
||||
if (isX11) { // The following only works in an x11 environment.
|
||||
#if defined(__linux__)
|
||||
/* There's no headless build on linux ... */
|
||||
@@ -356,7 +356,7 @@ static char *getPlatformFontPathChars(JNIEnv *env, jboolean noType1, jboolean is
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif /* !HEADLESS */
|
||||
#endif /* XAWT */
|
||||
path = mergePaths(fcdirs, x11dirs, knowndirs, noType1);
|
||||
if (fcdirs != NULL) {
|
||||
char **p = fcdirs;
|
||||
|
||||
289
src/java.desktop/unix/native/common/java2d/wl/WLSurfaceData.c
Normal file
289
src/java.desktop/unix/native/common/java2d/wl/WLSurfaceData.c
Normal file
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, JetBrains s.r.o.. 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 <wayland-client.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <pthread.h>
|
||||
#include <jni.h>
|
||||
#include "jni_util.h"
|
||||
#include "Trace.h"
|
||||
#include "WLSurfaceData.h"
|
||||
extern struct wl_shm *wl_shm;
|
||||
//#undef HEADLESS
|
||||
void logWSDOp(char* str, void* p, jint lockFlags) {
|
||||
J2dTrace2(J2D_TRACE_INFO, "%s: %p, ", str, p);
|
||||
J2dTrace7(J2D_TRACE_INFO, "[%c%c%c%c%c%c%c]",
|
||||
(lockFlags&SD_LOCK_READ) ? 'R' : '.',
|
||||
(lockFlags&SD_LOCK_WRITE) ? 'W' : '.',
|
||||
(lockFlags&SD_LOCK_LUT) ? 'L' : '.',
|
||||
(lockFlags&SD_LOCK_INVCOLOR) ? 'C' : '.',
|
||||
(lockFlags&SD_LOCK_INVGRAY) ? 'G' : '.',
|
||||
(lockFlags&SD_LOCK_FASTEST) ? 'F' : '.',
|
||||
(lockFlags&SD_LOCK_PARTIAL) ? 'P' : '.');
|
||||
J2dTrace(J2D_TRACE_INFO, "\n");
|
||||
}
|
||||
|
||||
typedef struct _WLSDPrivate {
|
||||
jint lockFlags;
|
||||
struct wl_buffer* wlBuffer;
|
||||
} WLSDPrivate;
|
||||
|
||||
JNIEXPORT WLSDOps * JNICALL
|
||||
WLSurfaceData_GetOps(JNIEnv *env, jobject sData)
|
||||
{
|
||||
#ifdef HEADLESS
|
||||
return NULL;
|
||||
#else
|
||||
SurfaceDataOps *ops = SurfaceData_GetOps(env, sData);
|
||||
if (ops == NULL) {
|
||||
SurfaceData_ThrowInvalidPipeException(env, "not an valid WLSurfaceData");
|
||||
}
|
||||
return (WLSDOps *) ops;
|
||||
#endif /* !HEADLESS */
|
||||
}
|
||||
#ifndef HEADLESS
|
||||
static void
|
||||
wl_buffer_release(void *data, struct wl_buffer *wl_buffer) {
|
||||
/* Sent by the compositor when it's no longer using this buffer */
|
||||
wl_buffer_destroy(wl_buffer);
|
||||
}
|
||||
|
||||
static const struct wl_buffer_listener wl_buffer_listener = {
|
||||
.release = wl_buffer_release,
|
||||
};
|
||||
|
||||
|
||||
/* Shared memory support code (from https://wayland-book.com/) */
|
||||
static void randname(char *buf) {
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
long r = ts.tv_nsec;
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
buf[i] = 'A' + (r & 15) + (r & 16) * 2;
|
||||
r >>= 5;
|
||||
}
|
||||
}
|
||||
|
||||
static int create_shm_file() {
|
||||
int retries = 100;
|
||||
do {
|
||||
char name[] = "/wl_shm-XXXXXX";
|
||||
randname(name + sizeof(name) - 7);
|
||||
--retries;
|
||||
int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
|
||||
if (fd >= 0) {
|
||||
shm_unlink(name);
|
||||
return fd;
|
||||
}
|
||||
} while (retries > 0 && errno == EEXIST);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int allocate_shm_file(size_t size) {
|
||||
int fd = create_shm_file();
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
int ret;
|
||||
do {
|
||||
ret = ftruncate(fd, size);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
if (ret < 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Class: sun_java2d_wl_WLSurfaceData
|
||||
* Method: initSurface
|
||||
* Signature: (IIIJ)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_java2d_wl_WLSurfaceData_initSurface(JNIEnv *env, jobject wsd,
|
||||
jobject peer,
|
||||
jint rgb,
|
||||
jint width, jint height)
|
||||
{
|
||||
#ifndef HEADLESS
|
||||
J2dTrace6(J2D_TRACE_INFO, "WLSurfaceData_initSurface: %dx%d, rgba=(%d,%d,%d,%d)\n",
|
||||
width, height, rgb&0xff, (rgb>>8)&0xff, (rgb>>16)&0xff, (rgb>>24)&0xff);
|
||||
WLSDOps *wsdo = (WLSDOps*)SurfaceData_GetOps(env, wsd);
|
||||
if (wsdo == NULL) {
|
||||
return;
|
||||
}
|
||||
jboolean hasException;
|
||||
if (!wsdo->wlSurface) {
|
||||
wsdo->wlSurface = JNU_CallMethodByName(env, &hasException, peer, "getWLSurface", "()J").j;
|
||||
}
|
||||
if (width <= 0) {
|
||||
width = 1;
|
||||
}
|
||||
if (height <= 0) {
|
||||
height = 1;
|
||||
}
|
||||
int stride = width * 4;
|
||||
int size = stride * height;
|
||||
|
||||
wsdo->fd = allocate_shm_file(size);
|
||||
if (wsdo->fd == -1) {
|
||||
return;
|
||||
}
|
||||
wsdo->data = (uint32_t *) (mmap(NULL, size,
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED, wsdo->fd, 0));
|
||||
if (wsdo->data == MAP_FAILED) {
|
||||
close(wsdo->fd);
|
||||
return;
|
||||
}
|
||||
|
||||
wsdo->dataSize = size;
|
||||
wsdo->width = width;
|
||||
wsdo->height = height;
|
||||
|
||||
for (int i = 0; i < height*width; ++i) {
|
||||
wsdo->data[i] = rgb;
|
||||
}
|
||||
|
||||
wsdo->wlShmPool = (jlong)wl_shm_create_pool(wl_shm, wsdo->fd, size);
|
||||
wsdo->wlBuffer = (jlong) wl_shm_pool_create_buffer(
|
||||
(struct wl_shm_pool*)wsdo->wlShmPool, 0, width, height, stride, WL_SHM_FORMAT_XRGB8888);
|
||||
|
||||
wl_surface_attach((struct wl_surface*)wsdo->wlSurface, (struct wl_buffer*)wsdo->wlBuffer, 0, 0);
|
||||
wl_surface_commit((struct wl_surface*)wsdo->wlSurface);
|
||||
#endif /* !HEADLESS */
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the implementation of the general surface LockFunc defined in
|
||||
* SurfaceData.h.
|
||||
*/
|
||||
jint
|
||||
WLSD_Lock(JNIEnv *env,
|
||||
SurfaceDataOps *ops,
|
||||
SurfaceDataRasInfo *pRasInfo,
|
||||
jint lockflags)
|
||||
{
|
||||
#ifndef HEADLESS
|
||||
WLSDOps *wlso = (WLSDOps*)ops;
|
||||
logWSDOp("WLSD_Lock", wlso, lockflags);
|
||||
pthread_mutex_lock(&wlso->lock);
|
||||
WLSDPrivate *priv = (WLSDPrivate *) &(pRasInfo->priv);
|
||||
priv->lockFlags = lockflags;
|
||||
|
||||
if (priv->lockFlags & SD_LOCK_WRITE) {
|
||||
pRasInfo->rasBase = wlso->data;
|
||||
pRasInfo->pixelStride = 4;
|
||||
pRasInfo->pixelBitOffset = 0;
|
||||
pRasInfo->scanStride = 4 * wlso->width;
|
||||
}
|
||||
#endif
|
||||
return SD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static void WLSD_GetRasInfo(JNIEnv *env,
|
||||
SurfaceDataOps *ops,
|
||||
SurfaceDataRasInfo *pRasInfo)
|
||||
{
|
||||
#ifndef HEADLESS
|
||||
WLSDPrivate *priv = (WLSDPrivate *) &(pRasInfo->priv);
|
||||
WLSDOps *wlso = (WLSDOps*)ops;
|
||||
logWSDOp("WLSD_GetRasInfo", wlso, priv->lockFlags);
|
||||
if (priv->lockFlags & SD_LOCK_WRITE) {
|
||||
wl_surface_damage ((struct wl_surface*)wlso->wlSurface, pRasInfo->bounds.x1, pRasInfo->bounds.y1,
|
||||
pRasInfo->bounds.x2 - pRasInfo->bounds.x1, pRasInfo->bounds.y2 - pRasInfo->bounds.y1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void WLSD_Unlock(JNIEnv *env,
|
||||
SurfaceDataOps *ops,
|
||||
SurfaceDataRasInfo *pRasInfo)
|
||||
{
|
||||
#ifndef HEADLESS
|
||||
WLSDOps *wsdo = (WLSDOps*)ops;
|
||||
J2dTrace1(J2D_TRACE_INFO, "WLSD_Unlock: %p\n", wsdo);
|
||||
wl_surface_commit((struct wl_surface*)wsdo->wlSurface);
|
||||
pthread_mutex_unlock(&wsdo->lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void WLSD_Dispose(JNIEnv *env, SurfaceDataOps *ops)
|
||||
{
|
||||
#ifndef HEADLESS
|
||||
/* ops is assumed non-null as it is checked in SurfaceData_DisposeOps */
|
||||
J2dTrace1(J2D_TRACE_INFO, "WLSD_Dispose %p\n", ops);
|
||||
WLSDOps *wsdo = (WLSDOps*)ops;
|
||||
if (wsdo->wlSurface != 0) {
|
||||
close(wsdo->fd);
|
||||
wsdo->fd = 0;
|
||||
munmap(wsdo->data, wsdo->dataSize);
|
||||
wl_shm_pool_destroy((struct wl_shm_pool *) wsdo->wlShmPool);
|
||||
wl_buffer_add_listener((struct wl_buffer *) wsdo->wlBuffer, &wl_buffer_listener, NULL);
|
||||
} else {
|
||||
J2dTrace(J2D_TRACE_INFO, "WLSD_Dispose: wlSurface == 0\n");
|
||||
}
|
||||
pthread_mutex_destroy(&wsdo->lock);
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Class: sun_java2d_wl_WLSurfaceData
|
||||
* Method: initOps
|
||||
* Signature: (Ljava/lang/Object;Ljava/lang/Object;I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_java2d_wl_WLSurfaceData_initOps(JNIEnv *env, jobject wsd,
|
||||
jobject peer,
|
||||
jobject graphicsConfig, jint depth)
|
||||
{
|
||||
#ifndef HEADLESS
|
||||
|
||||
WLSDOps *wsdo = (WLSDOps*)SurfaceData_InitOps(env, wsd, sizeof(WLSDOps));
|
||||
J2dTrace1(J2D_TRACE_INFO, "WLSurfaceData_initOps: %p\n", wsdo);
|
||||
jboolean hasException;
|
||||
if (wsdo == NULL) {
|
||||
JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
|
||||
return;
|
||||
}
|
||||
wsdo->sdOps.Lock = WLSD_Lock;
|
||||
wsdo->sdOps.Unlock = WLSD_Unlock;
|
||||
wsdo->sdOps.GetRasInfo = WLSD_GetRasInfo;
|
||||
wsdo->sdOps.Dispose = WLSD_Dispose;
|
||||
|
||||
wsdo->wlSurface = 0;
|
||||
wsdo->bgPixel = 0;
|
||||
wsdo->isBgInitialized = JNI_FALSE;
|
||||
pthread_mutex_init(&wsdo->lock, NULL);
|
||||
|
||||
#endif /* !HEADLESS */
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, JetBrains s.r.o.. 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 "SurfaceData.h"
|
||||
|
||||
typedef struct _WLSDOps WLSDOps;
|
||||
|
||||
struct _WLSDOps {
|
||||
SurfaceDataOps sdOps;
|
||||
jboolean invalid;
|
||||
jobject peer;
|
||||
jlong wlSurface;
|
||||
jlong wlBuffer;
|
||||
jlong wlShmPool;
|
||||
int fd;
|
||||
uint32_t *data;
|
||||
jint dataSize;
|
||||
jint width;
|
||||
jint height;
|
||||
jint bgPixel;
|
||||
jint pixelStride;
|
||||
pthread_mutex_t lock;
|
||||
jboolean isBgInitialized;
|
||||
};
|
||||
|
||||
/*
|
||||
* This function returns a pointer to a native WLSDOps structure
|
||||
* for accessing the indicated WL SurfaceData Java object. It
|
||||
* verifies that the indicated SurfaceData object is an instance
|
||||
* of WLSurfaceData before returning and will return NULL if the
|
||||
* wrong SurfaceData object is being accessed. This function will
|
||||
* throw the appropriate Java exception if it returns NULL so that
|
||||
* the caller can simply return.
|
||||
*
|
||||
* Note to callers:
|
||||
* This function uses JNI methods so it is important that the
|
||||
* caller not have any outstanding GetPrimitiveArrayCritical or
|
||||
* GetStringCritical locks which have not been released.
|
||||
*
|
||||
* The caller may continue to use JNI methods after this method
|
||||
* is called since this function will not leave any outstanding
|
||||
* JNI Critical locks unreleased.
|
||||
*/
|
||||
JNIEXPORT WLSDOps * JNICALL
|
||||
WLSurfaceData_GetOps(JNIEnv *env, jobject sData);
|
||||
@@ -31,7 +31,7 @@
|
||||
#include <jni_util.h>
|
||||
#include <jvm.h>
|
||||
#include "gdefs.h"
|
||||
|
||||
#include "sun_awt_PlatformGraphicsInfo.h"
|
||||
#include <sys/param.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
@@ -79,6 +79,34 @@ JNIEXPORT jboolean JNICALL AWTIsHeadless() {
|
||||
return isHeadless;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL AWTGetToolkitID() {
|
||||
static JNIEnv *env = NULL;
|
||||
static jint toolkitID;
|
||||
jmethodID toolkitIDFn;
|
||||
jclass platformGraphicsInfoClass;
|
||||
|
||||
if (env == NULL) {
|
||||
env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
|
||||
platformGraphicsInfoClass = (*env)->FindClass(env,
|
||||
"sun/awt/PlatformGraphicsInfo");
|
||||
if (platformGraphicsInfoClass == NULL) {
|
||||
return 0;
|
||||
}
|
||||
toolkitIDFn = (*env)->GetStaticMethodID(env,
|
||||
platformGraphicsInfoClass, "getToolkitID", "()I");
|
||||
if (toolkitIDFn == NULL) {
|
||||
return 0;
|
||||
}
|
||||
toolkitID = (*env)->CallStaticBooleanMethod(env, platformGraphicsInfoClass,
|
||||
toolkitIDFn);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
(*env)->ExceptionClear(env);
|
||||
return JNI_TRUE;
|
||||
}
|
||||
}
|
||||
return toolkitID;
|
||||
}
|
||||
|
||||
#define CHECK_EXCEPTION_FATAL(env, message) \
|
||||
if ((*env)->ExceptionCheck(env)) { \
|
||||
(*env)->ExceptionClear(env); \
|
||||
@@ -94,6 +122,7 @@ JNIEXPORT jboolean JNICALL AWTIsHeadless() {
|
||||
#define DEFAULT_PATH LWAWT_PATH
|
||||
#else
|
||||
#define XAWT_PATH "/libawt_xawt.so"
|
||||
#define WLAWT_PATH "/libawt_wlawt.so"
|
||||
#define DEFAULT_PATH XAWT_PATH
|
||||
#define HEADLESS_PATH "/libawt_headless.so"
|
||||
#endif
|
||||
@@ -109,6 +138,7 @@ AWT_OnLoad(JavaVM *vm, void *reserved)
|
||||
struct utsname name;
|
||||
JNIEnv *env = (JNIEnv *)JNU_GetEnv(vm, JNI_VERSION_1_2);
|
||||
void *v;
|
||||
jint tkID = 0;
|
||||
|
||||
if (awtHandle != NULL) {
|
||||
/* Avoid several loading attempts */
|
||||
@@ -128,10 +158,16 @@ AWT_OnLoad(JavaVM *vm, void *reserved)
|
||||
* loading appropriate awt library, i.e. libawt_xawt or libawt_headless
|
||||
*/
|
||||
|
||||
tkID = AWTGetToolkitID();
|
||||
|
||||
#ifdef MACOSX
|
||||
tk = LWAWT_PATH;
|
||||
#else
|
||||
tk = XAWT_PATH;
|
||||
if (tkID == sun_awt_PlatformGraphicsInfo_TK_WAYLAND) {
|
||||
tk = WLAWT_PATH;
|
||||
} else {
|
||||
tk = XAWT_PATH;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef MACOSX
|
||||
|
||||
207
src/java.desktop/unix/native/libawt_wlawt/WLComponentPeer.c
Normal file
207
src/java.desktop/unix/native/libawt_wlawt/WLComponentPeer.c
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (c) 2021, JetBrains s.r.o.. 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <jni.h>
|
||||
#include <Trace.h>
|
||||
|
||||
#include "jni_util.h"
|
||||
#include "WLToolkit.h"
|
||||
#include "WLRobotPeer.h"
|
||||
|
||||
#ifdef WAKEFIELD_ROBOT
|
||||
#include "wakefield-client-protocol.h"
|
||||
#endif
|
||||
|
||||
jfieldID nativePtrID;
|
||||
|
||||
struct WLFrame {
|
||||
jobject nativeFramePeer; // weak reference
|
||||
struct wl_surface *wl_surface;
|
||||
struct xdg_surface *xdg_surface;
|
||||
struct WLFrame *parent;
|
||||
struct xdg_positioner *xdg_positioner;
|
||||
jboolean toplevel;
|
||||
union {
|
||||
struct xdg_toplevel *xdg_toplevel;
|
||||
struct xdg_popup *xdg_popup;
|
||||
};
|
||||
};
|
||||
|
||||
static void xdg_surface_configure(void *data,
|
||||
struct xdg_surface *xdg_surface, uint32_t serial) {
|
||||
xdg_surface_ack_configure(xdg_surface, serial);
|
||||
}
|
||||
|
||||
static const struct xdg_surface_listener xdg_surface_listener = {
|
||||
.configure = xdg_surface_configure,
|
||||
};
|
||||
|
||||
static void xdg_toplevel_configure(void *data,
|
||||
struct xdg_toplevel *xdg_toplevel,
|
||||
int32_t width,
|
||||
int32_t height,
|
||||
struct wl_array *states) {
|
||||
J2dTrace3(J2D_TRACE_INFO, "WLComponentPeer: xdg_toplevel_configure(%p, %d, %d)\n", xdg_toplevel, width, height);
|
||||
}
|
||||
|
||||
static void xdg_popup_configure(void *data,
|
||||
struct xdg_popup *xdg_popup,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
int32_t width,
|
||||
int32_t height) {
|
||||
J2dTrace5(J2D_TRACE_INFO, "WLComponentPeer: xdg_popup_configure(%p, %d, %d, %d, %d)\n",
|
||||
xdg_popup, x, y, width, height);
|
||||
}
|
||||
|
||||
static void xdg_toplevel_close(void *data,
|
||||
struct xdg_toplevel *xdg_toplevel) {
|
||||
struct WLFrame *frame = (struct WLFrame *) data;
|
||||
JNIEnv *env = getEnv();
|
||||
jobject nativeFramePeer = (*env)->NewLocalRef(env, frame->nativeFramePeer);
|
||||
if (nativeFramePeer) {
|
||||
static jclass wlFramePeerCID = NULL;
|
||||
if (!wlFramePeerCID) {
|
||||
wlFramePeerCID = (*env)->FindClass(env, "sun/awt/wl/WLFramePeer");
|
||||
}
|
||||
static jmethodID postWindowClosingMID = NULL;
|
||||
if (!postWindowClosingMID) {
|
||||
postWindowClosingMID = (*env)->GetMethodID(env, wlFramePeerCID, "postWindowClosing", "()V");
|
||||
}
|
||||
(*env)->CallVoidMethod(env, nativeFramePeer, postWindowClosingMID);
|
||||
(*env)->DeleteLocalRef(env, nativeFramePeer);
|
||||
}
|
||||
}
|
||||
|
||||
static void xdg_popup_done(void *data,
|
||||
struct xdg_popup *xdg_popup) {
|
||||
J2dTrace1(J2D_TRACE_INFO, "WLComponentPeer: xdg_popup_done(%p)\n", xdg_popup);
|
||||
}
|
||||
|
||||
static const struct xdg_toplevel_listener xdg_toplevel_listener = {
|
||||
.configure = xdg_toplevel_configure,
|
||||
.close = xdg_toplevel_close,
|
||||
};
|
||||
|
||||
static const struct xdg_popup_listener xdg_popup_listener = {
|
||||
.configure = xdg_popup_configure,
|
||||
.popup_done = xdg_popup_done,
|
||||
};
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_awt_wl_WLComponentPeer_initIDs
|
||||
(JNIEnv *env, jclass clazz)
|
||||
{
|
||||
CHECK_NULL(nativePtrID = (*env)->GetFieldID(env, clazz, "nativePtr", "J"));
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_sun_awt_wl_WLComponentPeer_nativeCreateFrame
|
||||
(JNIEnv *env, jobject obj)
|
||||
{
|
||||
struct WLFrame *frame = (struct WLFrame *) malloc(sizeof(struct WLFrame));
|
||||
frame->nativeFramePeer = (*env)->NewWeakGlobalRef(env, obj);
|
||||
frame->wl_surface = NULL;
|
||||
frame->xdg_surface = NULL;
|
||||
frame->toplevel = JNI_FALSE;
|
||||
frame->xdg_popup = NULL;
|
||||
return (jlong)frame;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_awt_wl_WLComponentPeer_nativeShowComponent
|
||||
(JNIEnv *env, jobject obj, jlong ptr, jlong parentPtr, jint x, jint y)
|
||||
{
|
||||
struct WLFrame *frame = (struct WLFrame *) ptr;
|
||||
struct WLFrame *parentFrame = (struct WLFrame*) parentPtr;
|
||||
if (frame->wl_surface) return;
|
||||
frame->wl_surface = wl_compositor_create_surface(wl_compositor);
|
||||
frame->xdg_surface = xdg_wm_base_get_xdg_surface(xdg_wm_base, frame->wl_surface);
|
||||
|
||||
xdg_surface_add_listener(frame->xdg_surface, &xdg_surface_listener, NULL);
|
||||
frame->toplevel = parentFrame == NULL;
|
||||
if (frame->toplevel) {
|
||||
frame->xdg_toplevel = xdg_surface_get_toplevel(frame->xdg_surface);
|
||||
xdg_toplevel_add_listener(frame->xdg_toplevel, &xdg_toplevel_listener, frame);
|
||||
} else {
|
||||
struct xdg_positioner *xdg_positioner =
|
||||
xdg_wm_base_create_positioner(xdg_wm_base);
|
||||
xdg_positioner_set_offset(xdg_positioner, x, y);
|
||||
frame->xdg_popup = xdg_surface_get_popup(frame->xdg_surface, parentFrame->xdg_surface, xdg_positioner);
|
||||
xdg_popup_add_listener(frame->xdg_popup, &xdg_popup_listener, frame);
|
||||
}
|
||||
|
||||
wl_surface_commit(frame->wl_surface);
|
||||
wl_display_roundtrip(wl_display); // this should process 'configure' event, and send 'ack_configure' in response
|
||||
#ifdef WAKEFIELD_ROBOT
|
||||
if (wakefield) {
|
||||
// TODO: this doesn't work quite as expected for some reason
|
||||
wakefield_move_surface(wakefield, frame->wl_surface, x, y);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void doHide(struct WLFrame *frame) {
|
||||
if (frame->wl_surface) {
|
||||
if(frame->toplevel) {
|
||||
xdg_toplevel_destroy(frame->xdg_toplevel);
|
||||
} else {
|
||||
xdg_popup_destroy(frame->xdg_popup);
|
||||
}
|
||||
xdg_surface_destroy(frame->xdg_surface);
|
||||
wl_surface_destroy(frame->wl_surface);
|
||||
frame->wl_surface = NULL;
|
||||
frame->xdg_surface = NULL;
|
||||
frame->xdg_toplevel = NULL;
|
||||
frame->xdg_popup = NULL;
|
||||
frame->toplevel = JNI_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_awt_wl_WLComponentPeer_nativeHideFrame
|
||||
(JNIEnv *env, jobject obj, jlong ptr)
|
||||
{
|
||||
struct WLFrame *frame = (struct WLFrame *) ptr;
|
||||
doHide(frame);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_awt_wl_WLComponentPeer_nativeDisposeFrame
|
||||
(JNIEnv *env, jobject obj, jlong ptr)
|
||||
{
|
||||
struct WLFrame *frame = (struct WLFrame *) ptr;
|
||||
doHide(frame);
|
||||
(*env)->DeleteWeakGlobalRef(env, frame->nativeFramePeer);
|
||||
free(frame);
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_sun_awt_wl_WLComponentPeer_getWLSurface
|
||||
(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return (jlong)((struct WLFrame*)(*env)->GetLongField(env, obj, nativePtrID))->wl_surface;
|
||||
}
|
||||
471
src/java.desktop/unix/native/libawt_wlawt/WLRobotPeer.c
Normal file
471
src/java.desktop/unix/native/libawt_wlawt/WLRobotPeer.c
Normal file
@@ -0,0 +1,471 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, JetBrains s.r.o.. 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 <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <Trace.h>
|
||||
#include <jni_util.h>
|
||||
|
||||
#include "sun_awt_wl_WLRobotPeer.h"
|
||||
#include "WLToolkit.h"
|
||||
|
||||
#include "wakefield-client-protocol.h"
|
||||
|
||||
#ifdef WAKEFIELD_ROBOT
|
||||
struct wakefield *wakefield;
|
||||
struct wl_event_queue *robot_queue;
|
||||
#endif
|
||||
|
||||
#ifndef HEADLESS
|
||||
static struct wl_buffer*
|
||||
allocate_buffer(JNIEnv *env, int width, int height, uint32_t **buffer_data, int* size);
|
||||
#endif
|
||||
|
||||
#ifdef WAKEFIELD_ROBOT
|
||||
// These structs are used to transfer data between the thread that made the request
|
||||
// and the thread where the event handler was invoked in a race-free manner.
|
||||
struct pixel_color_request_t {
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
|
||||
bool is_data_available;
|
||||
uint32_t error_code;
|
||||
|
||||
uint32_t rgb;
|
||||
} pixel_color_request;
|
||||
|
||||
struct screen_capture_request_t {
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
|
||||
bool is_data_available;
|
||||
uint32_t error_code;
|
||||
} screen_capture_request;
|
||||
|
||||
struct surface_location_request_t {
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
|
||||
bool is_data_available;
|
||||
uint32_t error_code;
|
||||
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
} surface_location_request;
|
||||
|
||||
#define WAKEFIELD_REQUEST_INIT(r) (r).is_data_available = false
|
||||
|
||||
#define WAKEFIELD_REQUEST_WAIT_START(r) pthread_mutex_lock(&(r).mutex); \
|
||||
while (!(r).is_data_available) { \
|
||||
pthread_cond_wait(&(r).cond, &(r).mutex);\
|
||||
}
|
||||
|
||||
#define WAKEFIELD_REQUEST_WAIT_END(r) pthread_mutex_unlock(&(r).mutex)
|
||||
|
||||
#define WAKEFIELD_EVENT_NOTIFY_START(r) pthread_mutex_lock(&(r).mutex)
|
||||
|
||||
#define WAKEFIELD_EVENT_NOTIFY_END(r) (r).is_data_available = true; \
|
||||
pthread_cond_broadcast(&(r).cond); \
|
||||
pthread_mutex_unlock(&(r).mutex)
|
||||
|
||||
static int
|
||||
init_mutex_and_cond(JNIEnv *env, pthread_mutex_t *mutex, pthread_cond_t *cond)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
rc = pthread_mutex_init(mutex, NULL);
|
||||
if (rc != 0) {
|
||||
JNU_ThrowInternalError(env, "pthread_mutex_init() failed");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = pthread_cond_init(cond, NULL);
|
||||
if (rc != 0) {
|
||||
JNU_ThrowInternalError(env, "pthread_cond_init() failed");
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_wakefield_error(JNIEnv *env, uint32_t error_code);
|
||||
#endif
|
||||
|
||||
static jclass pointClass; // java.awt.Point
|
||||
static jmethodID pointClassConstrMID; // java.awt.Point(int, int)
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_awt_wl_WLRobotPeer_initIDs(JNIEnv *env, jclass clazz)
|
||||
{
|
||||
#ifdef WAKEFIELD_ROBOT
|
||||
int rc = init_mutex_and_cond(env, &pixel_color_request.mutex, &pixel_color_request.cond);
|
||||
if (rc != 0) return;
|
||||
|
||||
rc = init_mutex_and_cond(env, &screen_capture_request.mutex, &screen_capture_request.cond);
|
||||
if (rc != 0) return;
|
||||
|
||||
rc = init_mutex_and_cond(env, &surface_location_request.mutex, &surface_location_request.cond);
|
||||
if (rc != 0) return;
|
||||
#endif
|
||||
|
||||
const jclass pointClassLocal = (*env)->FindClass(env, "java/awt/Point");
|
||||
if (pointClassLocal == NULL) {
|
||||
JNU_ThrowInternalError(env, "cannot find class java.awt.Point");
|
||||
return;
|
||||
}
|
||||
pointClass = (*env)->NewGlobalRef(env, pointClassLocal); // never free'ed
|
||||
|
||||
pointClassConstrMID = (*env)->GetMethodID(env, pointClass, "<init>", "(II)V");
|
||||
if (pointClassConstrMID == NULL) {
|
||||
JNU_ThrowInternalError(env, "cannot find java.awt.Point(int, int)");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_awt_wl_WLRobotPeer_isRobotExtensionPresentImpl(JNIEnv *env, jclass clazz)
|
||||
{
|
||||
if (!wl_display) {
|
||||
J2dTrace(J2D_TRACE_ERROR, "WLRobotPeer: isRobotExtensionPresent can't work without a Wayland display\n");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
#ifdef WAKEFIELD_ROBOT
|
||||
return (wakefield != NULL);
|
||||
#else
|
||||
J2dTrace(J2D_TRACE_ERROR, "WLToolkit: robot extension was not enabled at build time \n");
|
||||
return JNI_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_awt_wl_WLRobotPeer_getRGBPixelImpl(JNIEnv *env, jclass clazz, jint x, jint y)
|
||||
{
|
||||
#ifdef WAKEFIELD_ROBOT
|
||||
if (!wakefield) {
|
||||
JNU_ThrowByName(env, "java/awt/AWTError", "no 'wakefield' protocol extension");
|
||||
return 0;
|
||||
}
|
||||
|
||||
WAKEFIELD_REQUEST_INIT(pixel_color_request);
|
||||
|
||||
wakefield_get_pixel_color(wakefield, x, y);
|
||||
wl_flush_to_server(env); // the event will be delivered on a dedicated thread, see wakefield_pixel_color()
|
||||
|
||||
WAKEFIELD_REQUEST_WAIT_START(pixel_color_request);
|
||||
const uint32_t error_code = pixel_color_request.error_code;
|
||||
const uint32_t rgb = pixel_color_request.rgb;
|
||||
WAKEFIELD_REQUEST_WAIT_END(pixel_color_request);
|
||||
|
||||
if (error_code != WAKEFIELD_ERROR_NO_ERROR) {
|
||||
handle_wakefield_error(env, error_code);
|
||||
return 0;
|
||||
} else {
|
||||
return (jint)rgb;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_sun_awt_wl_WLRobotPeer_getLocationOfWLSurfaceImpl
|
||||
(JNIEnv *env, jclass clazz, jlong wlSurfacePtr)
|
||||
{
|
||||
#ifdef WAKEFIELD_ROBOT
|
||||
if (!wakefield) {
|
||||
JNU_ThrowByName(env, "java/awt/AWTError", "no 'wakefield' protocol extension");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
WAKEFIELD_REQUEST_INIT(surface_location_request);
|
||||
|
||||
struct wl_surface * const surface = (struct wl_surface*) wlSurfacePtr;
|
||||
wakefield_get_surface_location(wakefield, surface);
|
||||
wl_flush_to_server(env); // the event will be delivered on a dedicated thread, see wakefield_surface_location()
|
||||
|
||||
WAKEFIELD_REQUEST_WAIT_START(surface_location_request);
|
||||
const uint32_t error_code = surface_location_request.error_code;
|
||||
const int32_t x = surface_location_request.x;
|
||||
const int32_t y = surface_location_request.y;
|
||||
WAKEFIELD_REQUEST_WAIT_END(surface_location_request);
|
||||
|
||||
if (error_code != WAKEFIELD_ERROR_NO_ERROR) {
|
||||
handle_wakefield_error(env, error_code);
|
||||
return NULL;
|
||||
} else {
|
||||
return (*env)->NewObject(env, pointClass, pointClassConstrMID, x, y);
|
||||
}
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_awt_wl_WLRobotPeer_setLocationOfWLSurfaceImpl
|
||||
(JNIEnv *env, jclass clazz, jlong wlSurfacePtr, jint x, jint y)
|
||||
{
|
||||
#ifdef WAKEFIELD_ROBOT
|
||||
if (!wakefield) {
|
||||
JNU_ThrowByName(env, "java/awt/AWTError", "no 'wakefield' protocol extension");
|
||||
return;
|
||||
}
|
||||
|
||||
J2dTrace2(J2D_TRACE_INFO, "WLRobotPeer: sending move_surface request to wakefield %d, %d\n",
|
||||
x, y);
|
||||
|
||||
struct wl_surface * const surface = (struct wl_surface*) wlSurfacePtr;
|
||||
if (!surface) {
|
||||
J2dTrace(J2D_TRACE_INFO, "WLRobotPeer: unable to set location for NULL surface\n");
|
||||
return;
|
||||
}
|
||||
|
||||
wakefield_move_surface(wakefield, surface, x, y);
|
||||
wl_surface_commit(surface);
|
||||
wl_flush_to_server(env);
|
||||
#endif
|
||||
}
|
||||
|
||||
JNIEXPORT jintArray JNICALL
|
||||
Java_sun_awt_wl_WLRobotPeer_getRGBPixelsImpl
|
||||
(JNIEnv *env, jclass clazz, jint x, jint y, jint width, jint height)
|
||||
{
|
||||
#ifdef WAKEFIELD_ROBOT
|
||||
if (!wakefield) {
|
||||
JNU_ThrowByName(env, "java/awt/AWTError", "no 'wakefield' protocol extension");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t *buffer_data;
|
||||
int buffer_size_in_bytes;
|
||||
struct wl_buffer *buffer = allocate_buffer(env, width, height, &buffer_data, &buffer_size_in_bytes);
|
||||
if (!buffer) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
WAKEFIELD_REQUEST_INIT(screen_capture_request);
|
||||
|
||||
wakefield_capture_create(wakefield, buffer, x, y);
|
||||
wl_display_flush(wl_display); // event will be delivered on EDT, see wakefield_capture_ready()
|
||||
|
||||
WAKEFIELD_REQUEST_WAIT_START(screen_capture_request);
|
||||
const uint32_t error_code = screen_capture_request.error_code;
|
||||
WAKEFIELD_REQUEST_WAIT_END(screen_capture_request);
|
||||
|
||||
jintArray arrayObj = NULL;
|
||||
|
||||
if (error_code != WAKEFIELD_ERROR_NO_ERROR) {
|
||||
handle_wakefield_error(env, error_code);
|
||||
} else {
|
||||
arrayObj = (*env)->NewIntArray(env, buffer_size_in_bytes / 4);
|
||||
if (arrayObj != NULL) {
|
||||
jint *array = (*env)->GetPrimitiveArrayCritical(env, arrayObj, NULL);
|
||||
if (array == NULL) {
|
||||
JNU_ThrowOutOfMemoryError(env, "Wayland robot screen capture");
|
||||
} else {
|
||||
memcpy(array, buffer_data, buffer_size_in_bytes);
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, arrayObj, array, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wl_buffer_destroy(buffer);
|
||||
munmap(buffer_data, buffer_size_in_bytes);
|
||||
return arrayObj;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WAKEFIELD_ROBOT
|
||||
|
||||
static void wakefield_surface_location(void *data, struct wakefield *wakefield,
|
||||
struct wl_surface *surface, int32_t x, int32_t y,
|
||||
uint32_t error_code)
|
||||
{
|
||||
J2dTrace3(J2D_TRACE_INFO, "WLRobotPeer: event wakefield_surface_location: coordinates %d, %d (error %d)\n",
|
||||
x, y, error_code);
|
||||
|
||||
WAKEFIELD_EVENT_NOTIFY_START(surface_location_request);
|
||||
surface_location_request.error_code = error_code;
|
||||
surface_location_request.x = x;
|
||||
surface_location_request.y = y;
|
||||
WAKEFIELD_EVENT_NOTIFY_END(surface_location_request);
|
||||
}
|
||||
|
||||
static void wakefield_pixel_color(void *data, struct wakefield *wakefield,
|
||||
int32_t x, int32_t y, uint32_t rgb,
|
||||
uint32_t error_code)
|
||||
{
|
||||
J2dTrace4(J2D_TRACE_INFO, "WLRobotPeer: event wakefield_pixel_color: %d, %d color 0x%08x (error %d)\n",
|
||||
x, y, rgb, error_code);
|
||||
|
||||
WAKEFIELD_EVENT_NOTIFY_START(pixel_color_request);
|
||||
pixel_color_request.error_code = error_code;
|
||||
pixel_color_request.rgb = rgb;
|
||||
WAKEFIELD_EVENT_NOTIFY_END(pixel_color_request);
|
||||
}
|
||||
|
||||
static void wakefield_capture_ready(void *data, struct wakefield *wakefield,
|
||||
struct wl_buffer *buffer,
|
||||
uint32_t error_code)
|
||||
{
|
||||
J2dTrace2(J2D_TRACE_INFO, "WLRobotPeer: event wakefield_capture_ready: buffer %p (error %d)\n",
|
||||
buffer, error_code);
|
||||
|
||||
WAKEFIELD_EVENT_NOTIFY_START(screen_capture_request);
|
||||
screen_capture_request.error_code = error_code;
|
||||
WAKEFIELD_EVENT_NOTIFY_END(screen_capture_request);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_wakefield_error(JNIEnv *env, uint32_t error_code)
|
||||
{
|
||||
J2dTrace1(J2D_TRACE_ERROR, "WLRobotPeer: error code %d\n", error_code);
|
||||
|
||||
switch (error_code) {
|
||||
case WAKEFIELD_ERROR_OUT_OF_MEMORY:
|
||||
JNU_ThrowOutOfMemoryError(env, "Wayland robot");
|
||||
break;
|
||||
|
||||
case WAKEFIELD_ERROR_FORMAT:
|
||||
JNU_ThrowInternalError(env, "Wayland robot unsupported buffer format");
|
||||
break;
|
||||
|
||||
case WAKEFIELD_ERROR_INTERNAL:
|
||||
JNU_ThrowInternalError(env, "Wayland robot");
|
||||
break;
|
||||
|
||||
case WAKEFIELD_ERROR_INVALID_COORDINATES:
|
||||
// not really an error, but a reason to return something default
|
||||
break;
|
||||
|
||||
default:
|
||||
// not all errors warrant an exception
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct wakefield_listener wakefield_listener = {
|
||||
.surface_location = wakefield_surface_location,
|
||||
.pixel_color = wakefield_pixel_color,
|
||||
.capture_ready = wakefield_capture_ready
|
||||
};
|
||||
#endif // WAKEFIELD_ROBOT
|
||||
|
||||
#ifndef HEADLESS
|
||||
|
||||
static void
|
||||
random_shm_name(char *buf) {
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
long r = ts.tv_nsec;
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
buf[i] = (char)('A' + (r & 15) + (r & 16) * 2);
|
||||
r >>= 5;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
create_shm_file() {
|
||||
int retries = 100;
|
||||
do {
|
||||
char name[] = "/wl_shm_robot-XXXXXX";
|
||||
random_shm_name(name + sizeof(name) - 7);
|
||||
--retries;
|
||||
int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
|
||||
if (fd >= 0) {
|
||||
shm_unlink(name);
|
||||
return fd;
|
||||
}
|
||||
} while (retries > 0 && errno == EEXIST);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
allocate_shm_file(int size) {
|
||||
const int fd = create_shm_file();
|
||||
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
int ret;
|
||||
do {
|
||||
ret = ftruncate(fd, size);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
|
||||
if (ret < 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static struct wl_buffer*
|
||||
allocate_buffer(JNIEnv *env, int width, int height, uint32_t **buffer_data, int* size)
|
||||
{
|
||||
const int stride = width * 4;
|
||||
*size = height * stride;
|
||||
*buffer_data = NULL;
|
||||
|
||||
if (*size <= 0) {
|
||||
JNU_ThrowByName(env, "java/awt/AWTError", "buffer size overflow");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int fd = allocate_shm_file(*size);
|
||||
if (fd == -1) {
|
||||
JNU_ThrowByName(env, "java/awt/AWTError", "couldn't open shared memory buffer file");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t *data = (uint32_t *) mmap(NULL, *size,
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (data == MAP_FAILED) {
|
||||
JNU_ThrowByName(env, "java/awt/AWTError", "couldn't mmap shared memory buffer");
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct wl_shm_pool *pool = wl_shm_create_pool(wl_shm, fd, *size);
|
||||
struct wl_buffer *buffer = wl_shm_pool_create_buffer(
|
||||
(struct wl_shm_pool*)pool, 0, width, height, stride, WL_SHM_FORMAT_XRGB8888);
|
||||
*buffer_data = data;
|
||||
wl_shm_pool_destroy(pool); // buffers keep references to the pool, can "destroy" now
|
||||
close(fd); // the server will keep this open as long as needed
|
||||
|
||||
return buffer;
|
||||
}
|
||||
#endif // HEADLESS
|
||||
31
src/java.desktop/unix/native/libawt_wlawt/WLRobotPeer.h
Normal file
31
src/java.desktop/unix/native/libawt_wlawt/WLRobotPeer.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, JetBrains s.r.o.. 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.
|
||||
*/
|
||||
|
||||
#ifdef WAKEFIELD_ROBOT
|
||||
extern struct wakefield *wakefield;
|
||||
extern struct wakefield_listener wakefield_listener;
|
||||
extern struct wl_event_queue *robot_queue;
|
||||
#endif
|
||||
453
src/java.desktop/unix/native/libawt_wlawt/WLToolkit.c
Normal file
453
src/java.desktop/unix/native/libawt_wlawt/WLToolkit.c
Normal file
@@ -0,0 +1,453 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, JetBrains s.r.o.. 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.
|
||||
*/
|
||||
|
||||
#ifdef HEADLESS
|
||||
#error This file should not be included in headless library
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <dlfcn.h>
|
||||
#include <string.h>
|
||||
#include <poll.h>
|
||||
#include <errno.h>
|
||||
#include <Trace.h>
|
||||
|
||||
#include "jni_util.h"
|
||||
#include "sun_awt_wl_WLToolkit.h"
|
||||
#include "WLToolkit.h"
|
||||
#include "WLRobotPeer.h"
|
||||
|
||||
#ifdef WAKEFIELD_ROBOT
|
||||
#include "wakefield-client-protocol.h"
|
||||
#include "sun_awt_wl_WLRobotPeer.h"
|
||||
#endif
|
||||
|
||||
extern JavaVM *jvm;
|
||||
|
||||
struct wl_display *wl_display = NULL;
|
||||
struct wl_shm *wl_shm = NULL;
|
||||
struct wl_compositor *wl_compositor = NULL;
|
||||
struct xdg_wm_base *xdg_wm_base = NULL;
|
||||
|
||||
JNIEnv *getEnv() {
|
||||
JNIEnv *env;
|
||||
// assuming we're always called from Java thread
|
||||
(*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_2);
|
||||
return env;
|
||||
}
|
||||
|
||||
static void xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial) {
|
||||
xdg_wm_base_pong(xdg_wm_base, serial);
|
||||
}
|
||||
|
||||
static const struct xdg_wm_base_listener xdg_wm_base_listener = {
|
||||
.ping = xdg_wm_base_ping,
|
||||
};
|
||||
|
||||
static void registry_global(void *data, struct wl_registry *wl_registry,
|
||||
uint32_t name, const char *interface, uint32_t version) {
|
||||
if (strcmp(interface, wl_shm_interface.name) == 0) {
|
||||
wl_shm = wl_registry_bind( wl_registry, name, &wl_shm_interface, 1);
|
||||
} else if (strcmp(interface, wl_compositor_interface.name) == 0) {
|
||||
wl_compositor = wl_registry_bind(wl_registry, name, &wl_compositor_interface, 4);
|
||||
} else if (strcmp(interface, xdg_wm_base_interface.name) == 0) {
|
||||
xdg_wm_base = wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, 1);
|
||||
xdg_wm_base_add_listener(xdg_wm_base, &xdg_wm_base_listener, NULL);
|
||||
}
|
||||
#ifdef WAKEFIELD_ROBOT
|
||||
else if (strcmp(interface, wakefield_interface.name) == 0) {
|
||||
wakefield = wl_registry_bind(wl_registry, name, &wakefield_interface, 1);
|
||||
wakefield_add_listener(wakefield, &wakefield_listener, NULL);
|
||||
robot_queue = wl_display_create_queue(wl_display);
|
||||
if (robot_queue == NULL) {
|
||||
J2dTrace(J2D_TRACE_ERROR, "WLToolkit: Failed to create wakefield robot queue\n");
|
||||
wakefield_destroy(wakefield);
|
||||
wakefield = NULL;
|
||||
} else {
|
||||
wl_proxy_set_queue((struct wl_proxy*)wakefield, robot_queue);
|
||||
}
|
||||
// TODO: call before destroying the display:
|
||||
// wl_event_queue_destroy(robot_queue);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void registry_global_remove(void *data, struct wl_registry *wl_registry, uint32_t name) {
|
||||
}
|
||||
|
||||
static const struct wl_registry_listener wl_registry_listener = {
|
||||
.global = registry_global,
|
||||
.global_remove = registry_global_remove,
|
||||
};
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_awt_wl_WLToolkit_initIDs
|
||||
(JNIEnv *env, jclass clazz)
|
||||
{
|
||||
wl_display = wl_display_connect(NULL);
|
||||
if (!wl_display) {
|
||||
J2dTrace(J2D_TRACE_ERROR, "WLToolkit: Failed to connect to Wayland display\n");
|
||||
JNU_ThrowByName(env, "java/awt/AWTError", "Can't connect to the Wayland server");
|
||||
return;
|
||||
}
|
||||
|
||||
struct wl_registry *wl_registry = wl_display_get_registry(wl_display);
|
||||
wl_registry_add_listener(wl_registry, &wl_registry_listener, NULL);
|
||||
wl_display_roundtrip(wl_display);
|
||||
J2dTrace1(J2D_TRACE_INFO, "WLToolkit: Connection to display(%p) established\n", wl_display);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_awt_wl_WLToolkit_dispatchEventsOnEDT
|
||||
(JNIEnv *env, jobject obj)
|
||||
{
|
||||
// Dispatch all the events on the display's default event queue.
|
||||
// The handlers of those events will be called from here, i.e. on EDT,
|
||||
// and therefore must not block indefinitely.
|
||||
wl_display_dispatch_pending(wl_display);
|
||||
}
|
||||
|
||||
static int
|
||||
wl_display_poll(struct wl_display *display, int events, int poll_timeout)
|
||||
{
|
||||
int rc = 0;
|
||||
struct pollfd pfd[1] = { {.fd = wl_display_get_fd(display), .events = events} };
|
||||
do {
|
||||
errno = 0;
|
||||
rc = poll(pfd, 1, poll_timeout);
|
||||
} while (rc == -1 && errno == EINTR);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
dispatch_nondefault_queues(JNIEnv *env)
|
||||
{
|
||||
// The handlers of the events on these queues will be called from here, i.e. on
|
||||
// the 'AWT-Wayland' (toolkit) thread. The handlers must *not* execute any
|
||||
// arbitrary user code that can block.
|
||||
int rc = 0;
|
||||
|
||||
#ifdef WAKEFIELD_ROBOT
|
||||
if (robot_queue) {
|
||||
rc = wl_display_dispatch_queue_pending(wl_display, robot_queue);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (rc < 0) {
|
||||
JNU_ThrowByName(env, "java/awt/AWTError", "Wayland error during events processing");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
wl_flush_to_server(JNIEnv *env)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
while (true) {
|
||||
errno = 0;
|
||||
rc = wl_display_flush(wl_display);
|
||||
if (rc != -1 || errno != EAGAIN) {
|
||||
break;
|
||||
}
|
||||
|
||||
rc = wl_display_poll(wl_display, POLLOUT, -1);
|
||||
if (rc == -1) {
|
||||
JNU_ThrowByName(env, "java/awt/AWTError", "Wayland display error polling out to the server");
|
||||
return sun_awt_wl_WLToolkit_READ_RESULT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (rc < 0 && errno != EPIPE) {
|
||||
JNU_ThrowByName(env, "java/awt/AWTError", "Wayland display error flushing data out to the server");
|
||||
return sun_awt_wl_WLToolkit_READ_RESULT_ERROR;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_awt_wl_WLToolkit_flushImpl
|
||||
(JNIEnv *env, jobject obj)
|
||||
{
|
||||
(void) wl_flush_to_server(env);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_awt_wl_WLToolkit_dispatchNonDefaultQueuesImpl
|
||||
(JNIEnv *env, jobject obj)
|
||||
{
|
||||
int rc = 0;
|
||||
while (rc != -1) {
|
||||
#ifdef WAKEFIELD_ROBOT
|
||||
if (robot_queue) {
|
||||
rc = wl_display_dispatch_queue(wl_display, robot_queue);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
// Simply return in case of any error; the actual error reporting (exception)
|
||||
// and/or shutdown will happen on the "main" toolkit thread AWT-Wayland,
|
||||
// see readEvents() below.
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_awt_wl_WLToolkit_readEvents
|
||||
(JNIEnv *env, jobject obj)
|
||||
{
|
||||
// NB: this method should be modeled after wl_display_dispatch_queue() from the Wayland code
|
||||
int rc = 0;
|
||||
|
||||
// Check if there's anything in the default event queue already *and*
|
||||
// lock the queue for this thread.
|
||||
rc = wl_display_prepare_read(wl_display);
|
||||
if (rc != 0) {
|
||||
// Ask the caller to give dispatchEventsOnEDT() more time to process
|
||||
// the default queue before calling us again.
|
||||
return sun_awt_wl_WLToolkit_READ_RESULT_NO_NEW_EVENTS;
|
||||
}
|
||||
|
||||
rc = wl_flush_to_server(env);
|
||||
if (rc != 0) {
|
||||
wl_display_cancel_read(wl_display);
|
||||
return sun_awt_wl_WLToolkit_READ_RESULT_ERROR;
|
||||
}
|
||||
|
||||
// Wait for new data *from* the server.
|
||||
// Specify some timeout because otherwise 'flush' above that sends data
|
||||
// to the server will have to wait too long.
|
||||
rc = wl_display_poll(wl_display, POLLIN,
|
||||
sun_awt_wl_WLToolkit_WAYLAND_DISPLAY_INTERACTION_TIMEOUT_MS);
|
||||
if (rc == -1) {
|
||||
wl_display_cancel_read(wl_display);
|
||||
JNU_ThrowByName(env, "java/awt/AWTError", "Wayland display error polling for data from the server");
|
||||
return sun_awt_wl_WLToolkit_READ_RESULT_ERROR;
|
||||
}
|
||||
|
||||
// Transform the data read by the above call into events on the corresponding queues of the display.
|
||||
rc = wl_display_read_events(wl_display);
|
||||
if (rc == -1) { // display disconnect has likely happened
|
||||
return sun_awt_wl_WLToolkit_READ_RESULT_ERROR;
|
||||
}
|
||||
|
||||
rc = wl_display_prepare_read(wl_display);
|
||||
if (rc != 0) {
|
||||
return sun_awt_wl_WLToolkit_READ_RESULT_FINISHED_WITH_EVENTS;
|
||||
} else {
|
||||
wl_display_cancel_read(wl_display);
|
||||
return sun_awt_wl_WLToolkit_READ_RESULT_FINISHED_NO_EVENTS;
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
|
||||
{
|
||||
jvm = vm;
|
||||
|
||||
return JNI_VERSION_1_2;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_awt_Component_initIDs
|
||||
(JNIEnv *env, jclass cls)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_awt_Container_initIDs
|
||||
(JNIEnv *env, jclass cls)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_awt_Button_initIDs
|
||||
(JNIEnv *env, jclass cls)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_awt_Scrollbar_initIDs
|
||||
(JNIEnv *env, jclass cls)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_awt_Window_initIDs
|
||||
(JNIEnv *env, jclass cls)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_awt_Frame_initIDs
|
||||
(JNIEnv *env, jclass cls)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_awt_MenuComponent_initIDs(JNIEnv *env, jclass cls)
|
||||
{
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_awt_Cursor_initIDs(JNIEnv *env, jclass cls)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void JNICALL Java_java_awt_MenuItem_initIDs
|
||||
(JNIEnv *env, jclass cls)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void JNICALL Java_java_awt_Menu_initIDs
|
||||
(JNIEnv *env, jclass cls)
|
||||
{
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_awt_TextArea_initIDs
|
||||
(JNIEnv *env, jclass cls)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_awt_Checkbox_initIDs
|
||||
(JNIEnv *env, jclass cls)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void JNICALL Java_java_awt_ScrollPane_initIDs
|
||||
(JNIEnv *env, jclass cls)
|
||||
{
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_awt_TextField_initIDs
|
||||
(JNIEnv *env, jclass cls)
|
||||
{
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_java_awt_Dialog_initIDs (JNIEnv *env, jclass cls)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Class: java_awt_TrayIcon
|
||||
* Method: initIDs
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_java_awt_TrayIcon_initIDs(JNIEnv *env , jclass clazz)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Class: java_awt_Cursor
|
||||
* Method: finalizeImpl
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_awt_Cursor_finalizeImpl(JNIEnv *env, jclass clazz, jlong pData)
|
||||
{
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_awt_FileDialog_initIDs
|
||||
(JNIEnv *env, jclass cls)
|
||||
{
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_awt_AWTEvent_initIDs(JNIEnv *env, jclass cls)
|
||||
{
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_awt_Insets_initIDs(JNIEnv *env, jclass cls)
|
||||
{
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_awt_KeyboardFocusManager_initIDs
|
||||
(JNIEnv *env, jclass cls)
|
||||
{
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_awt_Font_initIDs(JNIEnv *env, jclass cls) {
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_awt_event_InputEvent_initIDs(JNIEnv *env, jclass cls)
|
||||
{
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_awt_event_KeyEvent_initIDs(JNIEnv *env, jclass cls)
|
||||
{
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_awt_Event_initIDs(JNIEnv *env, jclass cls)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_awt_SunToolkit_closeSplashScreen(JNIEnv *env, jclass cls)
|
||||
{
|
||||
typedef void (*SplashClose_t)();
|
||||
SplashClose_t splashClose;
|
||||
void* hSplashLib = dlopen(0, RTLD_LAZY);
|
||||
if (!hSplashLib) {
|
||||
return;
|
||||
}
|
||||
splashClose = (SplashClose_t)dlsym(hSplashLib,
|
||||
"SplashClose");
|
||||
if (splashClose) {
|
||||
splashClose();
|
||||
}
|
||||
dlclose(hSplashLib);
|
||||
}
|
||||
36
src/java.desktop/unix/native/libawt_wlawt/WLToolkit.h
Normal file
36
src/java.desktop/unix/native/libawt_wlawt/WLToolkit.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2021, JetBrains s.r.o.. 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 <wayland-client.h>
|
||||
#include "xdg-shell-client-protocol.h"
|
||||
|
||||
extern struct wl_display *wl_display;
|
||||
extern struct wl_shm *wl_shm;
|
||||
extern struct wl_compositor *wl_compositor;
|
||||
extern struct xdg_wm_base *xdg_wm_base;
|
||||
|
||||
JNIEnv *getEnv();
|
||||
|
||||
int wl_flush_to_server(JNIEnv* env);
|
||||
@@ -0,0 +1,73 @@
|
||||
/* Generated by wayland-scanner 1.19.0 */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, JetBrains s.r.o.. 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.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "wayland-util.h"
|
||||
|
||||
extern const struct wl_interface wl_buffer_interface;
|
||||
extern const struct wl_interface wl_surface_interface;
|
||||
|
||||
static const struct wl_interface *wakefield_types[] = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&wl_surface_interface,
|
||||
NULL,
|
||||
NULL,
|
||||
&wl_surface_interface,
|
||||
&wl_buffer_interface,
|
||||
NULL,
|
||||
NULL,
|
||||
&wl_surface_interface,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&wl_buffer_interface,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct wl_message wakefield_requests[] = {
|
||||
{ "destroy", "", wakefield_types + 0 },
|
||||
{ "move_surface", "oii", wakefield_types + 4 },
|
||||
{ "get_surface_location", "o", wakefield_types + 7 },
|
||||
{ "get_pixel_color", "ii", wakefield_types + 0 },
|
||||
{ "capture_create", "oii", wakefield_types + 8 },
|
||||
};
|
||||
|
||||
static const struct wl_message wakefield_events[] = {
|
||||
{ "surface_location", "oiiu", wakefield_types + 11 },
|
||||
{ "pixel_color", "iiuu", wakefield_types + 0 },
|
||||
{ "capture_ready", "ou", wakefield_types + 15 },
|
||||
};
|
||||
|
||||
WL_EXPORT const struct wl_interface wakefield_interface = {
|
||||
"wakefield", 1,
|
||||
5, wakefield_requests,
|
||||
3, wakefield_events,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,266 @@
|
||||
/* Generated by wayland-scanner 1.19.0 */
|
||||
|
||||
#ifndef WAKEFIELD_CLIENT_PROTOCOL_H
|
||||
#define WAKEFIELD_CLIENT_PROTOCOL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "wayland-client.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @page page_wakefield The wakefield protocol
|
||||
* @section page_ifaces_wakefield Interfaces
|
||||
* - @subpage page_iface_wakefield - provides capabilities necessary to for java.awt.Robot and such
|
||||
* @section page_copyright_wakefield Copyright
|
||||
* <pre>
|
||||
*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, JetBrains s.r.o.. 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.
|
||||
* </pre>
|
||||
*/
|
||||
struct wakefield;
|
||||
struct wl_buffer;
|
||||
struct wl_surface;
|
||||
|
||||
#ifndef WAKEFIELD_INTERFACE
|
||||
#define WAKEFIELD_INTERFACE
|
||||
/**
|
||||
* @page page_iface_wakefield wakefield
|
||||
* @section page_iface_wakefield_desc Description
|
||||
* @section page_iface_wakefield_api API
|
||||
* See @ref iface_wakefield.
|
||||
*/
|
||||
/**
|
||||
* @defgroup iface_wakefield The wakefield interface
|
||||
*/
|
||||
extern const struct wl_interface wakefield_interface;
|
||||
#endif
|
||||
|
||||
#ifndef WAKEFIELD_ERROR_ENUM
|
||||
#define WAKEFIELD_ERROR_ENUM
|
||||
enum wakefield_error {
|
||||
/**
|
||||
* error code 0 reserved for the absence of error
|
||||
*/
|
||||
WAKEFIELD_ERROR_NO_ERROR = 0,
|
||||
/**
|
||||
* supplied absolute coordinates point outside of any output
|
||||
*/
|
||||
WAKEFIELD_ERROR_INVALID_COORDINATES = 1,
|
||||
/**
|
||||
* the request could not be fulfilled due to memory allocation error
|
||||
*/
|
||||
WAKEFIELD_ERROR_OUT_OF_MEMORY = 2,
|
||||
/**
|
||||
* a generic error code for internal errors
|
||||
*/
|
||||
WAKEFIELD_ERROR_INTERNAL = 3,
|
||||
/**
|
||||
* (temporary?) color cannot be converted to RGB format
|
||||
*/
|
||||
WAKEFIELD_ERROR_FORMAT = 4,
|
||||
};
|
||||
#endif /* WAKEFIELD_ERROR_ENUM */
|
||||
|
||||
/**
|
||||
* @ingroup iface_wakefield
|
||||
* @struct wakefield_listener
|
||||
*/
|
||||
struct wakefield_listener {
|
||||
/**
|
||||
* facilitates implementation of Frame.getLocation()
|
||||
*
|
||||
* This event reveals the absolute coordinates of the surface if
|
||||
* error_code is zero. If error_code is non-zero, (x, y) are
|
||||
* undefined. The surface argument always correspond to that of the
|
||||
* get_surface_location request.
|
||||
*/
|
||||
void (*surface_location)(void *data,
|
||||
struct wakefield *wakefield,
|
||||
struct wl_surface *surface,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
uint32_t error_code);
|
||||
/**
|
||||
* facilitates implementation of Robot.getPixelColor()
|
||||
*
|
||||
* This event shows the color (24-bit, format r8g8b8) of the
|
||||
* pixel with the given absolute coordinates. The (x, y) arguments
|
||||
* correspond to that of the get_pixel_color request. If error_code
|
||||
* is non-zero, the rgb argument is undefined and the error_code
|
||||
* argument contains a code from the error enum.
|
||||
*/
|
||||
void (*pixel_color)(void *data,
|
||||
struct wakefield *wakefield,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
uint32_t rgb,
|
||||
uint32_t error_code);
|
||||
/**
|
||||
*/
|
||||
void (*capture_ready)(void *data,
|
||||
struct wakefield *wakefield,
|
||||
struct wl_buffer *buffer,
|
||||
uint32_t error_code);
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup iface_wakefield
|
||||
*/
|
||||
static inline int
|
||||
wakefield_add_listener(struct wakefield *wakefield,
|
||||
const struct wakefield_listener *listener, void *data)
|
||||
{
|
||||
return wl_proxy_add_listener((struct wl_proxy *) wakefield,
|
||||
(void (**)(void)) listener, data);
|
||||
}
|
||||
|
||||
#define WAKEFIELD_DESTROY 0
|
||||
#define WAKEFIELD_MOVE_SURFACE 1
|
||||
#define WAKEFIELD_GET_SURFACE_LOCATION 2
|
||||
#define WAKEFIELD_GET_PIXEL_COLOR 3
|
||||
#define WAKEFIELD_CAPTURE_CREATE 4
|
||||
|
||||
/**
|
||||
* @ingroup iface_wakefield
|
||||
*/
|
||||
#define WAKEFIELD_SURFACE_LOCATION_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_wakefield
|
||||
*/
|
||||
#define WAKEFIELD_PIXEL_COLOR_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_wakefield
|
||||
*/
|
||||
#define WAKEFIELD_CAPTURE_READY_SINCE_VERSION 1
|
||||
|
||||
/**
|
||||
* @ingroup iface_wakefield
|
||||
*/
|
||||
#define WAKEFIELD_DESTROY_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_wakefield
|
||||
*/
|
||||
#define WAKEFIELD_MOVE_SURFACE_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_wakefield
|
||||
*/
|
||||
#define WAKEFIELD_GET_SURFACE_LOCATION_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_wakefield
|
||||
*/
|
||||
#define WAKEFIELD_GET_PIXEL_COLOR_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_wakefield
|
||||
*/
|
||||
#define WAKEFIELD_CAPTURE_CREATE_SINCE_VERSION 1
|
||||
|
||||
/** @ingroup iface_wakefield */
|
||||
static inline void
|
||||
wakefield_set_user_data(struct wakefield *wakefield, void *user_data)
|
||||
{
|
||||
wl_proxy_set_user_data((struct wl_proxy *) wakefield, user_data);
|
||||
}
|
||||
|
||||
/** @ingroup iface_wakefield */
|
||||
static inline void *
|
||||
wakefield_get_user_data(struct wakefield *wakefield)
|
||||
{
|
||||
return wl_proxy_get_user_data((struct wl_proxy *) wakefield);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
wakefield_get_version(struct wakefield *wakefield)
|
||||
{
|
||||
return wl_proxy_get_version((struct wl_proxy *) wakefield);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup iface_wakefield
|
||||
*/
|
||||
static inline void
|
||||
wakefield_destroy(struct wakefield *wakefield)
|
||||
{
|
||||
wl_proxy_marshal((struct wl_proxy *) wakefield,
|
||||
WAKEFIELD_DESTROY);
|
||||
|
||||
wl_proxy_destroy((struct wl_proxy *) wakefield);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup iface_wakefield
|
||||
*
|
||||
* This instructs the window manager to position the given wl_surface
|
||||
* at the given absolute coordinates. The subsequent get_surface_location
|
||||
* request will return these coordinates unless the surface was moved by
|
||||
* a third party.
|
||||
*/
|
||||
static inline void
|
||||
wakefield_move_surface(struct wakefield *wakefield, struct wl_surface *surface, int32_t x, int32_t y)
|
||||
{
|
||||
wl_proxy_marshal((struct wl_proxy *) wakefield,
|
||||
WAKEFIELD_MOVE_SURFACE, surface, x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup iface_wakefield
|
||||
*
|
||||
* This requests a surface_location event for the given surface.
|
||||
*/
|
||||
static inline void
|
||||
wakefield_get_surface_location(struct wakefield *wakefield, struct wl_surface *surface)
|
||||
{
|
||||
wl_proxy_marshal((struct wl_proxy *) wakefield,
|
||||
WAKEFIELD_GET_SURFACE_LOCATION, surface);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup iface_wakefield
|
||||
*
|
||||
* This requests a pixel_color event at the given absolute coordinates.
|
||||
*/
|
||||
static inline void
|
||||
wakefield_get_pixel_color(struct wakefield *wakefield, int32_t x, int32_t y)
|
||||
{
|
||||
wl_proxy_marshal((struct wl_proxy *) wakefield,
|
||||
WAKEFIELD_GET_PIXEL_COLOR, x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup iface_wakefield
|
||||
*/
|
||||
static inline void
|
||||
wakefield_capture_create(struct wakefield *wakefield, struct wl_buffer *buffer, int32_t x, int32_t y)
|
||||
{
|
||||
wl_proxy_marshal((struct wl_proxy *) wakefield,
|
||||
WAKEFIELD_CAPTURE_CREATE, buffer, x, y);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
181
src/java.desktop/unix/native/libawt_wlawt/xdg-shell-protocol.c
Normal file
181
src/java.desktop/unix/native/libawt_wlawt/xdg-shell-protocol.c
Normal file
@@ -0,0 +1,181 @@
|
||||
/* Generated by wayland-scanner 1.18.0 */
|
||||
|
||||
/*
|
||||
* Copyright © 2008-2013 Kristian Høgsberg
|
||||
* Copyright © 2013 Rafael Antognolli
|
||||
* Copyright © 2013 Jasper St. Pierre
|
||||
* Copyright © 2010-2013 Intel Corporation
|
||||
* Copyright © 2015-2017 Samsung Electronics Co., Ltd
|
||||
* Copyright © 2015-2017 Red Hat Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS 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. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "wayland-util.h"
|
||||
|
||||
#ifndef __has_attribute
|
||||
# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
|
||||
#endif
|
||||
|
||||
#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
|
||||
#define WL_PRIVATE __attribute__ ((visibility("hidden")))
|
||||
#else
|
||||
#define WL_PRIVATE
|
||||
#endif
|
||||
|
||||
extern const struct wl_interface wl_output_interface;
|
||||
extern const struct wl_interface wl_seat_interface;
|
||||
extern const struct wl_interface wl_surface_interface;
|
||||
extern const struct wl_interface xdg_popup_interface;
|
||||
extern const struct wl_interface xdg_positioner_interface;
|
||||
extern const struct wl_interface xdg_surface_interface;
|
||||
extern const struct wl_interface xdg_toplevel_interface;
|
||||
|
||||
static const struct wl_interface *xdg_shell_types[] = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&xdg_positioner_interface,
|
||||
&xdg_surface_interface,
|
||||
&wl_surface_interface,
|
||||
&xdg_toplevel_interface,
|
||||
&xdg_popup_interface,
|
||||
&xdg_surface_interface,
|
||||
&xdg_positioner_interface,
|
||||
&xdg_toplevel_interface,
|
||||
&wl_seat_interface,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&wl_seat_interface,
|
||||
NULL,
|
||||
&wl_seat_interface,
|
||||
NULL,
|
||||
NULL,
|
||||
&wl_output_interface,
|
||||
&wl_seat_interface,
|
||||
NULL,
|
||||
&xdg_positioner_interface,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct wl_message xdg_wm_base_requests[] = {
|
||||
{ "destroy", "", xdg_shell_types + 0 },
|
||||
{ "create_positioner", "n", xdg_shell_types + 4 },
|
||||
{ "get_xdg_surface", "no", xdg_shell_types + 5 },
|
||||
{ "pong", "u", xdg_shell_types + 0 },
|
||||
};
|
||||
|
||||
static const struct wl_message xdg_wm_base_events[] = {
|
||||
{ "ping", "u", xdg_shell_types + 0 },
|
||||
};
|
||||
|
||||
WL_PRIVATE const struct wl_interface xdg_wm_base_interface = {
|
||||
"xdg_wm_base", 3,
|
||||
4, xdg_wm_base_requests,
|
||||
1, xdg_wm_base_events,
|
||||
};
|
||||
|
||||
static const struct wl_message xdg_positioner_requests[] = {
|
||||
{ "destroy", "", xdg_shell_types + 0 },
|
||||
{ "set_size", "ii", xdg_shell_types + 0 },
|
||||
{ "set_anchor_rect", "iiii", xdg_shell_types + 0 },
|
||||
{ "set_anchor", "u", xdg_shell_types + 0 },
|
||||
{ "set_gravity", "u", xdg_shell_types + 0 },
|
||||
{ "set_constraint_adjustment", "u", xdg_shell_types + 0 },
|
||||
{ "set_offset", "ii", xdg_shell_types + 0 },
|
||||
{ "set_reactive", "3", xdg_shell_types + 0 },
|
||||
{ "set_parent_size", "3ii", xdg_shell_types + 0 },
|
||||
{ "set_parent_configure", "3u", xdg_shell_types + 0 },
|
||||
};
|
||||
|
||||
WL_PRIVATE const struct wl_interface xdg_positioner_interface = {
|
||||
"xdg_positioner", 3,
|
||||
10, xdg_positioner_requests,
|
||||
0, NULL,
|
||||
};
|
||||
|
||||
static const struct wl_message xdg_surface_requests[] = {
|
||||
{ "destroy", "", xdg_shell_types + 0 },
|
||||
{ "get_toplevel", "n", xdg_shell_types + 7 },
|
||||
{ "get_popup", "n?oo", xdg_shell_types + 8 },
|
||||
{ "set_window_geometry", "iiii", xdg_shell_types + 0 },
|
||||
{ "ack_configure", "u", xdg_shell_types + 0 },
|
||||
};
|
||||
|
||||
static const struct wl_message xdg_surface_events[] = {
|
||||
{ "configure", "u", xdg_shell_types + 0 },
|
||||
};
|
||||
|
||||
WL_PRIVATE const struct wl_interface xdg_surface_interface = {
|
||||
"xdg_surface", 3,
|
||||
5, xdg_surface_requests,
|
||||
1, xdg_surface_events,
|
||||
};
|
||||
|
||||
static const struct wl_message xdg_toplevel_requests[] = {
|
||||
{ "destroy", "", xdg_shell_types + 0 },
|
||||
{ "set_parent", "?o", xdg_shell_types + 11 },
|
||||
{ "set_title", "s", xdg_shell_types + 0 },
|
||||
{ "set_app_id", "s", xdg_shell_types + 0 },
|
||||
{ "show_window_menu", "ouii", xdg_shell_types + 12 },
|
||||
{ "move", "ou", xdg_shell_types + 16 },
|
||||
{ "resize", "ouu", xdg_shell_types + 18 },
|
||||
{ "set_max_size", "ii", xdg_shell_types + 0 },
|
||||
{ "set_min_size", "ii", xdg_shell_types + 0 },
|
||||
{ "set_maximized", "", xdg_shell_types + 0 },
|
||||
{ "unset_maximized", "", xdg_shell_types + 0 },
|
||||
{ "set_fullscreen", "?o", xdg_shell_types + 21 },
|
||||
{ "unset_fullscreen", "", xdg_shell_types + 0 },
|
||||
{ "set_minimized", "", xdg_shell_types + 0 },
|
||||
};
|
||||
|
||||
static const struct wl_message xdg_toplevel_events[] = {
|
||||
{ "configure", "iia", xdg_shell_types + 0 },
|
||||
{ "close", "", xdg_shell_types + 0 },
|
||||
};
|
||||
|
||||
WL_PRIVATE const struct wl_interface xdg_toplevel_interface = {
|
||||
"xdg_toplevel", 3,
|
||||
14, xdg_toplevel_requests,
|
||||
2, xdg_toplevel_events,
|
||||
};
|
||||
|
||||
static const struct wl_message xdg_popup_requests[] = {
|
||||
{ "destroy", "", xdg_shell_types + 0 },
|
||||
{ "grab", "ou", xdg_shell_types + 22 },
|
||||
{ "reposition", "3ou", xdg_shell_types + 24 },
|
||||
};
|
||||
|
||||
static const struct wl_message xdg_popup_events[] = {
|
||||
{ "configure", "iiii", xdg_shell_types + 0 },
|
||||
{ "popup_done", "", xdg_shell_types + 0 },
|
||||
{ "repositioned", "3u", xdg_shell_types + 0 },
|
||||
};
|
||||
|
||||
WL_PRIVATE const struct wl_interface xdg_popup_interface = {
|
||||
"xdg_popup", 3,
|
||||
3, xdg_popup_requests,
|
||||
3, xdg_popup_events,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2021, 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <dlfcn.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <jni.h>
|
||||
#include <jni_util.h>
|
||||
#include <jvm.h>
|
||||
#include "gdefs.h"
|
||||
#include "sun_awt_PlatformGraphicsInfo.h"
|
||||
#include <sys/param.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#ifdef AIX
|
||||
#include "porting_aix.h" /* For the 'dladdr' function. */
|
||||
#endif
|
||||
|
||||
#ifndef MACOSX
|
||||
#ifndef STATIC_BUILD
|
||||
|
||||
#define CHECK_EXCEPTION_FATAL(env, message) \
|
||||
if ((*env)->ExceptionCheck(env)) { \
|
||||
(*env)->ExceptionClear(env); \
|
||||
(*env)->FatalError(env, message); \
|
||||
}
|
||||
|
||||
static void *fontmanagerHandle = NULL;
|
||||
|
||||
JNIEXPORT jboolean JNICALL AWTIsHeadless();
|
||||
JNIEXPORT jint JNICALL AWTGetToolkitID();
|
||||
|
||||
jint
|
||||
Fontmanager_OnLoad(JavaVM *vm, void *reserved)
|
||||
{
|
||||
JNIEnv *env = (JNIEnv *)JNU_GetEnv(vm, JNI_VERSION_1_2);
|
||||
|
||||
if (!AWTIsHeadless() && AWTGetToolkitID() == sun_awt_PlatformGraphicsInfo_TK_X11) {
|
||||
|
||||
Dl_info dlinfo;
|
||||
char buf[MAXPATHLEN];
|
||||
int32_t len;
|
||||
char *p, *tk;
|
||||
|
||||
tk = "/libfontmanager_xawt.so";
|
||||
|
||||
/* Get address of this library and the directory containing it. */
|
||||
dladdr((void *)Fontmanager_OnLoad, &dlinfo);
|
||||
realpath((char *)dlinfo.dli_fname, buf);
|
||||
len = strlen(buf);
|
||||
p = strrchr(buf, '/');
|
||||
/* Calculate library name to load */
|
||||
strncpy(p, tk, MAXPATHLEN-len-1);
|
||||
|
||||
jstring jbuf = JNU_NewStringPlatform(env, buf);
|
||||
CHECK_EXCEPTION_FATAL(env, "Could not allocate library name");
|
||||
JNU_CallStaticMethodByName(env, NULL, "java/lang/System", "load",
|
||||
"(Ljava/lang/String;)V",
|
||||
jbuf);
|
||||
fontmanagerHandle = dlopen(buf, RTLD_LAZY | RTLD_GLOBAL);
|
||||
}
|
||||
|
||||
return JNI_VERSION_1_2;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
|
||||
{
|
||||
return Fontmanager_OnLoad(vm, reserved);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -366,8 +366,9 @@ JNIEXPORT jobject JNICALL
|
||||
* leadingY : made-up number, but being compatible with what 1.4.x did
|
||||
* advance : no need to set yMaxLinearAdvanceWidth - it will be zero.
|
||||
*/
|
||||
metrics = (*env)->NewObject(env, sunFontIDs.strikeMetricsClass,
|
||||
sunFontIDs.strikeMetricsCtr,
|
||||
const FontManagerNativeIDs* sunFontIDs = getSunFontIDsPtr(env);
|
||||
metrics = (*env)->NewObject(env, sunFontIDs->strikeMetricsClass,
|
||||
sunFontIDs->strikeMetricsCtr,
|
||||
j0, ay, j0, dy, j1, j0, j0, j1, mx, j0);
|
||||
/* printf("X11 asc=%f dsc=%f adv=%f scale=%f\n", */
|
||||
/* ay, dy, mx, (float)context->scale); */
|
||||
@@ -62,7 +62,7 @@ JNIEXPORT void JNICALL Java_sun_font_X11TextRenderer_doDrawGlyphList
|
||||
SurfaceDataBounds bounds;
|
||||
Region_GetBounds(env, clip, &bounds);
|
||||
|
||||
glyphCount = (*env)->GetIntField(env, glyphlist, sunFontIDs.glyphListLen);
|
||||
glyphCount = (*env)->GetIntField(env, glyphlist, getSunFontIDsPtr(env)->glyphListLen);
|
||||
if ((gbv = setupBlitVector(env, glyphlist, 0, glyphCount)) == NULL) {
|
||||
return;
|
||||
}
|
||||
41
test/jdk/java/awt/Toolkit/Wayland/WaylandToolkit.java
Normal file
41
test/jdk/java/awt/Toolkit/Wayland/WaylandToolkit.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, JetBrains s.r.o.. 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
|
||||
* @summary Check for Wayland toolkit
|
||||
* @run main/othervm -Dawt.toolkit.name=WLToolkit WaylandToolkit
|
||||
* @requires os.family == "linux"
|
||||
*/
|
||||
import java.awt.*;
|
||||
|
||||
public class WaylandToolkit {
|
||||
|
||||
public static void main(String args[]) {
|
||||
Toolkit tk = Toolkit.getDefaultToolkit();
|
||||
if (!"sun.awt.wl.WLToolkit".equals(tk.getClass().getName())) {
|
||||
throw new RuntimeException("WLToolkit not found");
|
||||
}
|
||||
}
|
||||
}
|
||||
174
test/jdk/java/awt/wakefield/ScreenCapture.java
Normal file
174
test/jdk/java/awt/wakefield/ScreenCapture.java
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, JetBrains s.r.o.. 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.
|
||||
*/
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import javax.swing.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import javax.imageio.ImageIO;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @key headful
|
||||
* @summary Windows HiDPI support
|
||||
* @requires (os.family == "linux")
|
||||
* @library /test/lib
|
||||
* @build ScreenCapture
|
||||
* @run driver WakefieldTestDriver 1x1400x800 ScreenCapture
|
||||
* @run driver WakefieldTestDriver 2x830x800 ScreenCapture
|
||||
*/
|
||||
|
||||
public class ScreenCapture {
|
||||
private static final Color[] COLORS = {
|
||||
Color.GREEN, Color.BLUE, Color.ORANGE, Color.RED};
|
||||
|
||||
private static volatile ScreenCapture theTest;
|
||||
|
||||
private static JFrame frame;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
runSwing( () -> {
|
||||
frame = new JFrame();
|
||||
frame.setPreferredSize(new Dimension(800, 300));
|
||||
frame.setUndecorated(true);
|
||||
frame.add(new JPanel() {
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
final int w = getWidth();
|
||||
final int h = getHeight();
|
||||
g.setColor(COLORS[0]);
|
||||
g.fillRect(0, 0, w / 2, h / 2);
|
||||
g.setColor(COLORS[1]);
|
||||
g.fillRect(w / 2, 0, w / 2, h / 2);
|
||||
g.setColor(COLORS[2]);
|
||||
g.fillRect(0, h / 2, w / 2, h / 2);
|
||||
g.setColor(COLORS[3]);
|
||||
g.fillRect(w / 2, h / 2, w / 2, h / 2);
|
||||
}
|
||||
});
|
||||
frame.pack();
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
frame.setVisible(true);
|
||||
frame.setBounds(432, 89, 800, 300);
|
||||
});
|
||||
|
||||
final Robot robot = new Robot();
|
||||
robot.waitForIdle();
|
||||
|
||||
final Rectangle rect = frame.getBounds();
|
||||
rect.setLocation(frame.getLocationOnScreen());
|
||||
|
||||
// the windows fades in slowly, need to wait quite a bit in order to get reliable colors
|
||||
robot.delay(1000);
|
||||
|
||||
System.out.println("Creating screen capture of " + rect);
|
||||
final BufferedImage image = robot.createScreenCapture(rect);
|
||||
|
||||
try {
|
||||
checkPixelColor(robot, rect.x + OFFSET, rect.y + OFFSET, COLORS[0]);
|
||||
checkPixelColor(robot, rect.x + rect.width - OFFSET, rect.y + OFFSET, COLORS[1]);
|
||||
checkPixelColor(robot, rect.x + OFFSET, rect.y + rect.height - OFFSET, COLORS[2]);
|
||||
checkPixelColor(robot, rect.x + rect.width - OFFSET, rect.y + rect.height - OFFSET, COLORS[3]);
|
||||
} finally {
|
||||
frame.dispose();
|
||||
}
|
||||
|
||||
final int w = image.getWidth();
|
||||
final int h = image.getHeight();
|
||||
|
||||
if (w != frame.getWidth() || h != frame.getHeight()) {
|
||||
throw new RuntimeException("Wrong image size!");
|
||||
}
|
||||
|
||||
checkRectColor(image, new Rectangle(0, 0, w / 2, h / 2), COLORS[0]);
|
||||
checkRectColor(image, new Rectangle(w / 2, 0, w / 2, h / 2), COLORS[1]);
|
||||
checkRectColor(image, new Rectangle(0, h / 2, w / 2, h / 2), COLORS[2]);
|
||||
checkRectColor(image, new Rectangle(w / 2, h / 2, w / 2, h / 2), COLORS[3]);
|
||||
|
||||
System.exit(0); // temporary
|
||||
}
|
||||
|
||||
private static final int OFFSET = 5;
|
||||
|
||||
static void checkPixelColor(Robot robot, int x, int y, Color expectedColor) {
|
||||
System.out.print("Checking pixel at " + x + ", " + y + " to have color " + expectedColor);
|
||||
final Color actualColor = robot.getPixelColor(x, y);
|
||||
if (!actualColor.equals(expectedColor)) {
|
||||
System.out.println("... Mismatch: found " + actualColor + " instead");
|
||||
throw new RuntimeException("Wrong color of pixel on screen");
|
||||
} else {
|
||||
System.out.println("... OK");
|
||||
}
|
||||
}
|
||||
|
||||
static void checkRectColor(BufferedImage image, Rectangle rect, Color expectedColor) {
|
||||
System.out.println("Checking rectangle " + rect + " to have color " + expectedColor);
|
||||
final Point[] pointsToCheck = new Point[] {
|
||||
new Point(rect.x + OFFSET, rect.y + OFFSET), // top left corner
|
||||
new Point(rect.x + rect.width - OFFSET, rect.y + OFFSET), // top right corner
|
||||
new Point(rect.x + rect.width / 2, rect.y + rect.height / 2), // center
|
||||
new Point(rect.x + OFFSET, rect.y + rect.height - OFFSET), // bottom left corner
|
||||
new Point(rect.x + rect.width - OFFSET, rect.y + rect.height - OFFSET) // bottom right corner
|
||||
};
|
||||
|
||||
for (final var point : pointsToCheck) {
|
||||
System.out.print("Checking color at " + point + " to be equal to " + expectedColor);
|
||||
final int actualColor = image.getRGB(point.x, point.y);
|
||||
if (actualColor != expectedColor.getRGB()) {
|
||||
System.out.println("... Mismatch: found " + new Color(actualColor) + " instead. Check image.png.");
|
||||
try {
|
||||
ImageIO.write(image, "png", new File("image.png"));
|
||||
} catch(IOException e) {
|
||||
System.out.println("failed to save image.png.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
throw new RuntimeException("Wrong image color!");
|
||||
} else {
|
||||
System.out.println("... OK");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
if (frame != null) {
|
||||
frame.dispose();
|
||||
frame = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void runSwing(Runnable r) {
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(r);
|
||||
} catch (InterruptedException e) {
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
162
test/jdk/java/awt/wakefield/WakefieldTestDriver.java
Normal file
162
test/jdk/java/awt/wakefield/WakefieldTestDriver.java
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 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.
|
||||
*/
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.io.IOException;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class WakefieldTestDriver {
|
||||
final static int DEFAULT_NUMBER_OF_SCREENS = 1;
|
||||
final static int DEFAULT_SCREEN_WIDTH = 1280;
|
||||
final static int DEFAULT_SCREEN_HEIGHT = 800;
|
||||
final static int TEST_TIMEOUT_SECONDS = 10;
|
||||
static void usage() {
|
||||
System.out.println(
|
||||
"""
|
||||
WakefieldTestDriver [NxWxH] ClassName [args]
|
||||
where
|
||||
N - number of Weston outputs (screens); defaults to 1
|
||||
W - width of each screen in pixels; defaults to 1280
|
||||
H - height of each screen in pixels; defaults to 800
|
||||
ClassName - class to execute
|
||||
args - arguments to give to the class""");
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
if (args.length < 1) {
|
||||
usage();
|
||||
throw new RuntimeException("Insufficient arguments to the test driver");
|
||||
}
|
||||
|
||||
checkEnv(System.getenv());
|
||||
|
||||
final List<String> jvmArgs = new ArrayList<String>();
|
||||
jvmArgs.add("-Dawt.toolkit.name=WLToolkit");
|
||||
jvmArgs.add("-Xcheck:jni");
|
||||
|
||||
int nScreens = DEFAULT_NUMBER_OF_SCREENS;
|
||||
int screenWidth = DEFAULT_SCREEN_WIDTH;
|
||||
int screenHeight = DEFAULT_SCREEN_HEIGHT;
|
||||
final String firstArg = args[0];
|
||||
if (Character.isDigit(firstArg.charAt(0))) {
|
||||
try {
|
||||
final int firstXIndex = firstArg.indexOf("x", 0);
|
||||
final int secondXIndex = firstArg.indexOf("x", firstXIndex + 1);
|
||||
nScreens = Integer.valueOf(firstArg.substring(0, firstXIndex));
|
||||
screenWidth = Integer.valueOf(firstArg.substring(firstXIndex + 1, secondXIndex));
|
||||
screenHeight = Integer.valueOf(firstArg.substring(secondXIndex + 1, firstArg.length()));
|
||||
|
||||
for (int i = 1; i < args.length; ++i) {
|
||||
jvmArgs.add(args[i]);
|
||||
}
|
||||
} catch (IndexOutOfBoundsException | NumberFormatException ignored) {
|
||||
usage();
|
||||
throw new RuntimeException("Error parsing the first argument of the test driver");
|
||||
}
|
||||
} else {
|
||||
jvmArgs.addAll(Arrays.asList(args));
|
||||
}
|
||||
|
||||
final String socketName = SOCKET_NAME_PREFIX + ProcessHandle.current().pid();
|
||||
final Process westonProcess = launchWeston(nScreens, screenWidth, screenHeight, socketName);
|
||||
try {
|
||||
System.out.println("Running test with WAYLAND_DISPLAY=" + socketName);
|
||||
final ProcessBuilder pb = ProcessTools.createTestJvm(jvmArgs);
|
||||
final Map<String, String> env = pb.environment();
|
||||
env.put("WAYLAND_DISPLAY", socketName);
|
||||
|
||||
final Process p = pb.start();
|
||||
final OutputAnalyzer output = new OutputAnalyzer(p);
|
||||
final boolean exited = p.waitFor(TEST_TIMEOUT_SECONDS, TimeUnit.SECONDS);
|
||||
if (!exited) p.destroy();
|
||||
System.out.println("Test finished. Output: [[[");
|
||||
System.out.println(output.getOutput());
|
||||
System.out.println("]]]");
|
||||
if (!exited) {
|
||||
throw new RuntimeException("Test timed out after " + TEST_TIMEOUT_SECONDS + " seconds");
|
||||
}
|
||||
|
||||
if (exited && output.getExitValue() != 0) {
|
||||
throw new RuntimeException("Test finished with non-zero exit code");
|
||||
}
|
||||
} finally {
|
||||
if (westonProcess != null) {
|
||||
final OutputAnalyzer westonOutput = new OutputAnalyzer(westonProcess);
|
||||
westonProcess.destroy();
|
||||
|
||||
System.out.println("Weston output: [[[");
|
||||
System.out.println(westonOutput.getOutput());
|
||||
System.out.println("]]]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void checkEnv(Map<String, String> env) {
|
||||
if (!env.containsKey("DISPLAY")) {
|
||||
throw new RuntimeException("DISPLAY environment variable must be set to run this test driver");
|
||||
}
|
||||
|
||||
if (!env.containsKey("XDG_RUNTIME_DIR")) {
|
||||
throw new RuntimeException("XDG_RUNTIME_DIR environment variable must be set to run this test driver; pass -e:XDG_RUNTIME_DIR to jtreg");
|
||||
}
|
||||
|
||||
if (!env.containsKey("LIBWAKEFIELD")) {
|
||||
throw new RuntimeException("Set LIBWAKEFIELD environment variable to full path to libwakefield.so");
|
||||
}
|
||||
|
||||
if (!Files.exists(Path.of(env.get("LIBWAKEFIELD")))) {
|
||||
throw new RuntimeException("LIBWAKEFIELD (" + env.get("LIBWAKEFIELD") + " does not point to an executable");
|
||||
}
|
||||
}
|
||||
|
||||
static final String SOCKET_NAME_PREFIX = "wakefield-";
|
||||
|
||||
static Process launchWeston(int nScreens, int width, int height, String socketName) throws IOException {
|
||||
final List<String> args = new ArrayList<String>();
|
||||
args.add("weston");
|
||||
args.add("--backend=x11-backend.so");
|
||||
args.add("--socket=" + socketName);
|
||||
args.add("--output-count=" + nScreens);
|
||||
args.add("--width=" + width);
|
||||
args.add("--height=" + height);
|
||||
args.add("--use-pixman");
|
||||
args.add("--idle-time=0");
|
||||
args.add("--logger-scopes=log,wakefield");
|
||||
//args.add("--log=weston-server-log.txt"); // Log to stderr, its easier to manage this way.
|
||||
args.add("--no-config");
|
||||
args.add("--modules=" + System.getenv("LIBWAKEFIELD"));
|
||||
|
||||
System.out.println("Running " + String.join(" ", args));
|
||||
|
||||
return new ProcessBuilder(args).redirectErrorStream(true).start();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user