mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-06 01:19:28 +01:00
Compare commits
4 Commits
e956e04e37
...
7abc1a541d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7abc1a541d | ||
|
|
de8ea2d81c | ||
|
|
bc737fb03a | ||
|
|
f8e0ee5a18 |
@@ -22,6 +22,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __linux
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include "cds/aotLogging.hpp"
|
||||
#include "cds/cds_globals.hpp"
|
||||
#include "cds/cdsConfig.hpp"
|
||||
@@ -3855,6 +3859,34 @@ void Arguments::set_compact_headers_flags() {
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __linux
|
||||
static const char * get_toolkit_name() {
|
||||
const char * toolkit_name = "XToolkit";
|
||||
void* libwayland = dlopen(VERSIONED_JNI_LIB_NAME("wayland-client", "0"), RTLD_LAZY | RTLD_LOCAL);
|
||||
if (!libwayland) {
|
||||
// Fallback to any development version available on the system
|
||||
libwayland = dlopen(JNI_LIB_NAME("wayland-client"), RTLD_LAZY | RTLD_LOCAL);
|
||||
}
|
||||
if (libwayland) {
|
||||
typedef void* (*wl_display_connect_t)(const char*);
|
||||
typedef void (*wl_display_disconnect_t)(void*);
|
||||
|
||||
wl_display_connect_t fp_wl_display_connect = (wl_display_connect_t) dlsym(libwayland, "wl_display_connect");
|
||||
wl_display_disconnect_t fp_wl_display_disconnect = (wl_display_disconnect_t) dlsym(libwayland, "wl_display_disconnect");
|
||||
|
||||
if (fp_wl_display_connect && fp_wl_display_disconnect) {
|
||||
void* display = fp_wl_display_connect(NULL);
|
||||
if (display) {
|
||||
toolkit_name = "WLToolkit";
|
||||
fp_wl_display_disconnect(display);
|
||||
}
|
||||
}
|
||||
dlclose(libwayland);
|
||||
}
|
||||
return toolkit_name;
|
||||
}
|
||||
#endif
|
||||
|
||||
jint Arguments::apply_ergo() {
|
||||
// Set flags based on ergonomics.
|
||||
jint result = set_ergonomics_flags();
|
||||
@@ -3925,6 +3957,17 @@ jint Arguments::apply_ergo() {
|
||||
FLAG_SET_DEFAULT(BytecodeVerificationRemote, true);
|
||||
}
|
||||
|
||||
#ifdef __linux
|
||||
// Replace -Dawt.toolkit.name=auto with either XToolkit (the default) or
|
||||
// WLToolkit, if we are able to connect to the Wayland server.
|
||||
const char* toolkit_name = PropertyList_get_value(_system_properties, "awt.toolkit.name");
|
||||
if (toolkit_name && strcmp(toolkit_name, "auto") == 0) {
|
||||
const char* toolkit_name = get_toolkit_name();
|
||||
PropertyList_unique_add(&_system_properties, "awt.toolkit.name", toolkit_name,
|
||||
AddProperty, WriteableProperty, ExternalProperty);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef PRODUCT
|
||||
if (!LogVMOutput && FLAG_IS_DEFAULT(LogVMOutput)) {
|
||||
if (use_vm_log()) {
|
||||
|
||||
@@ -164,7 +164,7 @@ public abstract class FullFrameDecorationHelper extends FrameDecoration {
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
assert isRepaintNeeded();
|
||||
assert isRepaintNeeded() : "paint() called when no repaint needed";
|
||||
|
||||
int width = peer.getWidth();
|
||||
int height = peer.getHeight();
|
||||
@@ -196,7 +196,7 @@ public abstract class FullFrameDecorationHelper extends FrameDecoration {
|
||||
}
|
||||
|
||||
private boolean isSignificantDrag(Point p) {
|
||||
assert EventQueue.isDispatchThread();
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
Objects.requireNonNull(p);
|
||||
return pressedLocation != null && isSignificantDragDistance(pressedLocation, p);
|
||||
@@ -208,7 +208,7 @@ public abstract class FullFrameDecorationHelper extends FrameDecoration {
|
||||
|
||||
@Override
|
||||
boolean processMouseEvent(MouseEvent e) {
|
||||
assert EventQueue.isDispatchThread();
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
if (super.processMouseEvent(e)) return true;
|
||||
|
||||
@@ -326,7 +326,7 @@ public abstract class FullFrameDecorationHelper extends FrameDecoration {
|
||||
}
|
||||
|
||||
private boolean processMouseEvent(MouseEvent e) {
|
||||
assert EventQueue.isDispatchThread();
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
Rectangle buttonBounds = bounds.get();
|
||||
boolean ourLocation = buttonBounds != null && e.getID() != MouseEvent.MOUSE_EXITED &&
|
||||
|
||||
@@ -68,7 +68,7 @@ public class GtkFrameDecoration extends FullFrameDecorationHelper {
|
||||
public GtkFrameDecoration(WLDecoratedPeer peer, boolean showMinimize, boolean showMaximize) {
|
||||
super(peer, showMinimize, showMaximize);
|
||||
nativePtr = nativeCreateDecoration(showMinimize, showMaximize, isDarkTheme());
|
||||
assert nativePtr != 0;
|
||||
assert nativePtr != 0 : "Failed to create the native part of the decoration";
|
||||
int t = nativeGetIntProperty(nativePtr, "gtk-dnd-drag-threshold");
|
||||
dndThreshold = t > 0 ? t : 4;
|
||||
}
|
||||
@@ -87,8 +87,8 @@ public class GtkFrameDecoration extends FullFrameDecorationHelper {
|
||||
int width = peer.getWidth();
|
||||
int height = titleBarHeight;
|
||||
|
||||
assert width >= titleBarMinWidth;
|
||||
assert peer.getHeight() >= titleBarHeight;
|
||||
assert width >= titleBarMinWidth : "The frame width is too small to display the title bar";
|
||||
assert peer.getHeight() >= titleBarHeight : "The frame height is too small to display the title bar";
|
||||
|
||||
double scale = ((WLGraphicsConfig) peer.getGraphicsConfiguration()).getEffectiveScale();
|
||||
g2d.setBackground(new Color(0, true));
|
||||
|
||||
@@ -96,7 +96,7 @@ public class ServerSideFrameDecoration extends FrameDecoration {
|
||||
@Override
|
||||
public void dispose() {
|
||||
// Native resources must have been already disposed when the window was hidden
|
||||
assert nativeDecorPtr == 0;
|
||||
assert nativeDecorPtr == 0 : "Native resources must have been already disposed";
|
||||
}
|
||||
|
||||
private native long createToplevelDecorationImpl(long nativeFramePtr);
|
||||
|
||||
@@ -88,6 +88,8 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.wl.focus.WLComponentPeer");
|
||||
private static final PlatformLogger popupLog = PlatformLogger.getLogger("sun.awt.wl.popup.WLComponentPeer");
|
||||
|
||||
public static final String POPUP_POSITION_UNCONSTRAINED_CLIENT_PROPERTY = "wlawt.popup_position_unconstrained";
|
||||
|
||||
protected static final int MINIMUM_WIDTH = 1;
|
||||
protected static final int MINIMUM_HEIGHT = 1;
|
||||
|
||||
@@ -318,7 +320,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
if (what.getMinY() >= where.getMaxY()) {
|
||||
what.y -= what.getMinY() - where.getMaxY();
|
||||
}
|
||||
assert what.intersects(where);
|
||||
assert what.intersects(where) : String.format("Failed to move %s to overlap %s", what, where);
|
||||
}
|
||||
|
||||
Point nativeLocationForPopup(Window popup, Component popupParent, Window toplevel) {
|
||||
@@ -351,6 +353,18 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
return popupBounds.getLocation();
|
||||
}
|
||||
|
||||
private boolean isPopupPositionUnconstrained() {
|
||||
if (SunToolkit.isInstanceOf(target, "javax.swing.RootPaneContainer")) {
|
||||
javax.swing.JRootPane rootpane = ((javax.swing.RootPaneContainer) target).getRootPane();
|
||||
Object prop = rootpane.getClientProperty(POPUP_POSITION_UNCONSTRAINED_CLIENT_PROPERTY);
|
||||
if (prop instanceof Boolean booleanProp) {
|
||||
return booleanProp;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void wlSetVisible(boolean v) {
|
||||
// TODO: this whole method should be moved to WLWindowPeer
|
||||
synchronized (getStateLock()) {
|
||||
@@ -370,9 +384,10 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
: Frame.NORMAL;
|
||||
boolean isMaximized = (state & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH;
|
||||
boolean isMinimized = (state & Frame.ICONIFIED) == Frame.ICONIFIED;
|
||||
boolean isUnconstrained = isPopupPositionUnconstrained();
|
||||
|
||||
performLocked(() -> {
|
||||
assert wlSurface == null;
|
||||
assert wlSurface == null : "Invisible window already has a Wayland surface attached";
|
||||
wlSurface = new WLMainSurface((WLWindowPeer) this);
|
||||
long wlSurfacePtr = wlSurface.getWlSurfacePtr();
|
||||
if (isWlPopup) {
|
||||
@@ -381,7 +396,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
Window toplevel = getToplevelFor(popupParent);
|
||||
Point nativeLocation = nativeLocationForPopup(popup, popupParent, toplevel);
|
||||
nativeCreatePopup(nativePtr, getNativePtrFor(toplevel), wlSurfacePtr,
|
||||
thisWidth, thisHeight, nativeLocation.x, nativeLocation.y);
|
||||
thisWidth, thisHeight, nativeLocation.x, nativeLocation.y, isUnconstrained);
|
||||
} else {
|
||||
nativeCreateWindow(nativePtr, getParentNativePtr(target), wlSurfacePtr,
|
||||
isModal, isMaximized, isMinimized, title, WLToolkit.getApplicationID());
|
||||
@@ -462,7 +477,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
|
||||
@Override
|
||||
public void updateSurfaceSize() {
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread();
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread() : "This method must be invoked while holding the AWT lock";
|
||||
// Note: must be called after a buffer of proper size has been attached to the surface,
|
||||
// but the surface has not yet been committed. Otherwise, the sizes will get out of sync,
|
||||
// which may result in visual artifacts.
|
||||
@@ -500,7 +515,8 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
final Component popupParent = AWTAccessor.getWindowAccessor().getPopupParent(popup);
|
||||
final Window toplevel = getToplevelFor(popupParent);
|
||||
Point nativeLocation = nativeLocationForPopup(popup, popupParent, toplevel);
|
||||
nativeRepositionWLPopup(nativePtr, surfaceWidth, surfaceHeight, nativeLocation.x, nativeLocation.y);
|
||||
boolean isUnconstrained = isPopupPositionUnconstrained();
|
||||
nativeRepositionWLPopup(nativePtr, surfaceWidth, surfaceHeight, nativeLocation.x, nativeLocation.y, isUnconstrained);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -894,7 +910,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
// a button press, key press, or touch down event."
|
||||
// So 'serial' must appertain to such an event.
|
||||
|
||||
assert serial != 0;
|
||||
assert serial != 0 : "The serial number of the event requesting the window menu must be non-zero";
|
||||
|
||||
int xNative = javaUnitsToSurfaceUnits(x);
|
||||
int yNative = javaUnitsToSurfaceUnits(y);
|
||||
@@ -954,7 +970,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
WLToolkit.targetDisposedPeer(target, this);
|
||||
|
||||
performLocked(() -> {
|
||||
assert !isVisible();
|
||||
assert !isVisible() : "Disposed window must have been already hidden";
|
||||
|
||||
nativeDisposeFrame(nativePtr);
|
||||
nativePtr = 0;
|
||||
@@ -1150,12 +1166,14 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
String title, String appID);
|
||||
|
||||
protected native void nativeCreatePopup(long ptr, long parentPtr, long wlSurfacePtr,
|
||||
int width, int height,
|
||||
int offsetX, int offsetY);
|
||||
int width, int height,
|
||||
int offsetX, int offsetY,
|
||||
boolean isUnconstrained);
|
||||
|
||||
protected native void nativeRepositionWLPopup(long ptr,
|
||||
int width, int height,
|
||||
int offsetX, int offsetY);
|
||||
int offsetX, int offsetY,
|
||||
boolean isUnconstrained);
|
||||
protected native void nativeHideFrame(long ptr);
|
||||
|
||||
protected native void nativeDisposeFrame(long ptr);
|
||||
@@ -1355,7 +1373,8 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
}
|
||||
|
||||
if (verticalMWERoundRotations != 0 || verticalMWEPreciseRotations != 0) {
|
||||
assert(verticalMWEScrollAmount > 0);
|
||||
assert verticalMWEScrollAmount > 0
|
||||
: String.format("Vertical scrolling event has negative scroll amount: %d", verticalMWEScrollAmount);
|
||||
|
||||
final MouseEvent mouseEvent = new MouseWheelEvent(getTarget(),
|
||||
MouseEvent.MOUSE_WHEEL,
|
||||
@@ -1374,7 +1393,8 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
}
|
||||
|
||||
if (horizontalMWERoundRotations != 0 || horizontalMWEPreciseRotations != 0) {
|
||||
assert(horizontalMWEScrollAmount > 0);
|
||||
assert horizontalMWEScrollAmount > 0
|
||||
: String.format("Horizontal scrolling event has negative scroll amount: %d", horizontalMWEScrollAmount);;
|
||||
|
||||
final MouseEvent mouseEvent = new MouseWheelEvent(getTarget(),
|
||||
MouseEvent.MOUSE_WHEEL,
|
||||
@@ -1585,7 +1605,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
// "This request must be used in response to some sort of user action like a button press,
|
||||
// key press, or touch down event. The passed serial is used to determine the type
|
||||
// of interactive move (touch, pointer, etc)."
|
||||
assert serial != 0;
|
||||
assert serial != 0 : "The serial number of the event requesting the drag must be non-zero";
|
||||
|
||||
performLocked(() -> nativeStartDrag(serial, nativePtr));
|
||||
}
|
||||
@@ -1594,7 +1614,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
// "This request must be used in response to some sort of user action like a button press,
|
||||
// key press, or touch down event. The passed serial is used to determine the type
|
||||
// of interactive resize (touch, pointer, etc)."
|
||||
assert serial != 0;
|
||||
assert serial != 0 : "The serial number of the event requesting the resize must be non-zero";
|
||||
|
||||
performLocked(() -> nativeStartResize(serial, nativePtr, edges));
|
||||
}
|
||||
@@ -1674,7 +1694,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
|
||||
void notifyConfigured(int newSurfaceX, int newSurfaceY, int newSurfaceWidth, int newSurfaceHeight,
|
||||
boolean active, boolean maximized, boolean fullscreen) {
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread();
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread() : "This method must be invoked while holding the AWT lock";
|
||||
|
||||
// NB: The width and height, as well as X and Y arguments, specify the size and the location
|
||||
// of the window in surface-local coordinates.
|
||||
@@ -1755,12 +1775,12 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
}
|
||||
|
||||
void notifyPopupDone() {
|
||||
assert(targetIsWlPopup());
|
||||
assert targetIsWlPopup() : "This method must be invoked only for popups";
|
||||
target.setVisible(false);
|
||||
}
|
||||
|
||||
void checkIfOnNewScreen() {
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread();
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread() : "This method must be invoked while holding the AWT lock";
|
||||
|
||||
if (wlSurface == null) return;
|
||||
final WLGraphicsDevice newDevice = wlSurface.getGraphicsDevice();
|
||||
@@ -2005,7 +2025,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
|
||||
@Override
|
||||
public void updateSurfaceSize() {
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread();
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread() : "This method must be invoked while holding the AWT lock";
|
||||
|
||||
shadowSurface.updateSurfaceSize(shadowWlSize.getSurfaceWidth(), shadowWlSize.getSurfaceHeight());
|
||||
}
|
||||
@@ -2017,8 +2037,8 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
}
|
||||
|
||||
public void createSurface() {
|
||||
assert shadowSurface == null;
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread();
|
||||
assert shadowSurface == null : "The shadow surface must not be created twice";
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread() : "This method must be invoked while holding the AWT lock";
|
||||
|
||||
int shadowOffset = -javaUnitsToSurfaceUnits(shadowSize);
|
||||
shadowSurface = new WLSubSurface(wlSurface, shadowOffset, shadowOffset);
|
||||
@@ -2026,13 +2046,13 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
|
||||
public void commitSurface() {
|
||||
assert shadowSurface != null;
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread();
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread() : "This method must be invoked while holding the AWT lock";
|
||||
|
||||
shadowSurface.commit();
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread();
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread() : "This method must be invoked while holding the AWT lock";
|
||||
|
||||
if (shadowSurface != null) {
|
||||
shadowSurface.dispose();
|
||||
@@ -2047,7 +2067,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread();
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread() : "This method must be invoked while holding the AWT lock";
|
||||
|
||||
if (shadowSurface != null) {
|
||||
shadowSurface.dispose();
|
||||
@@ -2056,7 +2076,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
}
|
||||
|
||||
public void updateSurfaceData() {
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread();
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread() : "This method must be invoked while holding the AWT lock";
|
||||
|
||||
needsRepaint = true;
|
||||
SurfaceData.convertTo(WLSurfaceDataExt.class, shadowSurfaceData).revalidate(
|
||||
@@ -2064,7 +2084,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
}
|
||||
|
||||
public void paint() {
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread();
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread() : "This method must be invoked while holding the AWT lock";
|
||||
|
||||
if (!needsRepaint) {
|
||||
return;
|
||||
@@ -2090,7 +2110,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
|
||||
public void notifyConfigured(boolean active, boolean maximized, boolean fullscreen) {
|
||||
assert shadowSurface != null;
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread();
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread() : "This method must be invoked while holding the AWT lock";
|
||||
|
||||
needsRepaint |= active ^ isActive;
|
||||
|
||||
|
||||
@@ -77,7 +77,8 @@ public class WLDataOffer {
|
||||
|
||||
fd = openReceivePipe(nativePtr, mime);
|
||||
|
||||
assert(fd != -1); // Otherwise an exception should be thrown from native code
|
||||
// Otherwise an exception should be thrown from native code
|
||||
assert fd != -1 : "An invalid file descriptor received from the native code";
|
||||
|
||||
FileDescriptor javaFD = new FileDescriptor();
|
||||
jdk.internal.access.SharedSecrets.getJavaIOFileDescriptorAccess().set(javaFD, fd);
|
||||
|
||||
@@ -53,7 +53,7 @@ public class WLDataSource {
|
||||
var wlDataTransferer = (WLDataTransferer) WLDataTransferer.getInstance();
|
||||
|
||||
nativePtr = initNative(dataDevice.getNativePtr(), protocol);
|
||||
assert nativePtr != 0; // should've already thrown in native
|
||||
assert nativePtr != 0 : "Failed to initialize the native part of the source"; // should've already thrown in native
|
||||
this.data = data;
|
||||
|
||||
try {
|
||||
|
||||
@@ -128,10 +128,10 @@ public class WLGraphicsDevice extends GraphicsDevice {
|
||||
int widthLogical, int heightLogical,
|
||||
int widthMm, int heightMm,
|
||||
int displayScale) {
|
||||
assert width > 0 && height > 0;
|
||||
assert widthLogical > 0 && heightLogical > 0;
|
||||
assert widthMm > 0 && heightMm > 0;
|
||||
assert displayScale > 0;
|
||||
assert width > 0 && height > 0 : String.format("Invalid device size: %dx%d", width, height);
|
||||
assert widthLogical > 0 && heightLogical > 0 : String.format("Invalid logical device size: %dx%d", widthLogical, heightLogical);
|
||||
assert widthMm > 0 && heightMm > 0 : String.format("Invalid physical device size: %dx%d", widthMm, heightMm);
|
||||
assert displayScale > 0 : String.format("Invalid display scale: %d", displayScale);
|
||||
|
||||
this.wlID = id;
|
||||
this.name = name;
|
||||
@@ -176,10 +176,10 @@ public class WLGraphicsDevice extends GraphicsDevice {
|
||||
int widthLogical, int heightLogical,
|
||||
int widthMm, int heightMm,
|
||||
int scale) {
|
||||
assert width > 0 && height > 0;
|
||||
assert widthLogical > 0 && heightLogical > 0;
|
||||
assert widthMm > 0 && heightMm > 0;
|
||||
assert scale > 0;
|
||||
assert width > 0 && height > 0 : String.format("Invalid device size: %dx%d", width, height);
|
||||
assert widthLogical > 0 && heightLogical > 0 : String.format("Invalid logical device size: %dx%d", widthLogical, heightLogical);
|
||||
assert widthMm > 0 && heightMm > 0 : String.format("Invalid physical device size: %dx%d", widthMm, heightMm);
|
||||
assert scale > 0 : String.format("Invalid display scale: %d", scale);
|
||||
|
||||
this.name = name;
|
||||
this.x = x;
|
||||
|
||||
@@ -133,8 +133,16 @@ public class WLGraphicsEnvironment extends SunGraphicsEnvironment implements HiD
|
||||
}
|
||||
|
||||
// Logical size comes from an optional protocol, so take the data from the main one, if absent
|
||||
if (widthLogical == 0) widthLogical = width;
|
||||
if (heightLogical == 0) heightLogical = height;
|
||||
if (widthLogical <= 0) widthLogical = width;
|
||||
if (heightLogical <= 0) heightLogical = height;
|
||||
|
||||
// Physical size may be absent for virtual outputs.
|
||||
if (widthMm <= 0 || heightMm <= 0) {
|
||||
// Assume a 92 DPI display
|
||||
widthMm = (int) Math.ceil(25.4 * width / 92.0);
|
||||
heightMm = (int) Math.ceil(25.4 * height / 92.0);
|
||||
}
|
||||
|
||||
String humanID = deviceNameFrom(name, make, model);
|
||||
|
||||
WLGraphicsDevice gd = deviceWithID(wlID);
|
||||
|
||||
@@ -242,7 +242,9 @@ record WLInputState(WLPointerEvent eventWithSurface,
|
||||
WLPointerEvent newEventWithTimestamp,
|
||||
WLPointerEvent newEventWithPosition) {
|
||||
if (pointerEvent.hasButtonEvent() && pointerEvent.getIsButtonPressed() && newEventWithSurface != null) {
|
||||
assert newEventWithTimestamp != null && newEventWithPosition != null;
|
||||
assert newEventWithTimestamp != null && newEventWithPosition != null
|
||||
: "Events with timestamp and position are both required to be present";
|
||||
|
||||
int clickCount = 1;
|
||||
final boolean pressedSameButton = pointerButtonPressedEvent != null
|
||||
&& pointerEvent.getButtonCode() == pointerButtonPressedEvent.linuxCode;
|
||||
|
||||
@@ -48,7 +48,7 @@ class WLKeyboard {
|
||||
// called from native code
|
||||
void setRepeatInfo(int charsPerSecond, int delayMillis) {
|
||||
// this function receives (0, 0) when key repeat is disabled
|
||||
assert EventQueue.isDispatchThread();
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
this.delayBeforeRepeatMillis = delayMillis;
|
||||
if (charsPerSecond > 0) {
|
||||
this.delayBetweenRepeatMillis = (int) (1000.0 / charsPerSecond);
|
||||
@@ -64,7 +64,7 @@ class WLKeyboard {
|
||||
}
|
||||
|
||||
void cancelRepeat() {
|
||||
assert EventQueue.isDispatchThread();
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
if (currentRepeatTask != null) {
|
||||
currentRepeatTask.cancel();
|
||||
currentRepeatTask = null;
|
||||
@@ -74,7 +74,7 @@ class WLKeyboard {
|
||||
|
||||
// called from native code
|
||||
void stopRepeat(int keycode) {
|
||||
assert EventQueue.isDispatchThread();
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
if (currentRepeatKeycode == keycode) {
|
||||
cancelRepeat();
|
||||
}
|
||||
@@ -82,7 +82,7 @@ class WLKeyboard {
|
||||
|
||||
// called from native code
|
||||
void startRepeat(long serial, long timestamp, int keycode) {
|
||||
assert EventQueue.isDispatchThread();
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
cancelRepeat();
|
||||
if (keycode == 0 || !isRepeatEnabled()) {
|
||||
return;
|
||||
@@ -123,7 +123,7 @@ class WLKeyboard {
|
||||
public native boolean isNumLockPressed();
|
||||
|
||||
public void onLostFocus() {
|
||||
assert EventQueue.isDispatchThread();
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
keyRepeatManager.cancelRepeat();
|
||||
cancelCompose();
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ public class WLMainSurface extends WLSurface {
|
||||
}
|
||||
|
||||
public void activateByAnotherSurface(long serial, long activatingSurfacePtr) {
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread();
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread() : "This method must be invoked while holding the AWT lock";
|
||||
assertIsValid();
|
||||
|
||||
nativeActivate(getNativePtr(), serial, activatingSurfacePtr);
|
||||
|
||||
@@ -217,37 +217,37 @@ class WLPointerEvent {
|
||||
}
|
||||
|
||||
public long getSurface() {
|
||||
assert hasSurface();
|
||||
assert hasSurface() : "The event must have a valid surface";
|
||||
return surface;
|
||||
}
|
||||
|
||||
public long getSerial() {
|
||||
assert hasSerial();
|
||||
assert hasSerial() : "The event must have a valid serial";
|
||||
return serial;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
assert hasTimestamp();
|
||||
assert hasTimestamp() : "The event must have a valid timestamp";
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public int getSurfaceX() {
|
||||
assert hasCoordinates();
|
||||
assert hasCoordinates() : "The event must have valid coordinates";
|
||||
return surface_x;
|
||||
}
|
||||
|
||||
public int getSurfaceY() {
|
||||
assert hasCoordinates();
|
||||
assert hasCoordinates() : "The event must have valid coordinates";
|
||||
return surface_y;
|
||||
}
|
||||
|
||||
public int getButtonCode() {
|
||||
assert hasButtonEvent();
|
||||
assert hasButtonEvent() : "Must have a button event to get the button code";
|
||||
return buttonCode;
|
||||
}
|
||||
|
||||
public boolean getIsButtonPressed() {
|
||||
assert hasButtonEvent();
|
||||
assert hasButtonEvent() : "Must have a button event to get the button state";
|
||||
return isButtonPressed;
|
||||
}
|
||||
|
||||
@@ -270,12 +270,12 @@ class WLPointerEvent {
|
||||
}
|
||||
|
||||
public double getXAxisVectorValue() {
|
||||
assert xAxisHasVectorValue();
|
||||
assert xAxisHasVectorValue() : "Must have an X axis vector value";
|
||||
return xAxis_vectorValue;
|
||||
}
|
||||
|
||||
public int getXAxisSteps120Value() {
|
||||
assert xAxisHasSteps120Value();
|
||||
assert xAxisHasSteps120Value() : "Must have an X axis steps120 value";
|
||||
return xAxis_steps120Value;
|
||||
}
|
||||
|
||||
@@ -298,12 +298,12 @@ class WLPointerEvent {
|
||||
}
|
||||
|
||||
public double getYAxisVectorValue() {
|
||||
assert yAxisHasVectorValue();
|
||||
assert yAxisHasVectorValue() : "Must have an Y axis vector value";
|
||||
return yAxis_vectorValue;
|
||||
}
|
||||
|
||||
public int getYAxisSteps120Value() {
|
||||
assert yAxisHasSteps120Value();
|
||||
assert yAxisHasSteps120Value(): "Must have an Y axis steps120 value";
|
||||
return yAxis_steps120Value;
|
||||
}
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ public class WLRobotPeer implements RobotPeer {
|
||||
static Point getLocationOfWLSurface(WLSurface wlSurface) {
|
||||
checkExtensionPresent();
|
||||
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread();
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread() : "This method must be invoked while holding the AWT lock";
|
||||
|
||||
final long wlSurfacePtr = wlSurface.getWlSurfacePtr();
|
||||
// The native implementation allows for just one such request at a time
|
||||
|
||||
@@ -57,7 +57,7 @@ public class WLSurface {
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread();
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread() : "This method must be invoked while holding the AWT lock";
|
||||
|
||||
if (isValid) {
|
||||
hide();
|
||||
@@ -67,7 +67,7 @@ public class WLSurface {
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread();
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread() : "This method must be invoked while holding the AWT lock";
|
||||
assertIsValid();
|
||||
|
||||
if (surfaceData == null) return;
|
||||
@@ -85,14 +85,14 @@ public class WLSurface {
|
||||
}
|
||||
|
||||
public boolean hasSurfaceData() {
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread();
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread() : "This method must be invoked while holding the AWT lock";
|
||||
assertIsValid();
|
||||
|
||||
return surfaceData != null;
|
||||
}
|
||||
|
||||
public void associateWithSurfaceData(SurfaceData data) {
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread();
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread() : "This method must be invoked while holding the AWT lock";
|
||||
Objects.requireNonNull(data);
|
||||
assertIsValid();
|
||||
|
||||
@@ -103,7 +103,7 @@ public class WLSurface {
|
||||
}
|
||||
|
||||
public void commit() {
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread();
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread() : "This method must be invoked while holding the AWT lock";
|
||||
assertIsValid();
|
||||
|
||||
nativeCommitWlSurface(nativePtr);
|
||||
@@ -115,28 +115,28 @@ public class WLSurface {
|
||||
* @return a pointer to wl_surface native object
|
||||
*/
|
||||
public long getWlSurfacePtr() {
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread();
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread() : "This method must be invoked while holding the AWT lock";
|
||||
assertIsValid();
|
||||
|
||||
return wlSurfacePtr;
|
||||
}
|
||||
|
||||
protected long getNativePtr() {
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread();
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread() : "This method must be invoked while holding the AWT lock";
|
||||
assertIsValid();
|
||||
|
||||
return nativePtr;
|
||||
}
|
||||
|
||||
public void setSize(int width, int height) {
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread();
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread() : "This method must be invoked while holding the AWT lock";
|
||||
assertIsValid();
|
||||
|
||||
nativeSetSize(nativePtr, width, height);
|
||||
}
|
||||
|
||||
public void setOpaqueRegion(int x, int y, int width, int height) {
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread();
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread() : "This method must be invoked while holding the AWT lock";
|
||||
assertIsValid();
|
||||
|
||||
nativeSetOpaqueRegion(nativePtr, x, y, width, height);
|
||||
@@ -151,7 +151,7 @@ public class WLSurface {
|
||||
}
|
||||
|
||||
public void updateSurfaceSize(int surfaceWidth, int surfaceHeight) {
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread();
|
||||
assert SunToolkit.isAWTLockHeldByCurrentThread() : "This method must be invoked while holding the AWT lock";
|
||||
assertIsValid();
|
||||
|
||||
setSize(surfaceWidth, surfaceHeight);
|
||||
|
||||
@@ -331,7 +331,7 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
|
||||
|
||||
private static void dispatchPointerEvent(WLPointerEvent e) {
|
||||
// Invoked from the native code
|
||||
assert EventQueue.isDispatchThread();
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) log.fine("dispatchPointerEvent: " + e);
|
||||
|
||||
@@ -362,7 +362,7 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
|
||||
char keyChar,
|
||||
int modifiers) {
|
||||
// Invoked from the native code
|
||||
assert EventQueue.isDispatchThread();
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
inputState = inputState.updatedFromKeyEvent(serial);
|
||||
|
||||
@@ -425,14 +425,14 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
|
||||
}
|
||||
|
||||
private static void dispatchKeyboardModifiersEvent(long serial) {
|
||||
assert EventQueue.isDispatchThread();
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
inputState = inputState.updatedFromKeyboardModifiersEvent(serial, keyboard.getModifiers());
|
||||
WLDropTargetContextPeer.getInstance().handleModifiersUpdate();
|
||||
}
|
||||
|
||||
private static void dispatchKeyboardEnterEvent(long serial, long surfacePtr) {
|
||||
// Invoked from the native code
|
||||
assert EventQueue.isDispatchThread();
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
if (logKeys.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
logKeys.fine("dispatchKeyboardEnterEvent: " + serial + ", surface 0x"
|
||||
@@ -461,7 +461,7 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
|
||||
|
||||
private static void dispatchKeyboardLeaveEvent(long serial, long surfacePtr) {
|
||||
// Invoked from the native code
|
||||
assert EventQueue.isDispatchThread();
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
if (logKeys.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
logKeys.fine("dispatchKeyboardLeaveEvent: " + serial + ", surface 0x"
|
||||
|
||||
@@ -67,7 +67,7 @@ class ClientComponentCaretPositionTracker implements ComponentListener, CaretLis
|
||||
|
||||
|
||||
public void startTracking(final Component component) {
|
||||
assert(EventQueue.isDispatchThread());
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
if (log.isLoggable(PlatformLogger.Level.FINER)) {
|
||||
log.finer(
|
||||
@@ -108,7 +108,7 @@ class ClientComponentCaretPositionTracker implements ComponentListener, CaretLis
|
||||
}
|
||||
|
||||
public void stopTrackingCurrentComponent() {
|
||||
assert(EventQueue.isDispatchThread());
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
if (log.isLoggable(PlatformLogger.Level.FINER)) {
|
||||
log.finer(String.format("stopTrackingCurrentComponent(): this=%s.", this), new Throwable("Stacktrace"));
|
||||
@@ -160,7 +160,7 @@ class ClientComponentCaretPositionTracker implements ComponentListener, CaretLis
|
||||
}
|
||||
|
||||
public Component getTrackedComponentIfTracking() {
|
||||
assert(EventQueue.isDispatchThread());
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
final Component trackedComponentStrong;
|
||||
if (trackedComponent == null) {
|
||||
@@ -188,7 +188,7 @@ class ClientComponentCaretPositionTracker implements ComponentListener, CaretLis
|
||||
|
||||
|
||||
public void deferUpdates() {
|
||||
assert(EventQueue.isDispatchThread());
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
if (log.isLoggable(PlatformLogger.Level.FINER)) {
|
||||
log.finer(String.format("deferUpdates(): this=%s.", this), new Throwable("Stacktrace"));
|
||||
@@ -198,7 +198,7 @@ class ClientComponentCaretPositionTracker implements ComponentListener, CaretLis
|
||||
}
|
||||
|
||||
public void resumeUpdates(final boolean discardDeferredUpdates) {
|
||||
assert(EventQueue.isDispatchThread());
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
if (log.isLoggable(PlatformLogger.Level.FINER)) {
|
||||
log.finer(String.format("resumeUpdates(%b): this=%s.", discardDeferredUpdates, this), new Throwable("Stacktrace"));
|
||||
@@ -215,7 +215,7 @@ class ClientComponentCaretPositionTracker implements ComponentListener, CaretLis
|
||||
}
|
||||
|
||||
public boolean areUpdatesDeferred() {
|
||||
assert(EventQueue.isDispatchThread());
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
return updatesAreDeferred;
|
||||
}
|
||||
@@ -225,7 +225,7 @@ class ClientComponentCaretPositionTracker implements ComponentListener, CaretLis
|
||||
|
||||
/** This method is intended to be called from the owning IM's {@link java.awt.im.spi.InputMethod#dispatchEvent(AWTEvent)}. */
|
||||
public void onIMDispatchEvent(AWTEvent event) {
|
||||
assert(EventQueue.isDispatchThread());
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
if (log.isLoggable(PlatformLogger.Level.FINER)) {
|
||||
log.finer("onIMDispatchEvent(event={0}): this={1}.", event, this);
|
||||
@@ -254,7 +254,7 @@ class ClientComponentCaretPositionTracker implements ComponentListener, CaretLis
|
||||
|
||||
/** This method is intended to be called from the owning IM's {@link java.awt.im.spi.InputMethod#notifyClientWindowChange(Rectangle)}. */
|
||||
public void onIMNotifyClientWindowChange(Rectangle location) {
|
||||
assert(EventQueue.isDispatchThread());
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
if (log.isLoggable(PlatformLogger.Level.FINER)) {
|
||||
log.finer("onIMNotifyClientWindowChange(location={0}): this={1}.", location, this);
|
||||
@@ -333,7 +333,7 @@ class ClientComponentCaretPositionTracker implements ComponentListener, CaretLis
|
||||
|
||||
|
||||
private WLInputMethodZwpTextInputV3 getOwnerIm() {
|
||||
assert(EventQueue.isDispatchThread());
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
final WLInputMethodZwpTextInputV3 thisImStrong;
|
||||
if (this.im == null) {
|
||||
|
||||
@@ -40,7 +40,7 @@ final class InputContextState {
|
||||
|
||||
|
||||
public InputContextState(long nativeContextPtr) {
|
||||
assert(nativeContextPtr != 0);
|
||||
assert nativeContextPtr != 0 : "Cannot create an input context from a NULL pointer";
|
||||
|
||||
this.nativeContextPtr = nativeContextPtr;
|
||||
}
|
||||
|
||||
@@ -82,8 +82,8 @@ record JavaPreeditString(String text, int cursorBeginCodeUnit, int cursorEndCode
|
||||
}
|
||||
|
||||
if (resultText == null) {
|
||||
assert(fixedCursorBeginUtf8Byte == 0);
|
||||
assert(fixedCursorEndUtf8Byte == 0);
|
||||
assert fixedCursorBeginUtf8Byte == 0 : "Cursor begin byte must be zero for an empty string";
|
||||
assert fixedCursorEndUtf8Byte == 0 : "Cursor end byte must be zero for an empty string";
|
||||
|
||||
return JavaPreeditString.EMPTY;
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ public final class WLInputMethodDescriptorZwpTextInputV3 implements InputMethodD
|
||||
|
||||
@Override
|
||||
public String getInputMethodDisplayName(Locale inputLocale, Locale displayLanguage) {
|
||||
assert isAvailableOnPlatform();
|
||||
assert isAvailableOnPlatform() : "IM must be available on the platform";
|
||||
|
||||
// This is how it's implemented in all other Toolkits.
|
||||
//
|
||||
@@ -183,7 +183,7 @@ public final class WLInputMethodDescriptorZwpTextInputV3 implements InputMethodD
|
||||
|
||||
|
||||
private WLInputMethodDescriptorZwpTextInputV3() {
|
||||
assert isAvailableOnPlatform();
|
||||
assert isAvailableOnPlatform() : "IM must be available on the platform";
|
||||
|
||||
initAndGetToolkitStartupLocale();
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
}
|
||||
|
||||
// "The method is only called when the input method is inactive."
|
||||
assert(this.awtActivationStatus != AWTActivationStatus.ACTIVATED);
|
||||
assert this.awtActivationStatus != AWTActivationStatus.ACTIVATED : "The method is called when the IM is active";
|
||||
|
||||
// The protocol doesn't provide a separate method for hiding the IM window(s),
|
||||
// but this effect can be achieved by disabling the native context.
|
||||
@@ -259,7 +259,7 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
}
|
||||
|
||||
// "The method is only called when the input method is inactive."
|
||||
assert(this.awtActivationStatus != AWTActivationStatus.ACTIVATED);
|
||||
assert this.awtActivationStatus != AWTActivationStatus.ACTIVATED : "The method is called when the IM is active";
|
||||
|
||||
wlDisableContextNow();
|
||||
}
|
||||
@@ -374,10 +374,10 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
/* AWT-side methods section */
|
||||
|
||||
private static void awtFillWlContentTypeOf(Component component, OutgoingChanges out) {
|
||||
assert(component != null);
|
||||
assert(out != null);
|
||||
assert component != null : "Component must not be null";
|
||||
assert out != null : "OutgoingChanges must not be null";
|
||||
|
||||
assert(EventQueue.isDispatchThread());
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
// TODO: there's no dedicated AWT/Swing API for that, but we can make a few guesses, e.g.
|
||||
// (component instanceof JPasswordField) ? ContentPurpose.PASSWORD
|
||||
@@ -389,7 +389,7 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
* compatible with {@code zwp_text_input_v3::set_cursor_rectangle} API;
|
||||
*/
|
||||
private static Rectangle awtGetWlCursorRectangleOf(Component component) {
|
||||
assert EventQueue.isDispatchThread();
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
Rectangle result = null;
|
||||
|
||||
@@ -434,7 +434,7 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
* @throws IllegalArgumentException if {@code visibleComponent} is {@code null} or isn't showing on the screen.
|
||||
*/
|
||||
private static Rectangle awtGetCaretOf(Component visibleComponent) {
|
||||
assert(EventQueue.isDispatchThread());
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
if (!Objects.requireNonNull(visibleComponent, "visibleComponent").isShowing()) {
|
||||
throw new IllegalArgumentException("visibleComponent must be showing");
|
||||
@@ -474,7 +474,7 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
}
|
||||
|
||||
private static Rectangle awtGetVisibleRectOf(final Component component) {
|
||||
assert(EventQueue.isDispatchThread());
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
if (component instanceof javax.swing.JComponent jComponent) {
|
||||
return jComponent.getVisibleRect();
|
||||
@@ -488,7 +488,7 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
* or {@code null} if the rectangle couldn't be determined.
|
||||
*/
|
||||
private static Rectangle awtConvertRectOnComponentToRectOnWlSurface(Component component, Rectangle rectOnComponent) {
|
||||
assert(EventQueue.isDispatchThread());
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
Objects.requireNonNull(component, "component");
|
||||
|
||||
@@ -536,7 +536,7 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
* or its closest ancestor meeting these requirements.
|
||||
*/
|
||||
private static Window awtGetWlSurfaceComponentOf(Component component) {
|
||||
assert EventQueue.isDispatchThread();
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
return WLComponentPeer.getToplevelFor(component);
|
||||
}
|
||||
@@ -557,8 +557,8 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
log.finer("awtPostIMESafely(preeditString={0}, commitString={1}): this={2}.", preeditString, commitString, this);
|
||||
}
|
||||
|
||||
assert(preeditString != null);
|
||||
assert(commitString != null);
|
||||
assert preeditString != null : "Pre-edit string must be present";
|
||||
assert commitString != null : "Commit string must be present";
|
||||
|
||||
try {
|
||||
if (awtActivationStatus != AWTActivationStatus.ACTIVATED) {
|
||||
@@ -769,8 +769,8 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
specialPreeditHighlightingBegin = swapTemp;
|
||||
}
|
||||
|
||||
assert(specialPreeditHighlightingBegin >= 0);
|
||||
assert(specialPreeditHighlightingEnd <= preeditTextLength);
|
||||
assert specialPreeditHighlightingBegin >= 0 : "specialPreeditHighlightingBegin is invalid";
|
||||
assert specialPreeditHighlightingEnd <= preeditTextLength : "specialPreeditHighlightingEnd is out of range";
|
||||
|
||||
// v
|
||||
// |BASIC+SPECIAL...|
|
||||
@@ -827,10 +827,10 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
// The methods in this section implement the core logic of working with the "text-input-unstable-v3" protocol.
|
||||
|
||||
private void wlInitializeContext() throws AWTException {
|
||||
assert(wlInputContextState == null);
|
||||
assert(wlPendingChanges == null);
|
||||
assert(wlBeingCommittedChanges == null);
|
||||
assert(wlIncomingChanges == null);
|
||||
assert wlInputContextState == null : "Must not initialize input context twice";
|
||||
assert wlPendingChanges == null : "Must not initialize pending changes twice";
|
||||
assert wlBeingCommittedChanges == null : "Must not initialize being-committed changes twice";
|
||||
assert wlIncomingChanges == null : "Must not initialize incoming changes twice";
|
||||
|
||||
long nativeCtxPtr = 0;
|
||||
|
||||
@@ -878,7 +878,7 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
* followed by a {@code zwp_text_input_v3::commit} request.
|
||||
*/
|
||||
private void wlSendPendingChangesNow() {
|
||||
assert(wlCanSendChangesNow());
|
||||
assert wlCanSendChangesNow() : "Must be able to send pending changes now";
|
||||
|
||||
final OutgoingChanges changesToSend = wlPendingChanges;
|
||||
wlPendingChanges = null;
|
||||
@@ -997,7 +997,7 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
throw new IllegalStateException("Attempt to enable an input context which hasn't entered any surface");
|
||||
}
|
||||
|
||||
assert(wlContextCanBeEnabledNow());
|
||||
assert wlContextCanBeEnabledNow() : "Can't enable InputContext";
|
||||
|
||||
// This way we guarantee the context won't accidentally get disabled because such a change has been scheduled earlier.
|
||||
// Anyway we consider any previously scheduled changes outdated because an 'enable' request is supposed to
|
||||
@@ -1029,7 +1029,7 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
awtFillWlContentTypeOf(getClientComponent(), changeSet);
|
||||
|
||||
wlScheduleContextNewChanges(changeSet);
|
||||
assert(wlPendingChanges != null);
|
||||
assert wlPendingChanges != null : "Must have non-empty pending changes";
|
||||
|
||||
// Pretending there are no committed, but not applied yet changes, so that wlCanSendChangesNow() is true.
|
||||
// We can do that because the assumption #1 and because any previously committed changes get lost when a
|
||||
@@ -1038,7 +1038,7 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
// set_surrounding_text, set_text_change_cause, set_content_type, and set_cursor_rectangle requests [...]"
|
||||
wlBeingCommittedChanges = null;
|
||||
|
||||
assert(wlCanSendChangesNow());
|
||||
assert wlCanSendChangesNow() : "Must be able to send pending changes now";
|
||||
wlSendPendingChangesNow();
|
||||
|
||||
// See the assumption #2 above.
|
||||
@@ -1103,10 +1103,10 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
assert(wlInputContextState.getCurrentWlSurfacePtr() != 0);
|
||||
assert wlInputContextState.getCurrentWlSurfacePtr() != 0 : "InputContext must have a valid current surface pointer";
|
||||
|
||||
wlScheduleContextNewChanges(new OutgoingChanges().setEnabledState(false));
|
||||
assert(wlPendingChanges != null);
|
||||
assert wlPendingChanges != null : "Must have non-empty pending changes";
|
||||
|
||||
// Pretending there are no committed, but not applied yet changes, so that wlCanSendChangesNow() is true.
|
||||
// We can do that because the assumption #1 and because any previously committed changes get lost when a
|
||||
@@ -1114,7 +1114,7 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
// "After an enter event or disable request all state information is invalidated and needs to be resent by the client."
|
||||
wlBeingCommittedChanges = null;
|
||||
|
||||
assert(wlCanSendChangesNow());
|
||||
assert wlCanSendChangesNow() : "Must be able to send pending changes now";
|
||||
wlSendPendingChangesNow();
|
||||
|
||||
// See the assumption #2 above.
|
||||
@@ -1206,7 +1206,7 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
|
||||
/** Called by {@link ClientComponentCaretPositionTracker} */
|
||||
boolean wlUpdateCursorRectangle(final boolean forceUpdate) {
|
||||
assert(EventQueue.isDispatchThread());
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
if (log.isLoggable(PlatformLogger.Level.FINER)) {
|
||||
log.finer("wlUpdateCursorRectangle(): forceUpdate={0}, this={1}.", forceUpdate, this);
|
||||
@@ -1290,7 +1290,7 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
|
||||
/** Called in response to {@code zwp_text_input_v3::enter} events. */
|
||||
private void zwp_text_input_v3_onEnter(long enteredWlSurfacePtr) {
|
||||
assert EventQueue.isDispatchThread();
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
try {
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
@@ -1312,7 +1312,7 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
|
||||
/** Called in response to {@code zwp_text_input_v3::leave} events. */
|
||||
private void zwp_text_input_v3_onLeave(long leftWlSurfacePtr) {
|
||||
assert EventQueue.isDispatchThread();
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
try {
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
@@ -1335,7 +1335,7 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
|
||||
/** Called in response to {@code zwp_text_input_v3::preedit_string} events. */
|
||||
private void zwp_text_input_v3_onPreeditString(byte[] preeditStrUtf8, int cursorBeginUtf8Byte, int cursorEndUtf8Byte) {
|
||||
assert EventQueue.isDispatchThread();
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
try {
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
@@ -1355,7 +1355,7 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
|
||||
/** Called in response to {@code zwp_text_input_v3::commit_string} events. */
|
||||
private void zwp_text_input_v3_onCommitString(byte[] commitStrUtf8) {
|
||||
assert EventQueue.isDispatchThread();
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
try {
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
@@ -1375,7 +1375,7 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
|
||||
/** Called in response to {@code zwp_text_input_v3::delete_surrounding_text} events. */
|
||||
private void zwp_text_input_v3_onDeleteSurroundingText(long numberOfUtf8BytesBeforeToDelete, long numberOfUtf8BytesAfterToDelete) {
|
||||
assert EventQueue.isDispatchThread();
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
// TODO: support the surrounding text API (set_surrounding_text + set_text_change_cause | delete_surrounding text)
|
||||
// at least for particular cases.
|
||||
@@ -1394,7 +1394,7 @@ final class WLInputMethodZwpTextInputV3 extends InputMethodAdapter {
|
||||
|
||||
/** Called in response to {@code zwp_text_input_v3::done} events. */
|
||||
private void zwp_text_input_v3_onDone(long doneSerial) {
|
||||
assert EventQueue.isDispatchThread();
|
||||
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
|
||||
|
||||
try {
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
|
||||
@@ -387,7 +387,7 @@ Java_sun_awt_wl_WLComponentPeer_nativeCreateWindow
|
||||
|
||||
static struct xdg_positioner *
|
||||
newPositioner
|
||||
(jint width, jint height, jint offsetX, jint offsetY)
|
||||
(jint width, jint height, jint offsetX, jint offsetY, jboolean isUnconstrained)
|
||||
{
|
||||
struct xdg_positioner *xdg_positioner = xdg_wm_base_create_positioner(xdg_wm_base);
|
||||
CHECK_NULL_RETURN(xdg_positioner, NULL);
|
||||
@@ -400,10 +400,15 @@ newPositioner
|
||||
xdg_positioner_set_offset(xdg_positioner, 0, 0);
|
||||
xdg_positioner_set_anchor(xdg_positioner, XDG_POSITIONER_ANCHOR_TOP_LEFT);
|
||||
xdg_positioner_set_gravity(xdg_positioner, XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT);
|
||||
xdg_positioner_set_constraint_adjustment(xdg_positioner,
|
||||
XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y
|
||||
| XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X
|
||||
| XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y);
|
||||
if (isUnconstrained) {
|
||||
xdg_positioner_set_constraint_adjustment(xdg_positioner,
|
||||
XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_NONE);
|
||||
} else {
|
||||
xdg_positioner_set_constraint_adjustment(xdg_positioner,
|
||||
XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y
|
||||
| XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X
|
||||
| XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y);
|
||||
}
|
||||
return xdg_positioner;
|
||||
}
|
||||
|
||||
@@ -411,7 +416,8 @@ JNIEXPORT void JNICALL
|
||||
Java_sun_awt_wl_WLComponentPeer_nativeCreatePopup
|
||||
(JNIEnv *env, jobject obj, jlong ptr, jlong parentPtr, jlong wlSurfacePtr,
|
||||
jint width, jint height,
|
||||
jint offsetX, jint offsetY)
|
||||
jint offsetX, jint offsetY,
|
||||
jboolean isUnconstrained)
|
||||
{
|
||||
struct WLFrame *frame = (struct WLFrame *) ptr;
|
||||
struct WLFrame *parentFrame = (struct WLFrame*) parentPtr;
|
||||
@@ -423,7 +429,7 @@ Java_sun_awt_wl_WLComponentPeer_nativeCreatePopup
|
||||
frame->toplevel = JNI_FALSE;
|
||||
|
||||
assert(parentFrame);
|
||||
struct xdg_positioner *xdg_positioner = newPositioner(width, height, offsetX, offsetY);
|
||||
struct xdg_positioner *xdg_positioner = newPositioner(width, height, offsetX, offsetY, isUnconstrained);
|
||||
CHECK_NULL(xdg_positioner);
|
||||
JNU_RUNTIME_ASSERT(env, parentFrame->toplevel, "Popup's parent surface must be a toplevel");
|
||||
frame->xdg_popup = xdg_surface_get_popup(frame->xdg_surface, parentFrame->xdg_surface, xdg_positioner);
|
||||
@@ -436,13 +442,14 @@ JNIEXPORT void JNICALL
|
||||
Java_sun_awt_wl_WLComponentPeer_nativeRepositionWLPopup
|
||||
(JNIEnv *env, jobject obj, jlong ptr,
|
||||
jint width, jint height,
|
||||
jint offsetX, jint offsetY)
|
||||
jint offsetX, jint offsetY,
|
||||
jboolean isUnconstrained)
|
||||
{
|
||||
struct WLFrame *frame = jlong_to_ptr(ptr);
|
||||
assert (!frame->toplevel);
|
||||
|
||||
if (wl_proxy_get_version((struct wl_proxy *)xdg_wm_base) >= 3) {
|
||||
struct xdg_positioner *xdg_positioner = newPositioner(width, height, offsetX, offsetY);
|
||||
struct xdg_positioner *xdg_positioner = newPositioner(width, height, offsetX, offsetY, isUnconstrained);
|
||||
CHECK_NULL(xdg_positioner);
|
||||
static int token = 42; // This will be received by xdg_popup_repositioned(); unused for now.
|
||||
xdg_popup_reposition(frame->xdg_popup, xdg_positioner, token++);
|
||||
|
||||
95
test/jdk/jb/javax/swing/wayland/WLPopupUnconstrained.java
Normal file
95
test/jdk/jb/javax/swing/wayland/WLPopupUnconstrained.java
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2025 JetBrains s.r.o.
|
||||
* 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 javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JWindow;
|
||||
import javax.swing.SwingUtilities;
|
||||
import java.awt.GridLayout;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Verifies popups can be located regardless of the screen edge proximity
|
||||
* @requires os.family == "linux"
|
||||
* @key headful
|
||||
* @modules java.desktop/sun.awt
|
||||
* @run main/manual WLPopupUnconstrained
|
||||
*/
|
||||
public class WLPopupUnconstrained {
|
||||
static final CompletableFuture<RuntimeException> swingError = new CompletableFuture<>();
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SwingUtilities.invokeAndWait(WLPopupUnconstrained::showUI);
|
||||
swingError.get();
|
||||
}
|
||||
|
||||
private static void showUI() {
|
||||
JFrame frame = new JFrame("Unconstrained popup test");
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
JLabel label = new JLabel("Right-click here for a popup.");
|
||||
|
||||
JPanel popupContents = new JPanel();
|
||||
popupContents.add(new JLabel("test popup"));
|
||||
JWindow popup = new JWindow(frame);
|
||||
popup.setType(Window.Type.POPUP);
|
||||
sun.awt.AWTAccessor.getWindowAccessor().setPopupParent(popup, label);
|
||||
popup.getRootPane().putClientProperty("wlawt.popup_position_unconstrained", Boolean.TRUE);
|
||||
popup.setSize(300, 250);
|
||||
popup.add(popupContents);
|
||||
label.addMouseListener(new MouseAdapter() {
|
||||
public void mousePressed(MouseEvent e) {
|
||||
if (e.isPopupTrigger()) {
|
||||
popup.setLocation(e.getX(), e.getY());
|
||||
popup.setVisible(true);
|
||||
} else {
|
||||
popup.setVisible(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
JPanel content = new JPanel();
|
||||
var layout = new GridLayout(3, 2, 10, 10);
|
||||
content.setLayout(layout);
|
||||
content.add(new JLabel("<html><h1>INSTRUCTIONS</h1>" +
|
||||
"<p>Locate this window close to the bottom-right edge of the screen.</p>" +
|
||||
"<p>Make the popup appear (on the right) such that it is partially outside the screen.</p>" +
|
||||
"<p>Press Pass iff the popup indeed crossed the screen edge.</p>" +
|
||||
"<p>Otherwise press Fail.</p></html>"));
|
||||
content.add(label);
|
||||
JButton passButton = new JButton("Pass");
|
||||
passButton.addActionListener(e -> {swingError.complete(null);});
|
||||
JButton failButton = new JButton("Fail");
|
||||
failButton.addActionListener(e -> {swingError.completeExceptionally(new RuntimeException("The tester has pressed FAILED"));});
|
||||
content.add(failButton);
|
||||
content.add(passButton);
|
||||
frame.setContentPane(content);
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user