mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-06 09:29:38 +01:00
JBR API v0.0.3
JBR-4228 report HTMINBUTTON, HTMAXBUTTON, HTCLOSE, HTMENU, HTCAPTION targets via JBR API & handle corresponding non-client mouse events for windows with custom decoration
This commit is contained in:
@@ -39,6 +39,7 @@ public class JBRApiModule {
|
||||
.withStatic("getSubpixelResolution", "sun.font.FontUtilities")
|
||||
.service("com.jetbrains.JBRFileDialogService", null)
|
||||
.withStatic("getFileDialog", "com.jetbrains.desktop.JBRFileDialog", "get")
|
||||
.proxy("com.jetbrains.JBRFileDialog", "com.jetbrains.desktop.JBRFileDialog");
|
||||
.proxy("com.jetbrains.JBRFileDialog", "com.jetbrains.desktop.JBRFileDialog")
|
||||
.service("com.jetbrains.CustomWindowDecoration", "java.awt.Window$CustomWindowDecoration");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,13 +46,17 @@ import java.io.ObjectOutputStream;
|
||||
import java.io.OptionalDataException;
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.lang.annotation.Native;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.security.AccessController;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EventListener;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.Vector;
|
||||
@@ -64,6 +68,7 @@ import javax.accessibility.AccessibleRole;
|
||||
import javax.accessibility.AccessibleState;
|
||||
import javax.accessibility.AccessibleStateSet;
|
||||
|
||||
import com.jetbrains.internal.JBRApi;
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.AWTPermissions;
|
||||
import sun.awt.AppContext;
|
||||
@@ -4005,8 +4010,63 @@ public class Window extends Container implements Accessible {
|
||||
}
|
||||
}
|
||||
|
||||
private volatile boolean hasCustomDecoration;
|
||||
private transient volatile boolean hasCustomDecoration;
|
||||
private transient volatile List<Map.Entry<Shape, Integer>> customDecorHitTestSpots;
|
||||
private transient volatile int customDecorTitleBarHeight = -1; // 0 can be a legal value when no title bar is expected
|
||||
|
||||
// called from native
|
||||
private int hitTestCustomDecoration(int x, int y) {
|
||||
var spots = customDecorHitTestSpots;
|
||||
if (spots == null) return CustomWindowDecoration.NO_HIT_SPOT;
|
||||
for (var spot : spots) {
|
||||
if (spot.getKey().contains(x, y)) return spot.getValue();
|
||||
}
|
||||
return CustomWindowDecoration.NO_HIT_SPOT;
|
||||
}
|
||||
|
||||
private static class CustomWindowDecoration {
|
||||
|
||||
@Native public static final int
|
||||
NO_HIT_SPOT = 0,
|
||||
OTHER_HIT_SPOT = 1,
|
||||
MINIMIZE_BUTTON = 2,
|
||||
MAXIMIZE_BUTTON = 3,
|
||||
CLOSE_BUTTON = 4,
|
||||
MENU_BAR = 5,
|
||||
DRAGGABLE_AREA = 6;
|
||||
|
||||
void setCustomDecorationEnabled(Window window, boolean enabled) {
|
||||
window.hasCustomDecoration = enabled;
|
||||
if (Win.INSTANCE != null) {
|
||||
Win.INSTANCE.updateCustomDecoration(window.peer);
|
||||
}
|
||||
}
|
||||
boolean isCustomDecorationEnabled(Window window) {
|
||||
return window.hasCustomDecoration;
|
||||
}
|
||||
|
||||
void setCustomDecorationHitTestSpots(Window window, List<Map.Entry<Shape, Integer>> spots) {
|
||||
window.customDecorHitTestSpots = List.copyOf(spots);
|
||||
}
|
||||
List<Map.Entry<Shape, Integer>> getCustomDecorationHitTestSpots(Window window) {
|
||||
return window.customDecorHitTestSpots;
|
||||
}
|
||||
|
||||
void setCustomDecorationTitleBarHeight(Window window, int height) {
|
||||
if (height >= 0) window.customDecorTitleBarHeight = height;
|
||||
}
|
||||
int getCustomDecorationTitleBarHeight(Window window) {
|
||||
return window.customDecorTitleBarHeight;
|
||||
}
|
||||
|
||||
private interface Win {
|
||||
Win INSTANCE = (Win) JBRApi.internalServiceBuilder(MethodHandles.lookup(), null)
|
||||
.withStatic("updateCustomDecoration", "sun.awt.windows.WFramePeer").build();
|
||||
void updateCustomDecoration(ComponentPeer peer);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
boolean hasCustomDecoration() {
|
||||
return hasCustomDecoration;
|
||||
}
|
||||
@@ -4014,6 +4074,7 @@ public class Window extends Container implements Accessible {
|
||||
/**
|
||||
* Set via reflection (JB JdkEx API).
|
||||
*/
|
||||
@Deprecated
|
||||
void setHasCustomDecoration() {
|
||||
hasCustomDecoration = true;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import java.awt.Frame;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.MenuBar;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.peer.ComponentPeer;
|
||||
import java.awt.peer.FramePeer;
|
||||
import java.security.AccessController;
|
||||
|
||||
@@ -253,4 +254,10 @@ class WFramePeer extends WWindowPeer implements FramePeer {
|
||||
}
|
||||
|
||||
private native void synthesizeWmActivate(boolean activate);
|
||||
|
||||
// JBR API internals
|
||||
private static void updateCustomDecoration(ComponentPeer peer) {
|
||||
if (peer instanceof WFramePeer) ((WFramePeer) peer).updateCustomDecoration();
|
||||
}
|
||||
private native void updateCustomDecoration();
|
||||
}
|
||||
|
||||
@@ -55,8 +55,11 @@ import java.awt.image.DataBufferInt;
|
||||
import java.awt.peer.WindowPeer;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
@@ -995,31 +998,29 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
|
||||
return err;
|
||||
}
|
||||
|
||||
private volatile List<Rectangle> customDecorHitTestSpots;
|
||||
private volatile int customDecorTitleBarHeight = -1; // 0 can be a legal value when no title bar is expected
|
||||
|
||||
// called from client via reflection
|
||||
@Deprecated
|
||||
private void setCustomDecorationHitTestSpots(List<Rectangle> hitTestSpots) {
|
||||
this.customDecorHitTestSpots = new CopyOnWriteArrayList<>(hitTestSpots);
|
||||
List<Map.Entry<Shape, Integer>> spots = new ArrayList<>();
|
||||
for (Rectangle spot : hitTestSpots) spots.add(Map.entry(spot, 1));
|
||||
try {
|
||||
Field f = Window.class.getDeclaredField("customDecorHitTestSpots");
|
||||
f.setAccessible(true);
|
||||
f.set(target, spots);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
// called from client via reflection
|
||||
@Deprecated
|
||||
private void setCustomDecorationTitleBarHeight(int height) {
|
||||
if (height >= 0) customDecorTitleBarHeight = height;
|
||||
}
|
||||
|
||||
// called from native
|
||||
private boolean hitTestCustomDecoration(int x, int y) {
|
||||
List<Rectangle> spots = customDecorHitTestSpots;
|
||||
if (spots == null) return false;
|
||||
for (Rectangle spot : spots) {
|
||||
if (spot.contains(x, y)) return true;
|
||||
try {
|
||||
Field f = Window.class.getDeclaredField("customDecorTitleBarHeight");
|
||||
f.setAccessible(true);
|
||||
f.set(target, height);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// called from native
|
||||
private int getCustomDecorationTitleBarHeight() {
|
||||
return customDecorTitleBarHeight;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1646,6 +1646,9 @@ LRESULT AwtComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
|
||||
case WM_NCRBUTTONDOWN:
|
||||
mr = WmNcMouseDown(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), RIGHT_BUTTON);
|
||||
break;
|
||||
case WM_NCMOUSEMOVE:
|
||||
mr = WmNcMouseMove(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
break;
|
||||
case WM_LBUTTONUP:
|
||||
if (ignoreNextLBTNUP) {
|
||||
ignoreNextLBTNUP = FALSE;
|
||||
@@ -2338,6 +2341,9 @@ MsgRouting AwtComponent::WmNcMouseDown(WPARAM hitTest, int x, int y, int button)
|
||||
MsgRouting AwtComponent::WmNcMouseUp(WPARAM hitTest, int x, int y, int button) {
|
||||
return mrDoDefault;
|
||||
}
|
||||
MsgRouting AwtComponent::WmNcMouseMove(WPARAM hitTest, int x, int y) {
|
||||
return mrDoDefault;
|
||||
}
|
||||
|
||||
MsgRouting AwtComponent::WmWindowPosChanging(LPARAM windowPos) {
|
||||
return mrDoDefault;
|
||||
|
||||
@@ -525,6 +525,7 @@ public:
|
||||
int wheelRotation, BOOL isHorizontal);
|
||||
virtual MsgRouting WmNcMouseDown(WPARAM hitTest, int x, int y, int button);
|
||||
virtual MsgRouting WmNcMouseUp(WPARAM hitTest, int x, int y, int button);
|
||||
virtual MsgRouting WmNcMouseMove(WPARAM hitTest, int x, int y);
|
||||
virtual MsgRouting WmWindowPosChanging(LPARAM windowPos);
|
||||
virtual MsgRouting WmWindowPosChanged(LPARAM windowPos);
|
||||
virtual void WmTouch(WPARAM wParam, LPARAM lParam);
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <dwmapi.h>
|
||||
|
||||
#include <java_lang_Integer.h>
|
||||
#include <java_awt_Window_CustomWindowDecoration.h>
|
||||
#include <sun_awt_windows_WEmbeddedFrame.h>
|
||||
#include <sun_awt_windows_WEmbeddedFramePeer.h>
|
||||
|
||||
@@ -514,7 +515,15 @@ MsgRouting AwtFrame::WmMouseMove(UINT flags, int x, int y) {
|
||||
* If this Frame is non-focusable then we should implement move and size operation for it by
|
||||
* ourselfves because we don't dispatch appropriate mouse messages to default window procedure.
|
||||
*/
|
||||
if (!IsFocusableWindow() && isInManualMoveOrSize) {
|
||||
if (isInManualMoveOrSize) {
|
||||
if (grabbedHitTest == HTCAPTION) {
|
||||
WINDOWPLACEMENT placement;
|
||||
::GetWindowPlacement(GetHWnd(), &placement);
|
||||
if (placement.showCmd == SW_SHOWMAXIMIZED) {
|
||||
placement.showCmd = SW_SHOWNORMAL;
|
||||
::SetWindowPlacement(GetHWnd(), &placement);
|
||||
}
|
||||
}
|
||||
DWORD curPos = ::GetMessagePos();
|
||||
x = GET_X_LPARAM(curPos);
|
||||
y = GET_Y_LPARAM(curPos);
|
||||
@@ -622,6 +631,44 @@ MsgRouting AwtFrame::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) {
|
||||
if (m_grabbedWindow != NULL/* && !m_grabbedWindow->IsOneOfOwnersOf(this)*/) {
|
||||
m_grabbedWindow->Ungrab();
|
||||
}
|
||||
// For windows with custom decorations, handle caption-related mouse events
|
||||
// Do not handle events from caption itself to preserve native drag behavior
|
||||
if (HasCustomDecoration()) {
|
||||
switch (hitTest) {
|
||||
case HTCAPTION:
|
||||
case HTMINBUTTON:
|
||||
case HTMAXBUTTON:
|
||||
case HTCLOSE:
|
||||
case HTMENU:
|
||||
RECT rcWindow;
|
||||
GetWindowRect(GetHWnd(), &rcWindow);
|
||||
if (hitTest == HTCAPTION) {
|
||||
JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2);
|
||||
jint customSpot = JNU_CallMethodByName(env, NULL, GetTarget(env),
|
||||
"hitTestCustomDecoration", "(II)I",
|
||||
ScaleDownX(x - rcWindow.left),
|
||||
ScaleDownY(y - rcWindow.top)).i;
|
||||
if (customSpot == java_awt_Window_CustomWindowDecoration_DRAGGABLE_AREA) {
|
||||
if (button & LEFT_BUTTON) {
|
||||
savedMousePos.x = x;
|
||||
savedMousePos.y = y;
|
||||
::SetCapture(GetHWnd());
|
||||
isInManualMoveOrSize = TRUE;
|
||||
grabbedHitTest = hitTest;
|
||||
}
|
||||
} else break;
|
||||
}
|
||||
POINT myPos;
|
||||
myPos.x = x;
|
||||
myPos.y = y;
|
||||
::ScreenToClient(GetHWnd(), &myPos);
|
||||
WmMouseDown(GetButtonMK(button),
|
||||
myPos.x,
|
||||
myPos.y,
|
||||
button);
|
||||
return mrConsume;
|
||||
}
|
||||
}
|
||||
if (!IsFocusableWindow() && (button & LEFT_BUTTON)) {
|
||||
switch (hitTest) {
|
||||
case HTTOP:
|
||||
@@ -653,6 +700,26 @@ MsgRouting AwtFrame::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) {
|
||||
return AwtWindow::WmNcMouseDown(hitTest, x, y, button);
|
||||
}
|
||||
|
||||
MsgRouting AwtFrame::WmNcMouseMove(WPARAM hitTest, int x, int y) {
|
||||
// For windows with custom decorations, handle caption-related mouse events
|
||||
if (HasCustomDecoration()) {
|
||||
switch (hitTest) {
|
||||
case HTMINBUTTON:
|
||||
case HTMAXBUTTON:
|
||||
case HTCLOSE:
|
||||
case HTMENU:
|
||||
case HTCAPTION:
|
||||
POINT myPos;
|
||||
myPos.x = x;
|
||||
myPos.y = y;
|
||||
::ScreenToClient(GetHWnd(), &myPos);
|
||||
WmMouseMove(0, myPos.x, myPos.y);
|
||||
if (hitTest != HTCAPTION) return mrConsume; // Preserve default window drag for HTCAPTION
|
||||
}
|
||||
}
|
||||
return AwtWindow::WmNcMouseMove(hitTest, x, y);
|
||||
}
|
||||
|
||||
// Override AwtWindow::Reshape() to handle minimized/maximized
|
||||
// frames (see 6525850, 4065534)
|
||||
void AwtFrame::Reshape(int x, int y, int w, int h)
|
||||
@@ -1670,11 +1737,26 @@ BOOL AwtFrame::HasCustomDecoration()
|
||||
if (!m_pHasCustomDecoration) {
|
||||
m_pHasCustomDecoration = new BOOL;
|
||||
JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2);
|
||||
*m_pHasCustomDecoration = JNU_CallMethodByName(env, NULL, GetTarget(env), "hasCustomDecoration", "()Z").z;
|
||||
*m_pHasCustomDecoration = JNU_GetFieldByName(env, NULL, GetTarget(env), "hasCustomDecoration", "Z").z;
|
||||
}
|
||||
return *m_pHasCustomDecoration;
|
||||
}
|
||||
|
||||
void _UpdateCustomDecoration(void* p) {
|
||||
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
|
||||
|
||||
jobject self = reinterpret_cast<jobject>(p);
|
||||
PDATA pData;
|
||||
JNI_CHECK_PEER_GOTO(self, ret);
|
||||
|
||||
AwtFrame* frame = (AwtFrame*)pData;
|
||||
if (!frame->m_pHasCustomDecoration) frame->m_pHasCustomDecoration = new BOOL;
|
||||
*frame->m_pHasCustomDecoration = JNU_GetFieldByName(env, NULL, frame->GetTarget(env), "hasCustomDecoration", "Z").z;
|
||||
frame->RedrawNonClient();
|
||||
ret:
|
||||
env->DeleteGlobalRef(self);
|
||||
}
|
||||
|
||||
void GetSysInsets(RECT* insets, AwtFrame* pFrame) {
|
||||
if (pFrame->IsUndecorated()) {
|
||||
::SetRectEmpty(insets);
|
||||
@@ -1712,10 +1794,8 @@ LRESULT HitTestNCA(AwtFrame* frame, int x, int y) {
|
||||
AdjustWindowRectEx(&rcFrame, WS_OVERLAPPEDWINDOW & ~WS_CAPTION, FALSE, NULL);
|
||||
|
||||
JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2);
|
||||
int titleHeight = (int)JNU_CallMethodByName(env, NULL, frame->GetPeer(env),
|
||||
"getCustomDecorationTitleBarHeight", "()I",
|
||||
frame->ScaleDownX(x - rcWindow.left),
|
||||
frame->ScaleDownY(y - rcWindow.top)).i;
|
||||
int titleHeight = (int)JNU_GetFieldByName(env, NULL, frame->GetTarget(env),
|
||||
"customDecorTitleBarHeight", "I").i;
|
||||
if (titleHeight >= 0) {
|
||||
titleHeight = frame->ScaleUpY(titleHeight);
|
||||
insets.top = titleHeight; // otherwise leave default
|
||||
@@ -1728,12 +1808,24 @@ LRESULT HitTestNCA(AwtFrame* frame, int x, int y) {
|
||||
if (y >= rcWindow.top &&
|
||||
y < rcWindow.top + insets.top)
|
||||
{
|
||||
if (JNU_CallMethodByName(env, NULL, frame->GetPeer(env),
|
||||
"hitTestCustomDecoration", "(II)Z",
|
||||
frame->ScaleDownX(x - rcWindow.left),
|
||||
frame->ScaleDownY(y - rcWindow.top)).z)
|
||||
{
|
||||
return HTNOWHERE;
|
||||
jint customSpot = JNU_CallMethodByName(env, NULL, frame->GetTarget(env),
|
||||
"hitTestCustomDecoration", "(II)I",
|
||||
frame->ScaleDownX(x - rcWindow.left),
|
||||
frame->ScaleDownY(y - rcWindow.top)).i;
|
||||
switch (customSpot) {
|
||||
case java_awt_Window_CustomWindowDecoration_NO_HIT_SPOT:
|
||||
case java_awt_Window_CustomWindowDecoration_DRAGGABLE_AREA:
|
||||
break; // Nothing
|
||||
case java_awt_Window_CustomWindowDecoration_MINIMIZE_BUTTON:
|
||||
return HTMINBUTTON;
|
||||
case java_awt_Window_CustomWindowDecoration_MAXIMIZE_BUTTON:
|
||||
return HTMAXBUTTON;
|
||||
case java_awt_Window_CustomWindowDecoration_CLOSE_BUTTON:
|
||||
return HTCLOSE;
|
||||
case java_awt_Window_CustomWindowDecoration_MENU_BAR:
|
||||
return HTMENU;
|
||||
default:
|
||||
return HTNOWHERE;
|
||||
}
|
||||
fOnResizeBorder = (y < (rcWindow.top - rcFrame.top));
|
||||
uRow = 0;
|
||||
@@ -2160,6 +2252,17 @@ Java_sun_awt_windows_WFramePeer_updateIcon(JNIEnv *env, jobject self)
|
||||
CATCH_BAD_ALLOC;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_awt_windows_WFramePeer_updateCustomDecoration(JNIEnv *env, jobject self)
|
||||
{
|
||||
TRY;
|
||||
|
||||
AwtToolkit::GetInstance().InvokeFunction(_UpdateCustomDecoration, env->NewGlobalRef(self));
|
||||
// global ref is deleted in _UpdateCustomDecoration()
|
||||
|
||||
CATCH_BAD_ALLOC;
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
|
||||
static bool SetFocusToPluginControl(HWND hwndPlugin)
|
||||
|
||||
@@ -111,6 +111,7 @@ public:
|
||||
MsgRouting WmMouseMove(UINT flags, int x, int y);
|
||||
MsgRouting WmNcMouseDown(WPARAM hitTest, int x, int y, int button);
|
||||
MsgRouting WmNcMouseUp(WPARAM hitTest, int x, int y, int button);
|
||||
MsgRouting WmNcMouseMove(WPARAM hitTest, int x, int y);
|
||||
MsgRouting WmGetIcon(WPARAM iconType, LRESULT& retVal);
|
||||
MsgRouting WmShowWindow(BOOL show, UINT status);
|
||||
MsgRouting WmWindowPosChanging(LPARAM windowPos);
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2000-2022 JetBrains s.r.o.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.jetbrains;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Custom window decoration allows merging of window content with native title bar,
|
||||
* which is usually done by treating title bar as part of client area, but with some
|
||||
* special behavior like dragging or maximizing on double click.
|
||||
* @implNote Behavior is platform-dependent, only macOS and Windows are supported.
|
||||
*/
|
||||
public interface CustomWindowDecoration {
|
||||
|
||||
/*CONST java.awt.Window.*_HIT_SPOT*/
|
||||
/*CONST java.awt.Window.*_BUTTON*/
|
||||
/*CONST java.awt.Window.MENU_BAR*/
|
||||
/*CONST java.awt.Window.DRAGGABLE_AREA*/
|
||||
|
||||
/**
|
||||
* Turn custom decoration on or off, {@link #setCustomDecorationTitleBarHeight(Window, int)}
|
||||
* must be called to configure title bar height.
|
||||
*/
|
||||
void setCustomDecorationEnabled(Window window, boolean enabled);
|
||||
/**
|
||||
* @see #setCustomDecorationEnabled(Window, boolean)
|
||||
*/
|
||||
boolean isCustomDecorationEnabled(Window window);
|
||||
|
||||
/**
|
||||
* Set list of hit test spots for a custom decoration.
|
||||
* Hit test spot is a special area inside custom-decorated title bar.
|
||||
* Each hit spot type has its own (probably platform-specific) behavior:
|
||||
* <ul>
|
||||
* <li>{@link #NO_HIT_SPOT} - default title bar area, can be dragged to move a window, maximizes on double-click</li>
|
||||
* <li>{@link #OTHER_HIT_SPOT} - generic hit spot, window cannot be moved with drag or maximized on double-click</li>
|
||||
* <li>{@link #MINIMIZE_BUTTON} - like {@link #OTHER_HIT_SPOT} but displays tooltip on Windows when hovered</li>
|
||||
* <li>{@link #MAXIMIZE_BUTTON} - like {@link #OTHER_HIT_SPOT} but displays tooltip / snap layout menu on Windows when hovered</li>
|
||||
* <li>{@link #CLOSE_BUTTON} - like {@link #OTHER_HIT_SPOT} but displays tooltip on Windows when hovered</li>
|
||||
* <li>{@link #MENU_BAR} - currently no different from {@link #OTHER_HIT_SPOT}</li>
|
||||
* <li>{@link #DRAGGABLE_AREA} - special type, moves window when dragged, but doesn't maximize on double-click</li>
|
||||
* </ul>
|
||||
* @param spots pairs of hit spot shapes with corresponding types.
|
||||
* @implNote Hit spots are tested in sequence, so in case of overlapping areas, first found wins.
|
||||
*/
|
||||
void setCustomDecorationHitTestSpots(Window window, List<Map.Entry<Shape, Integer>> spots);
|
||||
/**
|
||||
* @see #setCustomDecorationHitTestSpots(Window, List)
|
||||
*/
|
||||
List<Map.Entry<Shape, Integer>> getCustomDecorationHitTestSpots(Window window);
|
||||
|
||||
/**
|
||||
* Set height of custom window decoration, won't take effect until custom decoration
|
||||
* is enabled via {@link #setCustomDecorationEnabled(Window, boolean)}.
|
||||
*/
|
||||
void setCustomDecorationTitleBarHeight(Window window, int height);
|
||||
/**
|
||||
* @see #setCustomDecorationTitleBarHeight(Window, int)
|
||||
*/
|
||||
int getCustomDecorationTitleBarHeight(Window window);
|
||||
}
|
||||
@@ -6,9 +6,9 @@
|
||||
# 2. When only new API is added, or some existing API was @Deprecated - increment MINOR, reset PATCH to 0
|
||||
# 3. For major backwards incompatible API changes - increment MAJOR, reset MINOR and PATCH to 0
|
||||
|
||||
VERSION = 0.0.2
|
||||
VERSION = 0.0.3
|
||||
|
||||
# Hash is used to track changes to jetbrains.api, so you would not forget to update version when needed.
|
||||
# When you make any changes, "make jbr-api" will fail and ask you to update hash and version number here.
|
||||
|
||||
HASH = 814F29888E5EB6C23DF27B53636E9F94
|
||||
HASH = 414128B7903002F2EF6234BC2CFCE3
|
||||
|
||||
Reference in New Issue
Block a user