From acfbff811b1502b4bdaa47a1feffc10230891aba Mon Sep 17 00:00:00 2001 From: mstr2 <43553916+mstr2@users.noreply.github.com> Date: Thu, 29 Jul 2021 20:52:55 +0200 Subject: [PATCH 1/5] added undecorated-interactive window style --- .../java/com/sun/glass/ui/Application.java | 9 +- .../com/sun/glass/ui/MoveResizeHelper.java | 174 ++++++++++++++++++ .../src/main/java/com/sun/glass/ui/View.java | 23 ++- .../main/java/com/sun/glass/ui/Window.java | 33 +++- .../com/sun/glass/ui/gtk/GtkApplication.java | 5 +- .../java/com/sun/glass/ui/gtk/GtkWindow.java | 7 +- .../com/sun/glass/ui/ios/IosApplication.java | 7 +- .../java/com/sun/glass/ui/ios/IosWindow.java | 7 +- .../com/sun/glass/ui/mac/MacApplication.java | 7 +- .../java/com/sun/glass/ui/mac/MacWindow.java | 10 +- .../glass/ui/monocle/MonocleApplication.java | 5 +- .../sun/glass/ui/monocle/MonocleWindow.java | 7 +- .../com/sun/glass/ui/win/WinApplication.java | 9 +- .../java/com/sun/glass/ui/win/WinView.java | 13 +- .../java/com/sun/glass/ui/win/WinWindow.java | 33 +++- .../java/com/sun/javafx/tk/DummyToolkit.java | 5 +- .../com/sun/javafx/tk/TKSceneListener.java | 3 + .../main/java/com/sun/javafx/tk/Toolkit.java | 8 +- .../javafx/tk/quantum/GlassAppletWindow.java | 2 +- .../tk/quantum/GlassViewEventHandler.java | 15 +- .../sun/javafx/tk/quantum/QuantumToolkit.java | 9 +- .../sun/javafx/tk/quantum/WindowStage.java | 12 +- .../java/com/sun/prism/d3d/D3DSwapChain.java | 9 +- .../src/main/java/javafx/scene/Scene.java | 15 ++ .../src/main/java/javafx/stage/Stage.java | 37 +++- .../main/java/javafx/stage/StageStyle.java | 11 +- .../main/java/javafx/stage/WindowRegion.java | 88 +++++++++ .../javafx/stage/WindowRegionClassifier.java | 50 +++++ .../src/main/native-glass/win/GlassView.cpp | 35 ++-- .../src/main/native-glass/win/GlassWindow.cpp | 93 ++++++---- .../src/main/native-glass/win/GlassWindow.h | 11 +- .../src/main/native-glass/win/Utils.cpp | 158 ++++++++++++++++ .../src/main/native-glass/win/Utils.h | 16 +- .../main/native-glass/win/ViewContainer.cpp | 44 ++--- .../com/sun/javafx/pgstub/StubToolkit.java | 3 +- 35 files changed, 821 insertions(+), 152 deletions(-) create mode 100644 modules/javafx.graphics/src/main/java/com/sun/glass/ui/MoveResizeHelper.java create mode 100644 modules/javafx.graphics/src/main/java/javafx/stage/WindowRegion.java create mode 100644 modules/javafx.graphics/src/main/java/javafx/stage/WindowRegionClassifier.java diff --git a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/Application.java b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/Application.java index ef9b6877d35..ea471429171 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/Application.java +++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/Application.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -27,6 +27,7 @@ import com.sun.glass.events.KeyEvent; import com.sun.glass.ui.CommonDialogs.ExtensionFilter; import com.sun.glass.ui.CommonDialogs.FileChooserResult; +import javafx.stage.WindowRegionClassifier; import java.io.File; import java.nio.ByteBuffer; @@ -567,7 +568,7 @@ public void menuAboutAction() { * allowed to be of exactly one visual kind, and exactly one functional * type. */ - public abstract Window createWindow(Window owner, Screen screen, int styleMask); + public abstract Window createWindow(Window owner, Screen screen, WindowRegionClassifier classifier, int styleMask); /** * Create a window. @@ -579,8 +580,8 @@ public void menuAboutAction() { * allowed to be of exactly one visual kind, and exactly one functional * type. */ - public final Window createWindow(Screen screen, int styleMask) { - return createWindow(null, screen, styleMask); + public final Window createWindow(Screen screen, WindowRegionClassifier classifier, int styleMask) { + return createWindow(null, screen, classifier, styleMask); } public abstract Window createWindow(long parent); diff --git a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/MoveResizeHelper.java b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/MoveResizeHelper.java new file mode 100644 index 00000000000..a3b3b5b066c --- /dev/null +++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/MoveResizeHelper.java @@ -0,0 +1,174 @@ +package com.sun.glass.ui; + +import com.sun.glass.events.MouseEvent; +import javafx.scene.Node; +import javafx.stage.WindowRegion; +import javafx.stage.WindowRegionClassifier; + +import java.util.HashMap; +import java.util.Map; + +public class MoveResizeHelper { + + private static final Map RESIZE_CURSORS = new HashMap<>(); + + static { + Application application = Application.GetApplication(); + RESIZE_CURSORS.put(WindowRegion.TOP_LEFT, application.createCursor(Cursor.CURSOR_RESIZE_NORTHWEST)); + RESIZE_CURSORS.put(WindowRegion.TOP_RIGHT, application.createCursor(Cursor.CURSOR_RESIZE_NORTHEAST)); + RESIZE_CURSORS.put(WindowRegion.BOTTOM_LEFT, application.createCursor(Cursor.CURSOR_RESIZE_SOUTHWEST)); + RESIZE_CURSORS.put(WindowRegion.BOTTOM_RIGHT, application.createCursor(Cursor.CURSOR_RESIZE_SOUTHEAST)); + RESIZE_CURSORS.put(WindowRegion.LEFT, application.createCursor(Cursor.CURSOR_RESIZE_LEFTRIGHT)); + RESIZE_CURSORS.put(WindowRegion.RIGHT, application.createCursor(Cursor.CURSOR_RESIZE_LEFTRIGHT)); + RESIZE_CURSORS.put(WindowRegion.TOP, application.createCursor(Cursor.CURSOR_RESIZE_UPDOWN)); + RESIZE_CURSORS.put(WindowRegion.BOTTOM, application.createCursor(Cursor.CURSOR_RESIZE_UPDOWN)); + } + + private final View view; + private final Window window; + private final WindowRegionClassifier regionClassifier; + private int mouseDownX, mouseDownY; + private int mouseDownWindowX, mouseDownWindowY; + private int mouseDownWindowWidth, mouseDownWindowHeight; + private WindowRegion currentWindowRegion; + private Cursor lastCursor; + + public MoveResizeHelper(View view, Window window) { + this.view = view; + this.window = window; + this.regionClassifier = window.regionClassifier; + } + + public final boolean handleMouseEvent(int type, int button, int x, int y, int xAbs, int yAbs) { + int wx = (int)(x / window.getPlatformScaleX()); + int wy = (int)(y / window.getPlatformScaleY()); + + if (type != MouseEvent.DRAG) { + var eventHandler = view.getEventHandler(); + Node pickedNode = eventHandler != null ? eventHandler.pickNode(wx, wy) : null; + currentWindowRegion = regionClassifier.classify(wx, wy, pickedNode); + updateCursor(currentWindowRegion); + + if (currentWindowRegion == WindowRegion.CLIENT) { + return false; + } + } + + switch (type) { + case MouseEvent.DRAG: + handleMouseDrag(button, xAbs, yAbs, currentWindowRegion); + break; + case MouseEvent.DOWN: + handleMouseDown(xAbs, yAbs); + break; + } + + return false; + } + + protected boolean shouldStartMoveDrag(int button, WindowRegion region) { + return button == MouseEvent.BUTTON_LEFT && region == WindowRegion.TITLE; + } + + protected boolean shouldStartResizeDrag(int button, WindowRegion region) { + return button == MouseEvent.BUTTON_LEFT && RESIZE_CURSORS.get(region) != null; + } + + private void handleMouseDrag(int button, int xAbs, int yAbs, WindowRegion region) { + if (shouldStartMoveDrag(button, region)) { + handleMoveWindow(xAbs, yAbs); + } else if (shouldStartResizeDrag(button, region)) { + handleResizeWindow(xAbs, yAbs, region); + } + } + + private void handleMouseDown(int xAbs, int yAbs) { + mouseDownX = xAbs; + mouseDownY = yAbs; + mouseDownWindowX = window.getX(); + mouseDownWindowY = window.getY(); + mouseDownWindowWidth = window.getWidth(); + mouseDownWindowHeight = window.getHeight(); + } + + private void handleMoveWindow(int xAbs, int yAbs) { + window.setPosition(mouseDownWindowX + xAbs - mouseDownX, mouseDownWindowY + yAbs - mouseDownY); + } + + private void handleResizeWindow(int xAbs, int yAbs, WindowRegion region) { + int dx = xAbs - mouseDownX; + int dy = yAbs - mouseDownY; + + switch (region) { + case LEFT: + adjustWindowPosition(dx, 0); + adjustWindowSize(-dx, 0); + break; + case RIGHT: + adjustWindowSize(dx, 0); + break; + case TOP: + adjustWindowPosition(0, dy); + adjustWindowSize(0, -dy); + break; + case BOTTOM: + adjustWindowSize(0, dy); + break; + case TOP_LEFT: + adjustWindowPosition(dx, dy); + adjustWindowSize(-dx, -dy); + break; + case TOP_RIGHT: + adjustWindowPosition(0, dy); + adjustWindowSize(dx, -dy); + break; + case BOTTOM_LEFT: + adjustWindowPosition(dx, 0); + adjustWindowSize(-dx, dy); + break; + case BOTTOM_RIGHT: + adjustWindowSize(dx, dy); + break; + } + } + + private void adjustWindowPosition(int dx, int dy) { + int unclampedWidth = mouseDownWindowWidth - dx; + int unclampedHeight = mouseDownWindowHeight - dy; + int clampedWidth = dx != 0 ? clampWidth(unclampedWidth) : unclampedWidth; + int clampedHeight = dy != 0 ? clampHeight(unclampedHeight) : unclampedHeight; + int cx = unclampedWidth - clampedWidth; + int cy = unclampedHeight - clampedHeight; + window.setPosition(mouseDownWindowX + dx + cx, mouseDownWindowY + dy + cy); + } + + private void adjustWindowSize(int dx, int dy) { + int width = dx != 0 ? clampWidth(mouseDownWindowWidth + dx) : mouseDownWindowWidth; + int height = dy != 0 ? clampHeight(mouseDownWindowHeight + dy) : mouseDownWindowHeight; + window.setSize(width, height); + } + + private int clampWidth(int width) { + return Math.max(window.getMinimumWidth(), Math.min(window.getMaximumWidth(), width)); + } + + private int clampHeight(int height) { + return Math.max(window.getMinimumHeight(), Math.min(window.getMaximumHeight(), height)); + } + + private void updateCursor(WindowRegion region) { + Cursor newCursor = RESIZE_CURSORS.get(region); + + if (lastCursor == null && newCursor != null) { + lastCursor = window.getCursor(); + } else if (lastCursor != null && newCursor == null) { + window.setCursor(lastCursor); + lastCursor = null; + } + + if (newCursor != null) { + window.setCursor(newCursor); + } + } + +} diff --git a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/View.java b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/View.java index 40c2a51a521..9cd39f0dd56 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/View.java +++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/View.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -26,6 +26,7 @@ import com.sun.glass.events.MouseEvent; import com.sun.glass.events.ViewEvent; +import javafx.scene.Node; import java.lang.annotation.Native; import java.lang.ref.WeakReference; @@ -367,6 +368,10 @@ public void handleSwipeGestureEvent(View view, long time, int type, public Accessible getSceneAccessible() { return null; } + + public Node pickNode(double x, double y) { + return null; + } } public static long getMultiClickTime() { @@ -394,6 +399,7 @@ protected void _finishInputMethodComposition(long ptr) { */ private volatile long ptr; // Native handle (NSView*, or internal structure pointer) private Window window; // parent window + private MoveResizeHelper moveResizeHelper; private EventHandler eventHandler; private int width = -1; // not set @@ -499,6 +505,16 @@ void setWindow(Window window) { this.window = window; _setParent(this.ptr, window == null ? 0L : window.getNativeHandle()); this.isValid = this.ptr != 0 && window != null; + + if (isValid && window.regionClassifier != null && !window.isDecorated() && window.isInteractive()) { + this.moveResizeHelper = getMoveResizeHelper(); + } else { + this.moveResizeHelper = null; + } + } + + protected MoveResizeHelper getMoveResizeHelper() { + return new MoveResizeHelper(this, window); } // package private @@ -908,6 +924,11 @@ protected void notifyMenu(int x, int y, int xAbs, int yAbs, boolean isKeyboardTr protected void notifyMouse(int type, int button, int x, int y, int xAbs, int yAbs, int modifiers, boolean isPopupTrigger, boolean isSynthesized) { + // If we have a move-resize helper, we give it the first chance to handle the event. + if (moveResizeHelper != null && moveResizeHelper.handleMouseEvent(type, button, x, y, xAbs, yAbs)) { + return; + } + // gznote: optimize - only call for undecorated Windows! if (this.window != null) { // handled by window (programmatical move/resize) diff --git a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/Window.java b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/Window.java index 26864349280..d92ab193517 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/Window.java +++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/Window.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -27,9 +27,9 @@ import com.sun.glass.events.MouseEvent; import com.sun.glass.events.WindowEvent; import com.sun.prism.impl.PrismSettings; +import javafx.stage.WindowRegionClassifier; import java.lang.annotation.Native; - import java.util.Collections; import java.util.LinkedList; import java.util.List; @@ -165,6 +165,11 @@ static protected void remove(Window window) { */ @Native public static final int MODAL = 1 << 9; + /** + * Indicates that the window enables platform-specific window interactions. + */ + @Native public static final int INTERACTIVE = 1 << 10; + final static public class State { @Native public static final int NORMAL = 1; @Native public static final int MINIMIZED = 2; @@ -198,8 +203,10 @@ public static final class Level { private final long parent; private final int styleMask; private final boolean isDecorated; + private final boolean isInteractive; private boolean shouldStartUndecoratedMove = false; + protected final WindowRegionClassifier regionClassifier; protected View view = null; protected Screen screen = null; private MenuBar menubar = null; @@ -245,7 +252,8 @@ public static final class Level { private EventHandler eventHandler; protected abstract long _createWindow(long ownerPtr, long screenPtr, int mask); - protected Window(Window owner, Screen screen, int styleMask) { + + protected Window(Window owner, Screen screen, WindowRegionClassifier regionClassifier, int styleMask) { Application.checkEventThread(); switch (styleMask & (TITLED | TRANSPARENT)) { case UNTITLED: @@ -274,11 +282,16 @@ protected Window(Window owner, Screen screen, int styleMask) { styleMask &= ~TRANSPARENT; } + if ((styleMask & INTERACTIVE) == 0) { + regionClassifier = null; + } this.owner = owner; this.parent = 0L; this.styleMask = styleMask; + this.regionClassifier = regionClassifier; this.isDecorated = (this.styleMask & Window.TITLED) != 0; + this.isInteractive = (this.styleMask & Window.INTERACTIVE) != 0; this.screen = screen != null ? screen : Screen.getMainScreen(); if (PrismSettings.allowHiDPIScaling) { @@ -304,7 +317,9 @@ protected Window(long parent) { this.owner = null; this.parent = parent; this.styleMask = Window.UNTITLED; + this.regionClassifier = null; this.isDecorated = false; + this.isInteractive = false; // Note: we can't always catch screen changes when parent is moved... this.screen = null; // should infer from the parent @@ -468,6 +483,11 @@ public boolean isDecorated() { return this.isDecorated; } + public boolean isInteractive() { + Application.checkEventThread(); + return this.isInteractive; + } + public boolean isMinimized() { Application.checkEventThread(); return (this.state == State.MINIMIZED); @@ -1130,6 +1150,8 @@ public void setIcon(final Pixels pixels) { _setIcon(this.ptr, pixels); } + private Cursor cursor; + protected abstract void _setCursor(long ptr, Cursor cursor); /** @@ -1140,9 +1162,14 @@ public void setIcon(final Pixels pixels) { */ public void setCursor(Cursor cursor) { Application.checkEventThread(); + this.cursor = cursor; _setCursor(this.ptr, cursor); } + public Cursor getCursor() { + return cursor; + } + protected abstract void _toFront(long ptr); /** * Bring the window to front in the z-order. diff --git a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/gtk/GtkApplication.java b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/gtk/GtkApplication.java index 9e119e42de5..09d774615a4 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/gtk/GtkApplication.java +++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/gtk/GtkApplication.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -40,6 +40,7 @@ import com.sun.glass.utils.NativeLibLoader; import com.sun.prism.impl.PrismSettings; import com.sun.javafx.logging.PlatformLogger; +import javafx.stage.WindowRegionClassifier; import java.io.File; import java.lang.reflect.Method; @@ -378,7 +379,7 @@ protected void _leaveNestedEventLoop(Object retValue) { } @Override - public Window createWindow(Window owner, Screen screen, int styleMask) { + public Window createWindow(Window owner, Screen screen, WindowRegionClassifier classifier, int styleMask) { return new GtkWindow(owner, screen, styleMask); } diff --git a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/gtk/GtkWindow.java b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/gtk/GtkWindow.java index fc770274de7..770dd59088e 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/gtk/GtkWindow.java +++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/gtk/GtkWindow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -30,11 +30,12 @@ import com.sun.glass.ui.Screen; import com.sun.glass.ui.View; import com.sun.glass.ui.Window; +import javafx.stage.WindowRegionClassifier; class GtkWindow extends Window { - public GtkWindow(Window owner, Screen screen, int styleMask) { - super(owner, screen, styleMask); + public GtkWindow(Window owner, Screen screen, WindowRegionClassifier regionClassifier, int styleMask) { + super(owner, screen, regionClassifier, styleMask); } protected GtkWindow(long parent) { diff --git a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/ios/IosApplication.java b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/ios/IosApplication.java index 1890ebf3ded..2c8f51f25d5 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/ios/IosApplication.java +++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/ios/IosApplication.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -28,6 +28,7 @@ import com.sun.glass.ui.*; import com.sun.glass.ui.CommonDialogs.ExtensionFilter; import com.sun.glass.ui.CommonDialogs.FileChooserResult; +import javafx.stage.WindowRegionClassifier; import java.io.File; import java.nio.ByteBuffer; @@ -75,8 +76,8 @@ private void setEventThread() { * @inheritDoc */ @Override - public Window createWindow(Window owner, Screen screen, int styleMask) { - return new IosWindow(owner, screen, styleMask); + public Window createWindow(Window owner, Screen screen, WindowRegionClassifier classifier, int styleMask) { + return new IosWindow(owner, screen, classifier, styleMask); } /** diff --git a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/ios/IosWindow.java b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/ios/IosWindow.java index 44057447786..d28278ab32d 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/ios/IosWindow.java +++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/ios/IosWindow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -30,13 +30,14 @@ import com.sun.glass.ui.Screen; import com.sun.glass.ui.View; import com.sun.glass.ui.Window; +import javafx.stage.WindowRegionClassifier; /** * iOS platform Window implementation class. */ final class IosWindow extends Window { - protected IosWindow(Window owner, Screen screen, int styleMask) { - super(owner, screen, styleMask); + protected IosWindow(Window owner, Screen screen, WindowRegionClassifier regionClassifier, int styleMask) { + super(owner, screen, regionClassifier, styleMask); } protected IosWindow(long parent) { super(parent); diff --git a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/mac/MacApplication.java b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/mac/MacApplication.java index f5dc2ddb0f3..9c7c4b76d62 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/mac/MacApplication.java +++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/mac/MacApplication.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -29,6 +29,7 @@ import com.sun.glass.ui.CommonDialogs.ExtensionFilter; import com.sun.glass.ui.CommonDialogs.FileChooserResult; import com.sun.javafx.util.Logging; +import javafx.stage.WindowRegionClassifier; import java.io.File; import java.nio.ByteBuffer; @@ -243,8 +244,8 @@ public Menu getAppleMenu() { // FACTORY METHODS - @Override public Window createWindow(Window owner, Screen screen, int styleMask) { - return new MacWindow(owner, screen, styleMask); + @Override public Window createWindow(Window owner, Screen screen, WindowRegionClassifier classifier, int styleMask) { + return new MacWindow(owner, screen, classifier, styleMask); } final static long BROWSER_PARENT_ID = -1L; diff --git a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/mac/MacWindow.java b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/mac/MacWindow.java index a42b9d341c4..dafb41ccfd4 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/mac/MacWindow.java +++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/mac/MacWindow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -31,9 +31,9 @@ import com.sun.glass.ui.Screen; import com.sun.glass.ui.View; import com.sun.glass.ui.Window; -import com.sun.glass.ui.Window.State; -import java.nio.ByteBuffer; +import javafx.stage.WindowRegionClassifier; +import java.nio.ByteBuffer; import java.util.Map; /** @@ -46,8 +46,8 @@ final class MacWindow extends Window { _initIDs(); } - protected MacWindow(Window owner, Screen screen, int styleMask) { - super(owner, screen, styleMask); + protected MacWindow(Window owner, Screen screen, WindowRegionClassifier regionClassifier, int styleMask) { + super(owner, screen, regionClassifier, styleMask); } protected MacWindow(long parent) { super(parent); diff --git a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/MonocleApplication.java b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/MonocleApplication.java index 88e539733d7..9e549faca1a 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/MonocleApplication.java +++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/MonocleApplication.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -36,6 +36,7 @@ import com.sun.glass.ui.View; import com.sun.glass.ui.Window; import javafx.collections.SetChangeListener; +import javafx.stage.WindowRegionClassifier; import java.io.File; import java.nio.ByteBuffer; @@ -151,7 +152,7 @@ protected void _leaveNestedEventLoop(Object retValue) { } @Override - public Window createWindow(Window owner, Screen screen, int styleMask) { + public Window createWindow(Window owner, Screen screen, WindowRegionClassifier classifier, int styleMask) { return new MonocleWindow(owner, screen, styleMask); } diff --git a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/MonocleWindow.java b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/MonocleWindow.java index f064f3913fc..82fdb67954e 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/MonocleWindow.java +++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/MonocleWindow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -34,6 +34,7 @@ import com.sun.glass.ui.Screen; import com.sun.glass.ui.View; import com.sun.glass.ui.Window; +import javafx.stage.WindowRegionClassifier; final class MonocleWindow extends Window { @@ -51,8 +52,8 @@ final class MonocleWindow extends Window { private int maxW = -1; private int maxH = -1; - MonocleWindow(Window owner, Screen screen, int styleMask) { - super(owner, screen, styleMask); + MonocleWindow(Window owner, Screen screen, WindowRegionClassifier regionClassifier, int styleMask) { + super(owner, screen, regionClassifier, styleMask); } MonocleWindow(long parent) { diff --git a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinApplication.java b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinApplication.java index 3370d30875d..557566aa8f1 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinApplication.java +++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinApplication.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -30,14 +30,13 @@ import com.sun.javafx.application.PlatformImpl; import com.sun.prism.impl.PrismSettings; import com.sun.javafx.tk.Toolkit; +import javafx.stage.WindowRegionClassifier; import java.io.File; import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.security.AccessController; import java.security.PrivilegedAction; -import java.util.Iterator; -import java.util.Locale; import java.util.ResourceBundle; final class WinApplication extends Application implements InvokeLaterDispatcher.InvokeLaterSubmitter { @@ -225,8 +224,8 @@ protected void runLoop(final Runnable launchable) { // FACTORY METHODS - @Override public Window createWindow(Window owner, Screen screen, int styleMask) { - return new WinWindow(owner, screen, styleMask); + @Override public Window createWindow(Window owner, Screen screen, WindowRegionClassifier classifier, int styleMask) { + return new WinWindow(owner, screen, classifier, styleMask); } @Override public Window createWindow(long parent) { diff --git a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinView.java b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinView.java index 7ac26266ef4..1540e8b7703 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinView.java +++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -24,12 +24,9 @@ */ package com.sun.glass.ui.win; -import com.sun.glass.ui.Application; +import com.sun.glass.ui.MoveResizeHelper; import com.sun.glass.ui.Pixels; import com.sun.glass.ui.View; -import com.sun.glass.ui.Window; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Map; @@ -100,5 +97,11 @@ protected void notifyResize(int width, int height) { // to be recalculated. updateLocation(); } + + /*@Override + protected MoveResizeHelper getMoveResizeHelper() { + // We don't use a move-resize helper on Windows, but handle the WM_NCHITTEST message instead. + return null; + }*/ } diff --git a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinWindow.java b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinWindow.java index 95136453c0f..7dd509aae7b 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinWindow.java +++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinWindow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -29,6 +29,8 @@ import com.sun.glass.ui.Screen; import com.sun.glass.ui.View; import com.sun.glass.ui.Window; +import javafx.scene.Node; +import javafx.stage.WindowRegionClassifier; /** * MS Windows platform implementation class for Window. @@ -50,8 +52,8 @@ class WinWindow extends Window { _initIDs(); } - protected WinWindow(Window owner, Screen screen, int styleMask) { - super(owner, screen, styleMask); + protected WinWindow(Window owner, Screen screen, WindowRegionClassifier regionClassifier, int styleMask) { + super(owner, screen, regionClassifier, styleMask); } protected WinWindow(long parent) { @@ -251,6 +253,31 @@ protected boolean _setBackground(long ptr, float r, float g, float b) { return true; } + protected int classifyWindowRegion(int x, int y) { + /*if (regionClassifier != null) { + double wx = (x - this.x) / platformScaleX; + double wy = (y - this.y) / platformScaleY; + + var eventHandler = view.getEventHandler(); + Node pickedNode = eventHandler != null ? eventHandler.pickNode(wx, wy) : null; + + switch (regionClassifier.classify(wx, wy, pickedNode)) { + case NONE: return 0; // HTNOWHERE + case TITLE: return 2; // HTCAPTION + case TOP: return 12; // HTTOP + case TOP_RIGHT: return 14; // HTTOPRIGHT + case RIGHT: return 11; // HTRIGHT + case BOTTOM_RIGHT: return 17; // HTBOTTOMRIGHT + case BOTTOM: return 15; // HTBOTTOM + case BOTTOM_LEFT: return 16; // HTBOTTOMLEFT + case LEFT: return 10; // HTLEFT + case TOP_LEFT: return 13; // HTTOPLEFT + } + }*/ + + return 1; // HTCLIENT + } + native private long _getInsets(long ptr); native private long _getAnchor(long ptr); @Override native protected long _createWindow(long ownerPtr, long screenPtr, int mask); diff --git a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/DummyToolkit.java b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/DummyToolkit.java index 84145ce2c3d..0ca27b721ec 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/DummyToolkit.java +++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/DummyToolkit.java @@ -43,7 +43,6 @@ import javafx.scene.shape.StrokeType; import javafx.stage.FileChooser.ExtensionFilter; import javafx.stage.Modality; -import javafx.stage.Stage; import javafx.stage.StageStyle; import javafx.stage.Window; import java.io.File; @@ -67,6 +66,8 @@ import com.sun.scenario.animation.AbstractPrimaryTimer; import com.sun.scenario.effect.FilterContext; import com.sun.scenario.effect.Filterable; +import javafx.stage.WindowRegionClassifier; + import java.util.Optional; /** @@ -103,7 +104,7 @@ public void exitAllNestedEventLoops() { } @Override - public TKStage createTKStage(Window peerWindow, boolean securityDialog, StageStyle stageStyle, boolean primary, Modality modality, TKStage owner, boolean rtl, @SuppressWarnings("removal") AccessControlContext acc) { + public TKStage createTKStage(Window peerWindow, boolean securityDialog, StageStyle stageStyle, boolean primary, Modality modality, WindowRegionClassifier classifier, TKStage owner, boolean rtl, @SuppressWarnings("removal") AccessControlContext acc) { throw new UnsupportedOperationException("Not supported yet."); } diff --git a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/TKSceneListener.java b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/TKSceneListener.java index 348cc8527a8..7678062fa26 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/TKSceneListener.java +++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/TKSceneListener.java @@ -28,6 +28,7 @@ import com.sun.glass.ui.Accessible; import javafx.collections.ObservableList; import javafx.event.EventType; +import javafx.scene.Node; import javafx.scene.input.*; /** @@ -120,4 +121,6 @@ public void touchEventNext( public void touchEventEnd(); public Accessible getSceneAccessible(); + + public Node pickNode(double x, double y); } diff --git a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/Toolkit.java b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/Toolkit.java index 5068c176b7e..be9634db9fc 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/Toolkit.java +++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/Toolkit.java @@ -28,7 +28,6 @@ import javafx.application.ConditionalFeature; import javafx.beans.property.ReadOnlyObjectProperty; import javafx.geometry.Dimension2D; -import javafx.scene.Scene; import javafx.scene.effect.BlurType; import javafx.scene.image.Image; import javafx.scene.image.PixelFormat; @@ -51,11 +50,10 @@ import javafx.scene.shape.StrokeType; import javafx.stage.FileChooser.ExtensionFilter; import javafx.stage.Modality; -import javafx.stage.Stage; import javafx.stage.StageStyle; import javafx.stage.Window; +import javafx.stage.WindowRegionClassifier; import java.io.File; -import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.security.AccessControlContext; @@ -63,7 +61,6 @@ import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -82,7 +79,6 @@ import com.sun.javafx.runtime.VersionInfo; import com.sun.javafx.runtime.async.AsyncOperation; import com.sun.javafx.runtime.async.AsyncOperationListener; -import com.sun.javafx.scene.SceneHelper; import com.sun.javafx.scene.text.TextLayoutFactory; import com.sun.javafx.sg.prism.NGCamera; import com.sun.javafx.sg.prism.NGLightBase; @@ -370,7 +366,7 @@ protected Toolkit() { public abstract boolean isNestedLoopRunning(); - public abstract TKStage createTKStage(Window peerWindow, boolean securityDialog, StageStyle stageStyle, boolean primary, Modality modality, TKStage owner, boolean rtl, @SuppressWarnings("removal") AccessControlContext acc); + public abstract TKStage createTKStage(Window peerWindow, boolean securityDialog, StageStyle stageStyle, boolean primary, Modality modality, WindowRegionClassifier classifier, TKStage owner, boolean rtl, @SuppressWarnings("removal") AccessControlContext acc); public abstract TKStage createTKPopupStage(Window peerWindow, StageStyle popupStyle, TKStage owner, @SuppressWarnings("removal") AccessControlContext acc); public abstract TKStage createTKEmbeddedStage(HostInterface host, @SuppressWarnings("removal") AccessControlContext acc); diff --git a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/GlassAppletWindow.java b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/GlassAppletWindow.java index da29fe76980..d1b7e12a887 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/GlassAppletWindow.java +++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/GlassAppletWindow.java @@ -53,7 +53,7 @@ class GlassAppletWindow implements AppletWindow { if (serverName != null) { throw new RuntimeException("GlassAppletWindow constructor used incorrectly."); } - glassWindow = Application.GetApplication().createWindow(null, Window.NORMAL); + glassWindow = Application.GetApplication().createWindow(null, null, Window.NORMAL); } else { this.serverName = serverName; glassWindow = Application.GetApplication().createWindow(nativeParent); diff --git a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/GlassViewEventHandler.java b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/GlassViewEventHandler.java index 0dca686b030..06a7bfdc8e4 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/GlassViewEventHandler.java +++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/GlassViewEventHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -48,6 +48,7 @@ import javafx.event.EventType; import javafx.geometry.Point2D; +import javafx.scene.Node; import javafx.scene.input.InputMethodEvent; import javafx.scene.input.InputMethodHighlight; import javafx.scene.input.InputMethodTextRun; @@ -1391,4 +1392,16 @@ public Accessible getSceneAccessible() { } return null; } + + @Override + public Node pickNode(double x, double y) { + return QuantumToolkit.runWithoutRenderLock(() -> { + return AccessController.doPrivileged((PrivilegedAction) () -> { + if (scene.sceneListener != null) { + return scene.sceneListener.pickNode(x, y); + } + return null; + }); + }); + } } diff --git a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/QuantumToolkit.java b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/QuantumToolkit.java index 6c00aa0f76b..83e4be24827 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/QuantumToolkit.java +++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/QuantumToolkit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -55,6 +55,7 @@ import javafx.stage.Modality; import javafx.stage.StageStyle; import javafx.stage.Window; +import javafx.stage.WindowRegionClassifier; import java.io.File; import java.io.InputStream; import java.nio.Buffer; @@ -607,9 +608,9 @@ void vsyncHint() { } } - @Override public TKStage createTKStage(Window peerWindow, boolean securityDialog, StageStyle stageStyle, boolean primary, Modality modality, TKStage owner, boolean rtl, @SuppressWarnings("removal") AccessControlContext acc) { + @Override public TKStage createTKStage(Window peerWindow, boolean securityDialog, StageStyle stageStyle, boolean primary, Modality modality, WindowRegionClassifier classifier, TKStage owner, boolean rtl, @SuppressWarnings("removal") AccessControlContext acc) { assertToolkitRunning(); - WindowStage stage = new WindowStage(peerWindow, securityDialog, stageStyle, modality, owner); + WindowStage stage = new WindowStage(peerWindow, securityDialog, stageStyle, modality, classifier, owner); stage.setSecurityContext(acc); if (primary) { stage.setIsPrimary(); @@ -684,7 +685,7 @@ void vsyncHint() { assertToolkitRunning(); boolean securityDialog = owner instanceof WindowStage ? ((WindowStage)owner).isSecurityDialog() : false; - WindowStage stage = new WindowStage(peerWindow, securityDialog, popupStyle, null, owner); + WindowStage stage = new WindowStage(peerWindow, securityDialog, popupStyle, null, null, owner); stage.setSecurityContext(acc); stage.setIsPopup(); stage.init(systemMenu); diff --git a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/WindowStage.java b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/WindowStage.java index de873c34d5e..4080a91b9c2 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/WindowStage.java +++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/WindowStage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -39,6 +39,7 @@ import javafx.stage.Modality; import javafx.stage.Stage; import javafx.stage.StageStyle; +import javafx.stage.WindowRegionClassifier; import com.sun.glass.events.WindowEvent; import com.sun.glass.ui.*; @@ -64,6 +65,7 @@ class WindowStage extends GlassStage { private StageStyle style; private GlassStage owner = null; private Modality modality = Modality.NONE; + private final WindowRegionClassifier regionClassifier; private final boolean securityDialog; private OverlayWarning warning = null; @@ -102,10 +104,11 @@ static GlassAppletWindow getAppletWindow() { ".QuantumMessagesBundle", LOCALE); - public WindowStage(javafx.stage.Window peerWindow, boolean securityDialog, final StageStyle stageStyle, Modality modality, TKStage owner) { + public WindowStage(javafx.stage.Window peerWindow, boolean securityDialog, final StageStyle stageStyle, Modality modality, WindowRegionClassifier classifier, TKStage owner) { this.style = stageStyle; this.owner = (GlassStage)owner; this.modality = modality; + this.regionClassifier = classifier; this.securityDialog = securityDialog; if (peerWindow instanceof javafx.stage.Stage) { @@ -188,6 +191,9 @@ private void initPlatformWindow() { case UTILITY: windowMask |= Window.TITLED | Window.UTILITY | Window.CLOSABLE; break; + case UNDECORATED_INTERACTIVE: + windowMask |= Window.INTERACTIVE; + // fall through default: windowMask |= (transparent ? Window.TRANSPARENT : Window.UNTITLED) | Window.CLOSABLE; @@ -198,7 +204,7 @@ private void initPlatformWindow() { windowMask |= Window.MODAL; } platformWindow = - app.createWindow(ownerWindow, Screen.getMainScreen(), windowMask); + app.createWindow(ownerWindow, Screen.getMainScreen(), regionClassifier, windowMask); platformWindow.setResizable(resizable); platformWindow.setFocusable(focusable); if (securityDialog) { diff --git a/modules/javafx.graphics/src/main/java/com/sun/prism/d3d/D3DSwapChain.java b/modules/javafx.graphics/src/main/java/com/sun/prism/d3d/D3DSwapChain.java index 98fc188575e..0f5acbe1908 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/prism/d3d/D3DSwapChain.java +++ b/modules/javafx.graphics/src/main/java/com/sun/prism/d3d/D3DSwapChain.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -66,12 +66,15 @@ public boolean prepare(Rectangle dirtyregion) { int sh = texBackBuffer.getContentHeight(); int dw = this.getContentWidth(); int dh = this.getContentHeight(); + int dx = (dw - sw) / 2; + int dy = (dh - sh) / 2; + if (isMSAA()) { context.flushVertexBuffer(); - g.blit(texBackBuffer, null, 0, 0, sw, sh, 0, 0, dw, dh); + g.blit(texBackBuffer, null, 0, 0, sw, sh, dx, dy, dx + sw, dy + sh); } else { g.setCompositeMode(CompositeMode.SRC); - g.drawTexture(texBackBuffer, 0, 0, dw, dh, 0, 0, sw, sh); + g.drawTexture(texBackBuffer, dx, dy, dx + sw, dy + sh, 0, 0, sw, sh); } context.flushVertexBuffer(); texBackBuffer.unlock(); diff --git a/modules/javafx.graphics/src/main/java/javafx/scene/Scene.java b/modules/javafx.graphics/src/main/java/javafx/scene/Scene.java index 5b2b5e0d838..2b4a0a8858d 100644 --- a/modules/javafx.graphics/src/main/java/javafx/scene/Scene.java +++ b/modules/javafx.graphics/src/main/java/javafx/scene/Scene.java @@ -2884,6 +2884,21 @@ public void touchEventEnd() { public Accessible getSceneAccessible() { return getAccessible(); } + + private final PickRay pickRay = new PickRay(); + + @Override + public Node pickNode(double x, double y) { + Node root = Scene.this.getRoot(); + if (root != null) { + pickRay.set(x, y, 1, 0, Double.POSITIVE_INFINITY); + var pickResultChooser = new PickResultChooser(); + root.pickNode(pickRay, pickResultChooser); + return pickResultChooser.getIntersectedNode(); + } + + return null; + } } private class ScenePeerPaintListener implements TKScenePaintListener { diff --git a/modules/javafx.graphics/src/main/java/javafx/stage/Stage.java b/modules/javafx.graphics/src/main/java/javafx/stage/Stage.java index 66dce31e0ed..5d941deaae5 100644 --- a/modules/javafx.graphics/src/main/java/javafx/stage/Stage.java +++ b/modules/javafx.graphics/src/main/java/javafx/stage/Stage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -532,6 +532,39 @@ public final Modality getModality() { return modality; } + private WindowRegionClassifier regionClassifier; + + /** + * Specifies the {@code WindowRegionClassifier} for this stage. + * Stages that use the {@link StageStyle#UNDECORATED_INTERACTIVE} style should also provide a + * window region classifier that returns the {@link WindowRegion} for a given coordinate. + *

+ * The JavaFX windowing subsystem may use this information to enable platform-specific window + * interactions or animations when the user interacts with each of the various window regions. + * For example, clicking and dragging the {@link WindowRegion#TITLE} region may move the window, + * while double-clicking may maximize the window or restore it from its maximized state. + * + * @param classifier the window region classifier + * @since 18 + */ + public final void initRegionClassifier(WindowRegionClassifier classifier) { + if (hasBeenVisible) { + throw new IllegalStateException("Cannot set classifier once stage has been set visible"); + } + + this.regionClassifier = classifier; + } + + /** + * Retrieves the {@code WindowRegionClassifier} for this stage. + * + * @return the window region classifier + * @since 18 + */ + public final WindowRegionClassifier getRegionClassifier() { + return regionClassifier; + } + private Window owner = null; /** @@ -1153,7 +1186,7 @@ private void doVisibleChanging(boolean value) { } } setPeer(toolkit.createTKStage(this, isSecurityDialog(), - stageStyle, isPrimary(), getModality(), tkStage, rtl, acc)); + stageStyle, isPrimary(), getModality(), getRegionClassifier(), tkStage, rtl, acc)); getPeer().setMinimumSize((int) Math.ceil(getMinWidth()), (int) Math.ceil(getMinHeight())); getPeer().setMaximumSize((int) Math.floor(getMaxWidth()), diff --git a/modules/javafx.graphics/src/main/java/javafx/stage/StageStyle.java b/modules/javafx.graphics/src/main/java/javafx/stage/StageStyle.java index baed126e9e4..de843aee878 100644 --- a/modules/javafx.graphics/src/main/java/javafx/stage/StageStyle.java +++ b/modules/javafx.graphics/src/main/java/javafx/stage/StageStyle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -41,6 +41,15 @@ public enum StageStyle { */ UNDECORATED, + /** + * Defines a {@code Stage} style that is similar to {@code StageStyle.UNDECORATED}, but enables + * platform-specific window interactions. A stage that is initialized with this style must also + * provide a region classifier using {@link Stage#initRegionClassifier(WindowRegionClassifier)}. + * + * @since 18 + */ + UNDECORATED_INTERACTIVE, + /** * Defines a {@code Stage} style with a transparent background and no decorations. * This is a conditional feature; to check if it is supported use diff --git a/modules/javafx.graphics/src/main/java/javafx/stage/WindowRegion.java b/modules/javafx.graphics/src/main/java/javafx/stage/WindowRegion.java new file mode 100644 index 00000000000..309ec5d3d11 --- /dev/null +++ b/modules/javafx.graphics/src/main/java/javafx/stage/WindowRegion.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 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. + */ + +package javafx.stage; + +/** + * Defines the regions of a window. + * + * @since 18 + */ +public enum WindowRegion { + /** + * The region is not a part of the window. + */ + NONE, + + /** + * The client area, which includes everything that is not part of one of the other named regions. + */ + CLIENT, + + /** + * The title bar of the window, which may afford a click-and-drag interaction. + */ + TITLE, + + /** + * The top border of the window, which may afford a click-and-resize interaction. + */ + TOP, + + /** + * The top-right corner of the window, which may afford a click-and-resize interaction. + */ + TOP_RIGHT, + + /** + * The right border of the window, which may afford a click-and-resize interaction. + */ + RIGHT, + + /** + * The bottom-right corner of the window, which may afford a click-and-resize interaction. + */ + BOTTOM_RIGHT, + + /** + * The bottom border of the window, which may afford a click-and-resize interaction. + */ + BOTTOM, + + /** + * The bottom-left corner of the window, which may afford a click-and-resize interaction. + */ + BOTTOM_LEFT, + + /** + * The left border of the window, which may afford a click-and-resize interaction. + */ + LEFT, + + /** + * The top-left corner of the window, which may afford a click-and-resize interaction. + */ + TOP_LEFT +} diff --git a/modules/javafx.graphics/src/main/java/javafx/stage/WindowRegionClassifier.java b/modules/javafx.graphics/src/main/java/javafx/stage/WindowRegionClassifier.java new file mode 100644 index 00000000000..a89ab04fa7f --- /dev/null +++ b/modules/javafx.graphics/src/main/java/javafx/stage/WindowRegionClassifier.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 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. + */ + +package javafx.stage; + +import javafx.scene.Node; + +/** + * Classifier that is used by windows with the {@link StageStyle#UNDECORATED_INTERACTIVE} style + * to determine which region of a window was interacted with. + * + * @since 18 + */ +@FunctionalInterface +public interface WindowRegionClassifier { + + /** + * Determines which window region corresponds to the specified coordinates. + * + * @param x x-coordinate, relative to the left window border + * @param y y-coordinate, relative to the top window border + * @param node the top-most node at the position indicated by {@code x} and {@code y}, + * or {@code null} if there is no node at this position + * @return the window region + */ + WindowRegion classify(double x, double y, Node node); + +} diff --git a/modules/javafx.graphics/src/main/native-glass/win/GlassView.cpp b/modules/javafx.graphics/src/main/native-glass/win/GlassView.cpp index a08d9faab1f..04e57288e37 100644 --- a/modules/javafx.graphics/src/main/native-glass/win/GlassView.cpp +++ b/modules/javafx.graphics/src/main/native-glass/win/GlassView.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -344,13 +344,7 @@ JNIEXPORT jint JNICALL Java_com_sun_glass_ui_win_WinView__1getX return 0; } - RECT rect1, rect2; - - ::GetWindowRect(hWnd, &rect1); - ::GetClientRect(hWnd, &rect2); - ::MapWindowPoints(hWnd, (HWND)NULL, (LPPOINT)&rect2, (sizeof(RECT)/sizeof(POINT))); - - return rect2.left - rect1.left; + return utils::GetScreenSpaceClipRect(hWnd).left; } LEAVE_MAIN_THREAD_WITH_view; @@ -373,14 +367,7 @@ JNIEXPORT jint JNICALL Java_com_sun_glass_ui_win_WinView__1getY return 0; } - RECT rect1, rect2; - POINT p = {0, 0}; - - ::GetWindowRect(hWnd, &rect1); - ::GetClientRect(hWnd, &rect2); - ::MapWindowPoints(hWnd, (HWND)NULL, (LPPOINT)&rect2, (sizeof(RECT)/sizeof(POINT))); - - return rect2.top - rect1.top; + return utils::GetScreenSpaceClipRect(hWnd).top; } LEAVE_MAIN_THREAD_WITH_view; @@ -428,6 +415,11 @@ JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinView__1uploadPixels GlassWindow *pWindow = GlassWindow::FromHandle(hWnd); Pixels pixels(GetEnv(), jPixels); + RECT windowRect; + ::GetWindowRect(hWnd, &windowRect); + SIZE windowSize = { windowRect.right - windowRect.left, windowRect.bottom - windowRect.top }; + int dx = (windowSize.cx - pixels.GetWidth()) / 2; + int dy = (windowSize.cy - pixels.GetHeight()) / 2; if (!pWindow || !pWindow->IsTransparent()) { // Either a non-glass window (FullScreenWindow), or not transparent @@ -444,7 +436,7 @@ JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinView__1uploadPixels HDC hdcDst = ::GetDC(hWnd); ::SetDIBitsToDevice( hdcDst, - 0, 0, pixels.GetWidth(), pixels.GetHeight(), + dx, dy, pixels.GetWidth(), pixels.GetHeight(), 0, 0, 0, pixels.GetHeight(), pixels.GetBits(), @@ -452,18 +444,15 @@ JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinView__1uploadPixels ::ReleaseDC(hWnd, hdcDst); } else { // IsTransparent() == TRUE // http://msdn.microsoft.com/en-us/library/ms997507.aspx - RECT rect; - ::GetWindowRect(hWnd, &rect); - SIZE size = { rect.right - rect.left, rect.bottom - rect.top }; - if (size.cx != pixels.GetWidth() || size.cy != pixels.GetHeight()) { + if (windowSize.cx != pixels.GetWidth() || windowSize.cy != pixels.GetHeight()) { //XXX: should report a error? OTOH, we could proceed, but //this will cause the window to resize to the size of the bitmap return; } POINT ptSrc = { 0, 0 }; - POINT ptDst = { rect.left, rect.top }; + POINT ptDst = { windowRect.left, windowRect.top }; BLENDFUNCTION bf; bf.SourceConstantAlpha = pWindow->GetAlpha(); @@ -477,7 +466,7 @@ JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinView__1uploadPixels HDC hdcSrc = ::CreateCompatibleDC(NULL); HBITMAP oldBitmap = (HBITMAP)::SelectObject(hdcSrc, bitmap); - ::UpdateLayeredWindow(hWnd, hdcDst, &ptDst, &size, hdcSrc, &ptSrc, + ::UpdateLayeredWindow(hWnd, hdcDst, &ptDst, &windowSize, hdcSrc, &ptSrc, RGB(0, 0, 0), &bf, ULW_ALPHA); ::SelectObject(hdcSrc, oldBitmap); diff --git a/modules/javafx.graphics/src/main/native-glass/win/GlassWindow.cpp b/modules/javafx.graphics/src/main/native-glass/win/GlassWindow.cpp index 384782e2a6e..06de57672c7 100644 --- a/modules/javafx.graphics/src/main/native-glass/win/GlassWindow.cpp +++ b/modules/javafx.graphics/src/main/native-glass/win/GlassWindow.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -62,7 +62,7 @@ HHOOK GlassWindow::sm_hCBTFilter = NULL; HWND GlassWindow::sm_grabWindow = NULL; static HWND activeTouchWindow = NULL; -GlassWindow::GlassWindow(jobject jrefThis, bool isTransparent, bool isDecorated, bool isUnified, bool isChild, HWND parentOrOwner) +GlassWindow::GlassWindow(jobject jrefThis, bool isTransparent, bool isDecorated, bool isUnified, bool isInteractive, bool isChild, HWND parentOrOwner) : BaseWnd(parentOrOwner), ViewContainer(), m_winChangingReason(Unknown), @@ -74,6 +74,7 @@ GlassWindow::GlassWindow(jobject jrefThis, bool isTransparent, bool isDecorated, m_isTransparent(isTransparent), m_isDecorated(isDecorated), m_isUnified(isUnified), + m_isInteractive(isInteractive), m_hMenu(NULL), m_alpha(255), m_isEnabled(true), @@ -106,6 +107,12 @@ GlassWindow::GlassWindow(jobject jrefThis, bool isTransparent, bool isDecorated, GlassWindow::~GlassWindow() { + LONG_PTR userData = ::GetWindowLongPtr(GetHWND(), GWLP_USERDATA); + if (userData != NULL) { + delete (WndUserData*)userData; + ::SetWindowLongPtr(GetHWND(), GWLP_USERDATA, NULL); + } + if (m_hIcon) { ::DestroyIcon(m_hIcon); } @@ -153,11 +160,21 @@ HWND GlassWindow::Create(DWORD dwStyle, DWORD dwExStyle, HMONITOR hMonitor, HWND ViewContainer::InitDropTarget(hwnd); ViewContainer::InitManipProcessor(hwnd); + WndUserData* userData = new WndUserData(); + userData->interactive = m_isInteractive; + ::SetWindowLongPtr(hwnd, GWLP_USERDATA, LONG_PTR(userData)); + return hwnd; } void GlassWindow::Close() { + LONG_PTR userData = ::GetWindowLongPtr(GetHWND(), GWLP_USERDATA); + if (userData != NULL) { + delete (WndUserData*)userData; + ::SetWindowLongPtr(GetHWND(), GWLP_USERDATA, NULL); + } + UngrabFocus(); ViewContainer::ReleaseDropTarget(); ViewContainer::ReleaseManipProcessor(); @@ -343,8 +360,8 @@ LRESULT GlassWindow::WindowProc(UINT msg, WPARAM wParam, LPARAM lParam) // It's possible that move/size events are reported by the platform // before the peer listener is set. As a result, location/size are // not reported, so resending them from here. - HandleMoveEvent(NULL); - HandleSizeEvent(com_sun_glass_events_WindowEvent_RESIZE, NULL); + HandleMoveEvent(); + HandleSizeEvent(com_sun_glass_events_WindowEvent_RESIZE); // The call below may be restricted to WS_POPUP windows NotifyViewSize(GetHWND()); @@ -356,10 +373,10 @@ LRESULT GlassWindow::WindowProc(UINT msg, WPARAM wParam, LPARAM lParam) } break; case WM_DWMCOMPOSITIONCHANGED: - if (m_isUnified && (IS_WINVISTA)) { + if ((m_isUnified || m_isInteractive) && (IS_WINVISTA)) { BOOL bEnabled = FALSE; if(SUCCEEDED(::DwmIsCompositionEnabled(&bEnabled)) && bEnabled) { - MARGINS dwmMargins = { -1, -1, -1, -1 }; + MARGINS dwmMargins = { m_isInteractive ? 1 : -1 }; ::DwmExtendFrameIntoClientArea(GetHWND(), &dwmMargins); } } @@ -374,18 +391,18 @@ LRESULT GlassWindow::WindowProc(UINT msg, WPARAM wParam, LPARAM lParam) switch (wParam) { case SIZE_RESTORED: if (m_state != Normal) { - HandleSizeEvent(com_sun_glass_events_WindowEvent_RESTORE, NULL); + HandleSizeEvent(com_sun_glass_events_WindowEvent_RESTORE); m_state = Normal; } else { - HandleSizeEvent(com_sun_glass_events_WindowEvent_RESIZE, NULL); + HandleSizeEvent(com_sun_glass_events_WindowEvent_RESIZE); } break; case SIZE_MINIMIZED: - HandleSizeEvent(com_sun_glass_events_WindowEvent_MINIMIZE, NULL); + HandleSizeEvent(com_sun_glass_events_WindowEvent_MINIMIZE); m_state = Minimized; break; case SIZE_MAXIMIZED: - HandleSizeEvent(com_sun_glass_events_WindowEvent_MAXIMIZE, NULL); + HandleSizeEvent(com_sun_glass_events_WindowEvent_MAXIMIZE); m_state = Maximized; break; } @@ -396,7 +413,7 @@ LRESULT GlassWindow::WindowProc(UINT msg, WPARAM wParam, LPARAM lParam) break; case WM_MOVE: if (!::IsIconic(GetHWND())) { - HandleMoveEvent(NULL); + HandleMoveEvent(); } break; case WM_WINDOWPOSCHANGING: @@ -492,6 +509,9 @@ LRESULT GlassWindow::WindowProc(UINT msg, WPARAM wParam, LPARAM lParam) // p->rgrc[0].bottom++; // return WVR_VALIDRECTS; // } + if (BOOL(wParam) && IsInteractive()) { + return 0; + } break; case WM_PAINT: HandleViewPaintEvent(GetHWND(), msg, wParam, lParam); @@ -583,6 +603,11 @@ LRESULT GlassWindow::WindowProc(UINT msg, WPARAM wParam, LPARAM lParam) return 0; } break; + case WM_NCHITTEST: + if (IsInteractive()) { + return HandleNCHitTestEvent(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); + } + break; case WM_NCLBUTTONDOWN: case WM_NCMBUTTONDOWN: case WM_NCRBUTTONDOWN: @@ -754,34 +779,19 @@ void GlassWindow::HandleWindowPosChangingEvent(WINDOWPOS *pWinPos) } } -// if pRect == NULL => get position/size by GetWindowRect -void GlassWindow::HandleMoveEvent(RECT *pRect) +void GlassWindow::HandleMoveEvent() { JNIEnv* env = GetEnv(); - - RECT r; - if (pRect == NULL) { - ::GetWindowRect(GetHWND(), &r); - pRect = &r; - } - - env->CallVoidMethod(m_grefThis, midNotifyMove, pRect->left, pRect->top); + RECT rect = utils::GetScreenSpaceWindowRect(GetHWND()); + env->CallVoidMethod(m_grefThis, midNotifyMove, rect.left, rect.top); CheckAndClearException(env); } -// if pRect == NULL => get position/size by GetWindowRect -void GlassWindow::HandleSizeEvent(int type, RECT *pRect) +void GlassWindow::HandleSizeEvent(int type) { JNIEnv* env = GetEnv(); - - RECT r; - if (pRect == NULL) { - ::GetWindowRect(GetHWND(), &r); - pRect = &r; - } - - env->CallVoidMethod(m_grefThis, midNotifyResize, - type, pRect->right-pRect->left, pRect->bottom-pRect->top); + RECT rect = utils::GetScreenSpaceWindowRect(GetHWND()); + env->CallVoidMethod(m_grefThis, midNotifyResize, type, rect.right - rect.left, rect.bottom - rect.top); CheckAndClearException(env); } @@ -806,6 +816,14 @@ void GlassWindow::HandleFocusDisabledEvent() CheckAndClearException(env); } +LRESULT GlassWindow::HandleNCHitTestEvent(SHORT x, SHORT y) +{ + JNIEnv* env = GetEnv(); + jint result = env->CallIntMethod(m_grefThis, javaIDs.Window.classifyWindowRegion, jint(x), jint(y)); + CheckAndClearException(env); + return LRESULT(result); +} + bool GlassWindow::HandleCommand(WORD cmdID) { return HandleMenuCommand(GetHWND(), cmdID); } @@ -905,6 +923,10 @@ bool GlassWindow::SetResizable(bool resizable) resizableStyle |= WS_THICKFRAME; } + if (IsInteractive()) { + resizableStyle |= WS_POPUP | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION; + } + if (resizable) { style |= resizableStyle; } else { @@ -1216,6 +1238,10 @@ JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinWindow__1initIDs javaIDs.Window.notifyDelegatePtr = env->GetMethodID(cls, "notifyDelegatePtr", "(J)V"); ASSERT(javaIDs.Window.notifyDelegatePtr); if (env->ExceptionCheck()) return; + + javaIDs.Window.classifyWindowRegion = env->GetMethodID(cls, "classifyWindowRegion", "(II)I"); + ASSERT(javaIDs.Window.classifyWindowRegion); + if (env->ExceptionCheck()) return; } /* @@ -1277,6 +1303,7 @@ JNIEXPORT jlong JNICALL Java_com_sun_glass_ui_win_WinWindow__1createWindow (mask & com_sun_glass_ui_Window_TRANSPARENT) != 0, (mask & com_sun_glass_ui_Window_TITLED) != 0, (mask & com_sun_glass_ui_Window_UNIFIED) != 0, + (mask & com_sun_glass_ui_Window_INTERACTIVE) != 0, false, owner); @@ -1332,7 +1359,7 @@ JNIEXPORT jlong JNICALL Java_com_sun_glass_ui_win_WinWindow__1createChildWindow dwExStyle = WS_EX_NOINHERITLAYOUT; GlassWindow *pWindow = - new GlassWindow(jThis, false, false, false, true, parent); + new GlassWindow(jThis, false, false, false, false, true, parent); HWND hWnd = pWindow->Create(dwStyle, dwExStyle, NULL, parent); diff --git a/modules/javafx.graphics/src/main/native-glass/win/GlassWindow.h b/modules/javafx.graphics/src/main/native-glass/win/GlassWindow.h index d3cab5f0217..0702a7db13b 100644 --- a/modules/javafx.graphics/src/main/native-glass/win/GlassWindow.h +++ b/modules/javafx.graphics/src/main/native-glass/win/GlassWindow.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -32,7 +32,7 @@ class GlassWindow : public BaseWnd, public ViewContainer { public: - GlassWindow(jobject jrefThis, bool isTransparent, bool isDecorated, bool isUnified, bool isChild, HWND parentOrOwner); + GlassWindow(jobject jrefThis, bool isTransparent, bool isDecorated, bool isUnified, bool isInteractive, bool isChild, HWND parentOrOwner); virtual ~GlassWindow(); static GlassWindow* FromHandle(HWND hWnd) { @@ -60,6 +60,7 @@ class GlassWindow : public BaseWnd, public ViewContainer { inline bool IsTransparent() { return m_isTransparent; } inline bool IsResizable() { return m_isResizable; } inline bool IsDecorated() { return m_isDecorated; } + inline bool IsInteractive() { return m_isInteractive; } inline virtual bool IsGlassWindow() { return true; } bool SetResizable(bool resizable); @@ -146,6 +147,7 @@ class GlassWindow : public BaseWnd, public ViewContainer { const bool m_isTransparent; const bool m_isDecorated; const bool m_isUnified; + const bool m_isInteractive; const HWND m_parent; // != NULL for child windows only bool m_isResizable; @@ -181,12 +183,13 @@ class GlassWindow : public BaseWnd, public ViewContainer { void HandleDestroyEvent(); // if pRect == NULL => get position/size by GetWindowRect void HandleWindowPosChangingEvent(WINDOWPOS *pWinPos); - void HandleMoveEvent(RECT *pRect); + void HandleMoveEvent(); // if pRect == NULL => get position/size by GetWindowRect - void HandleSizeEvent(int type, RECT *pRect); + void HandleSizeEvent(int type); void HandleDPIEvent(WPARAM wParam, LPARAM lParam); bool HandleCommand(WORD cmdID); void HandleFocusDisabledEvent(); + LRESULT HandleNCHitTestEvent(SHORT, SHORT); }; diff --git a/modules/javafx.graphics/src/main/native-glass/win/Utils.cpp b/modules/javafx.graphics/src/main/native-glass/win/Utils.cpp index 0589874ff00..fe7fe476b43 100644 --- a/modules/javafx.graphics/src/main/native-glass/win/Utils.cpp +++ b/modules/javafx.graphics/src/main/native-glass/win/Utils.cpp @@ -107,6 +107,164 @@ jint GetModifiers() return modifiers; } +RECT utils::GetScreenSpaceClipRect(HWND hwnd) +{ + WINDOWPLACEMENT placement = {}; + MONITORINFO monitorInfo = {}; + monitorInfo.cbSize = sizeof(MONITORINFO); + LONG_PTR userData = ::GetWindowLongPtr(hwnd, GWLP_USERDATA); + + // Due to historical reasons, a maximized window with the undecorated-interactive style + // will extend slightly beyond the edges of the screen's work area. The pixels that fall + // outside of the work area are clipped, which we need to take into account here. + if (userData != NULL + && ((WndUserData*)userData)->interactive + && SUCCEEDED(::GetWindowPlacement(hwnd, &placement)) + && placement.showCmd == SW_SHOWMAXIMIZED + && GetMonitorInfo(MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST), &monitorInfo)) { + return monitorInfo.rcWork; + } + + RECT rect; + POINT p = {0, 0}; + ::GetClientRect(hwnd, &rect); + ::MapWindowPoints(hwnd, NULL, (POINT*)&rect, 2); + return rect; +} + +RECT utils::GetScreenSpaceWindowRect(HWND hwnd) +{ + WINDOWPLACEMENT placement = {}; + MONITORINFO monitorInfo = {}; + monitorInfo.cbSize = sizeof(MONITORINFO); + LONG_PTR userData = ::GetWindowLongPtr(hwnd, GWLP_USERDATA); + + if (userData != NULL + && ((WndUserData*)userData)->interactive + && SUCCEEDED(::GetWindowPlacement(hwnd, &placement)) + && placement.showCmd == SW_SHOWMAXIMIZED + && GetMonitorInfo(MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST), &monitorInfo)) { + return monitorInfo.rcWork; + } + + RECT rect; + ::GetWindowRect(hwnd, &rect); + return rect; +} + +BOOL utils::GetClipRect(HWND hwnd, LPRECT rect) +{ + if (rect == NULL) { + return FALSE; + } + + WINDOWPLACEMENT placement = {}; + MONITORINFO monitorInfo = {}; + monitorInfo.cbSize = sizeof(MONITORINFO); + LONG_PTR userData = ::GetWindowLongPtr(hwnd, GWLP_USERDATA); + + if (userData != NULL + && ((WndUserData*)userData)->interactive + && SUCCEEDED(::GetWindowPlacement(hwnd, &placement)) + && placement.showCmd == SW_SHOWMAXIMIZED + && GetMonitorInfo(MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST), &monitorInfo)) { + RECT r = monitorInfo.rcWork; + *rect = { 0, 0, r.right - r.left, r.bottom - r.top }; + return TRUE; + } + + return ::GetClientRect(hwnd, rect); +} + +BOOL utils::ScreenToClip(HWND hwnd, LPPOINT point) +{ + if (point == NULL) { + return FALSE; + } + + WINDOWPLACEMENT placement = {}; + MONITORINFO monitorInfo = {}; + monitorInfo.cbSize = sizeof(MONITORINFO); + LONG_PTR userData = ::GetWindowLongPtr(hwnd, GWLP_USERDATA); + + if (userData != NULL + && ((WndUserData*)userData)->interactive + && SUCCEEDED(::GetWindowPlacement(hwnd, &placement)) + && placement.showCmd == SW_SHOWMAXIMIZED) { + RECT rect; + if (::GetMonitorInfo(MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST), &monitorInfo) + && ::GetWindowRect(hwnd, &rect) + && ::ScreenToClient(hwnd, point)) { + point->x -= monitorInfo.rcWork.left - rect.left; + point->y -= monitorInfo.rcWork.top - rect.top; + return TRUE; + } else { + return FALSE; + } + } + + return ::ScreenToClient(hwnd, point); +} + +BOOL utils::ClipToScreen(HWND hwnd, LPPOINT point) +{ + if (point == NULL) { + return FALSE; + } + + WINDOWPLACEMENT placement = {}; + MONITORINFO monitorInfo = {}; + monitorInfo.cbSize = sizeof(MONITORINFO); + LONG_PTR userData = ::GetWindowLongPtr(hwnd, GWLP_USERDATA); + + if (userData != NULL + && ((WndUserData*)userData)->interactive + && SUCCEEDED(::GetWindowPlacement(hwnd, &placement)) + && placement.showCmd == SW_SHOWMAXIMIZED) { + RECT rect; + if (::GetMonitorInfo(MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST), &monitorInfo) + && ::GetWindowRect(hwnd, &rect) + && ::ClientToScreen(hwnd, point)) { + point->x += monitorInfo.rcWork.left - rect.left; + point->y += monitorInfo.rcWork.top - rect.top; + return TRUE; + } else { + return FALSE; + } + } + + return ::ClientToScreen(hwnd, point); +} + +BOOL utils::ClientToClip(HWND hwnd, LPPOINT point) +{ + if (point == NULL) { + return FALSE; + } + + WINDOWPLACEMENT placement = {}; + MONITORINFO monitorInfo = {}; + monitorInfo.cbSize = sizeof(MONITORINFO); + LONG_PTR userData = ::GetWindowLongPtr(hwnd, GWLP_USERDATA); + + if (userData != NULL + && ((WndUserData*)userData)->interactive + && SUCCEEDED(::GetWindowPlacement(hwnd, &placement)) + && placement.showCmd == SW_SHOWMAXIMIZED) { + RECT rect; + if (::GetMonitorInfo(MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST), &monitorInfo) + && ::GetWindowRect(hwnd, &rect)) { + point->x -= monitorInfo.rcWork.left - rect.left; + point->y -= monitorInfo.rcWork.top - rect.top; + return TRUE; + } else { + return FALSE; + } + } + + return TRUE; +} + extern "C" { #ifdef STATIC_BUILD diff --git a/modules/javafx.graphics/src/main/native-glass/win/Utils.h b/modules/javafx.graphics/src/main/native-glass/win/Utils.h index 113a4353e02..d722b2be713 100644 --- a/modules/javafx.graphics/src/main/native-glass/win/Utils.h +++ b/modules/javafx.graphics/src/main/native-glass/win/Utils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -85,6 +85,19 @@ jboolean CheckAndClearException(JNIEnv *env); jint GetModifiers(); +struct WndUserData { + bool interactive = false; +}; + +namespace utils { + RECT GetScreenSpaceClipRect(HWND); + RECT GetScreenSpaceWindowRect(HWND); + BOOL GetClipRect(HWND, LPRECT); + BOOL ScreenToClip(HWND, LPPOINT); + BOOL ClipToScreen(HWND, LPPOINT); + BOOL ClientToClip(HWND, LPPOINT); +} + class JString { public: JString(JNIEnv *env, jstring jString) { @@ -443,6 +456,7 @@ typedef struct _tagJavaIDs { jmethodID notifyFocusUngrab; jmethodID notifyDestroy; jmethodID notifyDelegatePtr; + jmethodID classifyWindowRegion; } Window; struct { jmethodID notifyResize; diff --git a/modules/javafx.graphics/src/main/native-glass/win/ViewContainer.cpp b/modules/javafx.graphics/src/main/native-glass/win/ViewContainer.cpp index 5626fa3eb82..4c96d34ab0c 100644 --- a/modules/javafx.graphics/src/main/native-glass/win/ViewContainer.cpp +++ b/modules/javafx.graphics/src/main/native-glass/win/ViewContainer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -212,13 +212,12 @@ void ViewContainer::NotifyViewSize(HWND hwnd) return; } - RECT r; - if (::GetClientRect(hwnd, &r)) { - JNIEnv* env = GetEnv(); - env->CallVoidMethod(GetView(), javaIDs.View.notifyResize, - r.right-r.left, r.bottom - r.top); - CheckAndClearException(env); - } + RECT rect; + utils::GetClipRect(hwnd, &rect); + JNIEnv* env = GetEnv(); + env->CallVoidMethod(GetView(), javaIDs.View.notifyResize, + rect.right - rect.left, rect.bottom - rect.top); + CheckAndClearException(env); } void ViewContainer::HandleViewPaintEvent(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) @@ -322,10 +321,10 @@ void ViewContainer::HandleViewMenuEvent(HWND hwnd, UINT msg, WPARAM wParam, LPAR POINT pt; int absX = pt.x = GET_X_LPARAM(lParam); int absY = pt.y = GET_Y_LPARAM(lParam); - ::ScreenToClient (hwnd, &pt); + utils::ScreenToClip(hwnd, &pt); if (!isKeyboardTrigger) { RECT rect; - ::GetClientRect(hwnd, &rect); + utils::GetClipRect(hwnd, &rect); if (!::PtInRect(&rect, pt)) { return; } @@ -334,7 +333,7 @@ void ViewContainer::HandleViewMenuEvent(HWND hwnd, UINT msg, WPARAM wParam, LPAR LONG style = ::GetWindowLong(hwnd, GWL_EXSTYLE); if (style & WS_EX_LAYOUTRTL) { RECT rect = {0}; - ::GetClientRect(hwnd, &rect); + utils::GetClipRect(hwnd, &rect); pt.x = max(0, rect.right - rect.left) - pt.x; } JNIEnv* env = GetEnv(); @@ -759,7 +758,7 @@ BOOL ViewContainer::HandleViewMouseEvent(HWND hwnd, UINT msg, WPARAM wParam, LPA pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam); // this is screen coords, convert to client - ::ScreenToClient(hwnd, &pt); + utils::ScreenToClip(hwnd, &pt); // Windows has finished tracking mouse pointer already m_bTrackingMouse = FALSE; @@ -769,6 +768,7 @@ BOOL ViewContainer::HandleViewMouseEvent(HWND hwnd, UINT msg, WPARAM wParam, LPA // for all other messages lParam contains cursor coords pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam); + utils::ClientToClip(hwnd, &pt); switch (msg) { case WM_MOUSEMOVE: @@ -885,16 +885,16 @@ BOOL ViewContainer::HandleViewMouseEvent(HWND hwnd, UINT msg, WPARAM wParam, LPA // get screen coords POINT ptAbs = pt; if (type == com_sun_glass_events_MouseEvent_WHEEL) { - ::ScreenToClient(hwnd, &pt); + utils::ScreenToClip(hwnd, &pt); } else { - ::ClientToScreen(hwnd, &ptAbs); + utils::ClipToScreen(hwnd, &ptAbs); } // unmirror the x coordinate LONG style = ::GetWindowLong(hwnd, GWL_EXSTYLE); if (style & WS_EX_LAYOUTRTL) { RECT rect = {0}; - ::GetClientRect(hwnd, &rect); + utils::GetClipRect(hwnd, &rect); pt.x = max(0, rect.right - rect.left) - pt.x; } @@ -1014,13 +1014,13 @@ void ViewContainer::ResetMouseTracking(HWND hwnd) ::GetCursorPos(&ptAbs); POINT pt = ptAbs; - ::ScreenToClient(hwnd, &pt); + utils::ScreenToClip(hwnd, &pt); // unmirror the x coordinate LONG style = ::GetWindowLong(hwnd, GWL_EXSTYLE); if (style & WS_EX_LAYOUTRTL) { RECT rect = {0}; - ::GetClientRect(hwnd, &rect); + utils::GetClipRect(hwnd, &rect); pt.x = max(0, rect.right - rect.left) - pt.x; } @@ -1130,7 +1130,7 @@ void ViewContainer::WmImeNotify(HWND hwnd, WPARAM wParam, LPARAM lParam) CANDIDATEFORM cf; GetCandidatePos(&curPos); - ::ScreenToClient(hwnd, &curPos); + utils::ScreenToClip(hwnd, &curPos); for (int iCandType=0; iCandType<32; iCandType++, bits<<=1) { if (lParam & bits) { @@ -1294,13 +1294,13 @@ void NotifyTouchInput( POINT client; client.x = screen.x = LONG(ti->x / 100); client.y = screen.y = LONG(ti->y / 100); - ScreenToClient(hWnd, &client); + utils::ScreenToClip(hWnd, &client); // unmirror the x coordinate LONG style = ::GetWindowLong(hWnd, GWL_EXSTYLE); if (style & WS_EX_LAYOUTRTL) { RECT rect = {0}; - ::GetClientRect(hWnd, &rect); + utils::GetClipRect(hWnd, &rect); client.x = max(0, rect.right - rect.left) - client.x; } @@ -1513,13 +1513,13 @@ void ViewContainer::NotifyGesturePerformed(HWND hWnd, POINT client; client.x = screen.x; client.y = screen.y; - ScreenToClient(hWnd, &client); + utils::ScreenToClip(hWnd, &client); // unmirror the x coordinate LONG style = ::GetWindowLong(hWnd, GWL_EXSTYLE); if (style & WS_EX_LAYOUTRTL) { RECT rect = {0}; - ::GetClientRect(hWnd, &rect); + utils::GetClipRect(hWnd, &rect); client.x = max(0, rect.right - rect.left) - client.x; } diff --git a/modules/javafx.graphics/src/test/java/test/com/sun/javafx/pgstub/StubToolkit.java b/modules/javafx.graphics/src/test/java/test/com/sun/javafx/pgstub/StubToolkit.java index ee40fc3c2f1..b6be0059914 100644 --- a/modules/javafx.graphics/src/test/java/test/com/sun/javafx/pgstub/StubToolkit.java +++ b/modules/javafx.graphics/src/test/java/test/com/sun/javafx/pgstub/StubToolkit.java @@ -61,6 +61,7 @@ import javafx.stage.Modality; import javafx.stage.StageStyle; import javafx.stage.Window; +import javafx.stage.WindowRegionClassifier; import javafx.util.Pair; import java.io.File; @@ -120,7 +121,7 @@ public boolean init() { } @Override - public TKStage createTKStage(Window peerWindow, boolean securityDialog, StageStyle stageStyle, boolean primary, Modality modality, TKStage owner, boolean rtl, @SuppressWarnings("removal") AccessControlContext acc) { + public TKStage createTKStage(Window peerWindow, boolean securityDialog, StageStyle stageStyle, boolean primary, Modality modality, WindowRegionClassifier classifier, TKStage owner, boolean rtl, @SuppressWarnings("removal") AccessControlContext acc) { return new StubStage(); } From 054ca0eaed2a454cdf365069371ea1a036a2ccad Mon Sep 17 00:00:00 2001 From: mstr2 <43553916+mstr2@users.noreply.github.com> Date: Thu, 29 Jul 2021 20:57:22 +0200 Subject: [PATCH 2/5] changes --- .../src/main/java/com/sun/glass/ui/gtk/GtkApplication.java | 2 +- .../java/com/sun/glass/ui/monocle/MonocleApplication.java | 2 +- .../src/main/java/com/sun/glass/ui/win/WinView.java | 4 ++-- .../src/main/java/com/sun/glass/ui/win/WinWindow.java | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/gtk/GtkApplication.java b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/gtk/GtkApplication.java index 09d774615a4..6b45badfd5c 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/gtk/GtkApplication.java +++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/gtk/GtkApplication.java @@ -380,7 +380,7 @@ protected void _leaveNestedEventLoop(Object retValue) { @Override public Window createWindow(Window owner, Screen screen, WindowRegionClassifier classifier, int styleMask) { - return new GtkWindow(owner, screen, styleMask); + return new GtkWindow(owner, screen, classifier, styleMask); } @Override diff --git a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/MonocleApplication.java b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/MonocleApplication.java index 9e549faca1a..d02095f1655 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/MonocleApplication.java +++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/MonocleApplication.java @@ -153,7 +153,7 @@ protected void _leaveNestedEventLoop(Object retValue) { @Override public Window createWindow(Window owner, Screen screen, WindowRegionClassifier classifier, int styleMask) { - return new MonocleWindow(owner, screen, styleMask); + return new MonocleWindow(owner, screen, classifier, styleMask); } @Override diff --git a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinView.java b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinView.java index 1540e8b7703..6544568aba3 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinView.java +++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinView.java @@ -98,10 +98,10 @@ protected void notifyResize(int width, int height) { updateLocation(); } - /*@Override + @Override protected MoveResizeHelper getMoveResizeHelper() { // We don't use a move-resize helper on Windows, but handle the WM_NCHITTEST message instead. return null; - }*/ + } } diff --git a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinWindow.java b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinWindow.java index 7dd509aae7b..6234e7c4d25 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinWindow.java +++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinWindow.java @@ -254,7 +254,7 @@ protected boolean _setBackground(long ptr, float r, float g, float b) { } protected int classifyWindowRegion(int x, int y) { - /*if (regionClassifier != null) { + if (regionClassifier != null) { double wx = (x - this.x) / platformScaleX; double wy = (y - this.y) / platformScaleY; @@ -273,7 +273,7 @@ protected int classifyWindowRegion(int x, int y) { case LEFT: return 10; // HTLEFT case TOP_LEFT: return 13; // HTTOPLEFT } - }*/ + } return 1; // HTCLIENT } From 34d943eabddac271e0b5f09af916cdb31c8a711b Mon Sep 17 00:00:00 2001 From: mstr2 <43553916+mstr2@users.noreply.github.com> Date: Thu, 29 Jul 2021 21:07:27 +0200 Subject: [PATCH 3/5] docs --- modules/javafx.graphics/src/main/native-glass/win/Utils.cpp | 3 --- modules/javafx.graphics/src/main/native-glass/win/Utils.h | 5 +++++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/javafx.graphics/src/main/native-glass/win/Utils.cpp b/modules/javafx.graphics/src/main/native-glass/win/Utils.cpp index fe7fe476b43..1a7d82d219c 100644 --- a/modules/javafx.graphics/src/main/native-glass/win/Utils.cpp +++ b/modules/javafx.graphics/src/main/native-glass/win/Utils.cpp @@ -114,9 +114,6 @@ RECT utils::GetScreenSpaceClipRect(HWND hwnd) monitorInfo.cbSize = sizeof(MONITORINFO); LONG_PTR userData = ::GetWindowLongPtr(hwnd, GWLP_USERDATA); - // Due to historical reasons, a maximized window with the undecorated-interactive style - // will extend slightly beyond the edges of the screen's work area. The pixels that fall - // outside of the work area are clipped, which we need to take into account here. if (userData != NULL && ((WndUserData*)userData)->interactive && SUCCEEDED(::GetWindowPlacement(hwnd, &placement)) diff --git a/modules/javafx.graphics/src/main/native-glass/win/Utils.h b/modules/javafx.graphics/src/main/native-glass/win/Utils.h index d722b2be713..935198f09a6 100644 --- a/modules/javafx.graphics/src/main/native-glass/win/Utils.h +++ b/modules/javafx.graphics/src/main/native-glass/win/Utils.h @@ -89,6 +89,11 @@ struct WndUserData { bool interactive = false; }; +// A maximized window will extend slightly beyond the edges of the screen, such that +// its borders are clipped. However, with the undecorated-interactive style, we extended +// the client area to include the (now invisible) borders. +// We define the part of the client area that is visible on the screen as the "clip area" +// and use this area instead of the client area when we are dealing with a maximized window. namespace utils { RECT GetScreenSpaceClipRect(HWND); RECT GetScreenSpaceWindowRect(HWND); From 2a75424b737bf37484e3ef25f6d9f9ce3a7722df Mon Sep 17 00:00:00 2001 From: mstr2 <43553916+mstr2@users.noreply.github.com> Date: Fri, 30 Jul 2021 00:02:02 +0200 Subject: [PATCH 4/5] remove Window.UndecoratedMoveResizeHelper --- .../src/main/java/com/sun/glass/ui/View.java | 9 - .../main/java/com/sun/glass/ui/Window.java | 243 ------------------ 2 files changed, 252 deletions(-) diff --git a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/View.java b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/View.java index 9cd39f0dd56..9d81ab9c847 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/View.java +++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/View.java @@ -929,15 +929,6 @@ protected void notifyMouse(int type, int button, int x, int y, int xAbs, return; } - // gznote: optimize - only call for undecorated Windows! - if (this.window != null) { - // handled by window (programmatical move/resize) - if (this.window.handleMouseEvent(type, button, x, y, xAbs, yAbs)) { - // The evnet has been processed by Glass - return; - } - } - long now = System.nanoTime(); if (type == MouseEvent.DOWN) { View lastClickedView = View.lastClickedView == null ? null : View.lastClickedView.get(); diff --git a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/Window.java b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/Window.java index d92ab193517..ddde1c98f9a 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/Window.java +++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/Window.java @@ -24,7 +24,6 @@ */ package com.sun.glass.ui; -import com.sun.glass.events.MouseEvent; import com.sun.glass.events.WindowEvent; import com.sun.prism.impl.PrismSettings; import javafx.stage.WindowRegionClassifier; @@ -211,7 +210,6 @@ public static final class Level { protected Screen screen = null; private MenuBar menubar = null; private String title = ""; - private UndecoratedMoveResizeHelper helper = null; private int state = State.NORMAL; private int level = Level.NORMAL; @@ -431,9 +429,6 @@ public void setView(final View view) { if (view != null && _setView(this.ptr, view)) { this.view = view; this.view.setWindow(this); - if (this.isDecorated == false) { - this.helper = new UndecoratedMoveResizeHelper(); - } } else { _setView(this.ptr, null); this.view = null; @@ -1318,11 +1313,6 @@ protected void notifyResize(final int type, final int width, final int height) { } this.width = width; this.height = height; - - // update moveRect/resizeRect - if (this.helper != null){ - this.helper.updateRectangles(); - } } handleWindowEvent(System.nanoTime(), type); @@ -1364,102 +1354,6 @@ protected void handleWindowEvent(long time, int type) { } } - // ***************************************************** - // programmatical move/resize - // ***************************************************** - /** Sets "programmatical move" rectangle. - * The rectangle is measured from top of the View: - * width is View.width, height is size. - * - * throws RuntimeException for decorated window. - */ - public void setUndecoratedMoveRectangle(int size) { - Application.checkEventThread(); - if (this.isDecorated == true) { - //throw new RuntimeException("setUndecoratedMoveRectangle is only valid for Undecorated Window"); - System.err.println("Glass Window.setUndecoratedMoveRectangle is only valid for Undecorated Window. In the future this will be hard error."); - Thread.dumpStack(); - return; - } - - if (this.helper != null) { - this.helper.setMoveRectangle(size); - } - } - /** The method called only for undecorated windows - * x, y: mouse coordinates (in View space). - * - * throws RuntimeException for decorated window. - */ - public boolean shouldStartUndecoratedMove(final int x, final int y) { - Application.checkEventThread(); - if (this.shouldStartUndecoratedMove == true) { - return true; - } - if (this.isDecorated == true) { - return false; - } - - if (this.helper != null) { - return this.helper.shouldStartMove(x, y); - } else { - return false; - } - } - - /** Sets "programmatical resize" rectangle. - * The rectangle is measured from top of the View: - * width is View.width, height is size. - * - * throws RuntimeException for decorated window. - */ - public void setUndecoratedResizeRectangle(int size) { - Application.checkEventThread(); - if ((this.isDecorated == true) || (this.isResizable == false)) { - //throw new RuntimeException("setUndecoratedMoveRectangle is only valid for Undecorated Resizable Window"); - System.err.println("Glass Window.setUndecoratedResizeRectangle is only valid for Undecorated Resizable Window. In the future this will be hard error."); - Thread.dumpStack(); - return; - } - - if (this.helper != null) { - this.helper.setResizeRectangle(size); - } - } - - /** The method called only for undecorated windows - * x, y: mouse coordinates (in View space). - * - * throws RuntimeException for decorated window. - */ - public boolean shouldStartUndecoratedResize(final int x, final int y) { - Application.checkEventThread(); - if ((this.isDecorated == true) || (this.isResizable == false)) { - return false; - } - - if (this.helper != null) { - return this.helper.shouldStartResize(x, y); - } else { - return false; - } - } - - /** Mouse event handler for processing programmatical resize/move - * (for undecorated windows only). - * Must be called by View. - * x & y are View coordinates. - * NOTE: it's package private! - * @return true if the event is processed by the window, - * false if it has to be delivered to the app - */ - boolean handleMouseEvent(int type, int button, int x, int y, int xAbs, int yAbs) { - if (this.isDecorated == false) { - return this.helper.handleMouseEvent(type, button, x, y, xAbs, yAbs); - } - return false; - } - @Override public String toString() { Application.checkEventThread(); @@ -1495,143 +1389,6 @@ protected void notifyLevelChanged(int level) { } } - private class UndecoratedMoveResizeHelper { - TrackingRectangle moveRect = null; - TrackingRectangle resizeRect = null; - - boolean inMove = false; // we are in "move" mode - boolean inResize = false; // we are in "resize" mode - - int startMouseX, startMouseY; // start mouse coords - int startX, startY; // start window location (for move) - int startWidth, startHeight; // start window size (for resize) - - UndecoratedMoveResizeHelper() { - this.moveRect = new TrackingRectangle(); - this.resizeRect = new TrackingRectangle(); - } - - void setMoveRectangle(final int size) { - this.moveRect.size = size; - - this.moveRect.x = 0; - this.moveRect.y = 0; - this.moveRect.width = getWidth(); - this.moveRect.height = this.moveRect.size; - } - - boolean shouldStartMove(final int x, final int y) { - return this.moveRect.contains(x, y); - } - - boolean inMove() { - return this.inMove; - } - - void startMove(final int x, final int y) { - this.inMove = true; - - this.startMouseX = x; - this.startMouseY = y; - - this.startX = getX(); - this.startY = getY(); - } - - void deltaMove(final int x, final int y) { - int deltaX = x - this.startMouseX; - int deltaY = y - this.startMouseY; - - setPosition(this.startX + deltaX, this.startY + deltaY); - } - - void stopMove() { - this.inMove = false; - } - - void setResizeRectangle(final int size) { - this.resizeRect.size = size; - - // set the rect (bottom right corner of the Window) - this.resizeRect.x = getWidth() - this.resizeRect.size; - this.resizeRect.y = getHeight() - this.resizeRect.size; - this.resizeRect.width = this.resizeRect.size; - this.resizeRect.height = this.resizeRect.size; - } - - boolean shouldStartResize(final int x, final int y) { - return this.resizeRect.contains(x, y); - } - - boolean inResize() { - return this.inResize; - } - - void startResize(final int x, final int y) { - this.inResize = true; - - this.startMouseX = x; - this.startMouseY = y; - - this.startWidth = getWidth(); - this.startHeight = getHeight(); - } - - void deltaResize(final int x, final int y) { - int deltaX = x - this.startMouseX; - int deltaY = y - this.startMouseY; - - setSize(this.startWidth + deltaX, this.startHeight + deltaY); - } - - protected void stopResize() { - this.inResize = false; - } - - void updateRectangles() { - if (this.moveRect.size > 0) { - setMoveRectangle(this.moveRect.size); - } - if (this.resizeRect.size > 0) { - setResizeRectangle(this.resizeRect.size); - } - } - - boolean handleMouseEvent(final int type, final int button, final int x, final int y, final int xAbs, final int yAbs) { - switch (type) { - case MouseEvent.DOWN: - if (button == MouseEvent.BUTTON_LEFT) { - if (shouldStartUndecoratedMove(x, y) == true) { - startMove(xAbs, yAbs); - return true; - } else if (shouldStartUndecoratedResize(x, y) == true) { - startResize(xAbs, yAbs); - return true; - } - } - break; - - case MouseEvent.MOVE: - case MouseEvent.DRAG: - if (inMove() == true) { - deltaMove(xAbs, yAbs); - return true; - } else if (inResize() == true) { - deltaResize(xAbs, yAbs); - return true; - } - break; - - case MouseEvent.UP: - boolean wasProcessed = inMove() || inResize(); - stopResize(); - stopMove(); - return wasProcessed; - } - return false; - } - } - /** * Requests text input in form of native keyboard for text component * contained by this Window. Native text input component is drawn on the place From b4e8d1da0f85375c813b27cd32a1a7290d36d573 Mon Sep 17 00:00:00 2001 From: mstr2 <43553916+mstr2@users.noreply.github.com> Date: Fri, 30 Jul 2021 15:50:39 +0200 Subject: [PATCH 5/5] doc changes and copyright header --- .../com/sun/glass/ui/MoveResizeHelper.java | 25 +++++++++++++++++++ .../java/com/sun/javafx/tk/DummyToolkit.java | 2 +- .../com/sun/javafx/tk/TKSceneListener.java | 2 +- .../javafx/tk/quantum/GlassAppletWindow.java | 2 +- .../java/com/sun/prism/d3d/D3DSwapChain.java | 6 +++++ .../src/main/native-glass/win/Utils.cpp | 2 +- .../com/sun/javafx/pgstub/StubToolkit.java | 2 +- 7 files changed, 36 insertions(+), 5 deletions(-) diff --git a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/MoveResizeHelper.java b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/MoveResizeHelper.java index a3b3b5b066c..8b070421461 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/MoveResizeHelper.java +++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/MoveResizeHelper.java @@ -1,3 +1,28 @@ +/* + * Copyright (c) 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. + */ + package com.sun.glass.ui; import com.sun.glass.events.MouseEvent; diff --git a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/DummyToolkit.java b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/DummyToolkit.java index 0ca27b721ec..c998f1b3cbe 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/DummyToolkit.java +++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/DummyToolkit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 diff --git a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/TKSceneListener.java b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/TKSceneListener.java index 7678062fa26..3d656244889 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/TKSceneListener.java +++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/TKSceneListener.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/GlassAppletWindow.java b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/GlassAppletWindow.java index d1b7e12a887..507646f6620 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/GlassAppletWindow.java +++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/GlassAppletWindow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 diff --git a/modules/javafx.graphics/src/main/java/com/sun/prism/d3d/D3DSwapChain.java b/modules/javafx.graphics/src/main/java/com/sun/prism/d3d/D3DSwapChain.java index 0f5acbe1908..cc5c5493dbe 100644 --- a/modules/javafx.graphics/src/main/java/com/sun/prism/d3d/D3DSwapChain.java +++ b/modules/javafx.graphics/src/main/java/com/sun/prism/d3d/D3DSwapChain.java @@ -62,6 +62,12 @@ public boolean prepare(Rectangle dirtyregion) { if (g == null) { return false; } + + // The size of the swap chain surface may be different than the size of the back buffer. + // This happens for a maximized window with the UNDECORATED_INTERACTIVE stage style: + // In this case, the window extends slightly beyond the edges of the screen, while the + // back buffer only contains the pixels that are actually visible. We need to center + // the back buffer texture on the swap chain surface to line it up with the screen edges. int sw = texBackBuffer.getContentWidth(); int sh = texBackBuffer.getContentHeight(); int dw = this.getContentWidth(); diff --git a/modules/javafx.graphics/src/main/native-glass/win/Utils.cpp b/modules/javafx.graphics/src/main/native-glass/win/Utils.cpp index 1a7d82d219c..0f4efcbbc08 100644 --- a/modules/javafx.graphics/src/main/native-glass/win/Utils.cpp +++ b/modules/javafx.graphics/src/main/native-glass/win/Utils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 diff --git a/modules/javafx.graphics/src/test/java/test/com/sun/javafx/pgstub/StubToolkit.java b/modules/javafx.graphics/src/test/java/test/com/sun/javafx/pgstub/StubToolkit.java index b6be0059914..6a0d8ffd2da 100644 --- a/modules/javafx.graphics/src/test/java/test/com/sun/javafx/pgstub/StubToolkit.java +++ b/modules/javafx.graphics/src/test/java/test/com/sun/javafx/pgstub/StubToolkit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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