Added: #289 Support for Aero Snap on Windows

This commit is contained in:
Jindra Petřík
2025-05-24 08:22:54 +02:00
parent 4986d19a76
commit e903669e98
34 changed files with 338 additions and 126 deletions

View File

@@ -18,8 +18,16 @@ package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.gui.jna.platform.win32.BaseTSD;
import com.jpexs.decompiler.flash.gui.jna.platform.win32.Dwmapi;
import com.jpexs.decompiler.flash.gui.jna.platform.win32.User32;
import com.jpexs.decompiler.flash.gui.jna.platform.win32.WinDef;
import com.jpexs.decompiler.flash.gui.jna.platform.win32.WinUser;
import com.jpexs.decompiler.flash.treeitems.OpenableList;
import com.jpexs.helpers.Helper;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.win32.StdCallLibrary;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
@@ -28,6 +36,7 @@ import java.awt.Frame;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
@@ -36,24 +45,16 @@ import java.awt.event.ComponentEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowStateListener;
import java.awt.geom.AffineTransform;
import java.io.File;
import java.util.List;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JTree;
import javax.swing.plaf.RootPaneUI;
import org.pushingpixels.flamingo.api.ribbon.JRibbon;
import org.pushingpixels.flamingo.internal.ui.ribbon.appmenu.JRibbonApplicationMenuButton;
import org.pushingpixels.substance.api.DecorationAreaType;
import org.pushingpixels.substance.api.SubstanceColorScheme;
import org.pushingpixels.substance.api.SubstanceLookAndFeel;
import org.pushingpixels.substance.flamingo.ribbon.ui.SubstanceRibbonRootPaneUI;
import org.pushingpixels.substance.internal.utils.SubstanceCoreUtilities;
import org.pushingpixels.substance.internal.utils.SubstanceTitleButton;
import org.pushingpixels.substance.internal.utils.icon.SubstanceIconFactory;
import org.pushingpixels.substance.internal.utils.icon.TransitionAwareIcon;
import org.pushingpixels.substance.internal.utils.SubstanceSizeUtils;
/**
* @author JPEXS
@@ -66,7 +67,6 @@ public final class MainFrameRibbon extends AppRibbonFrame {
public MainFrameRibbon() {
super();
Container cnt = getContentPane();
cnt.setLayout(new BorderLayout());
@@ -181,70 +181,175 @@ public final class MainFrameRibbon extends AppRibbonFrame {
}
});
View.centerScreenMain(this);
/*addWindowListener(new WindowAdapter() {
View.centerScreenMain(this);
enableAeroSnap();
}
private void enableAeroSnap() {
if (!Platform.isWindows()) {
return;
}
Point posOnScreen = new Point();
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
update();
}
@Override
public void componentMoved(ComponentEvent e) {
update();
}
private void update() {
if (MainFrameRibbon.this.isVisible()) {
posOnScreen.x = MainFrameRibbon.this.getLocationOnScreen().x;
posOnScreen.y = MainFrameRibbon.this.getLocationOnScreen().y;
}
}
});
addWindowListener(new WindowAdapter() {
private BaseTSD.LONG_PTR oldWndProc;
private StdCallLibrary.StdCallCallback newProc;
private Rectangle activeRect = new Rectangle();
private AffineTransform trans;
@Override
public void windowOpened(WindowEvent e) {
RootPaneUI ui = getRootPane().getUI();
if (ui instanceof SubstanceRibbonRootPaneUI) {
SubstanceRibbonRootPaneUI sui = (SubstanceRibbonRootPaneUI) ui;
JComponent titlePane = sui.getTitlePane();
final String EXTRA_COMPONENT_KIND = "substancelaf.internal.titlePane.extraComponentKind";
Object trailing = null;
int i = 0;
int cnt = titlePane.getComponentCount();
for (; i < cnt; i++) {
Component c = titlePane.getComponent(i);
if (c instanceof JComponent) {
JComponent jc = (JComponent) c;
Object o = jc.getClientProperty(EXTRA_COMPONENT_KIND);
if ("TRAILING".equals("" + o)) {
trailing = o;
break;
}
}
}
if (trailing != null) {
JButton button = new SubstanceTitleButton();
button.setFocusPainted(false);
button.setFocusable(false);
button.setOpaque(true);
button.putClientProperty(EXTRA_COMPONENT_KIND, trailing);
button.setText(null);
button.setBorder(null);
Icon minIcon = new TransitionAwareIcon(button,
new TransitionAwareIcon.Delegate() {
@Override
public Icon getColorSchemeIcon(
SubstanceColorScheme scheme) {
return SubstanceIconFactory
.getTitlePaneIcon(
SubstanceIconFactory.IconKind.MINIMIZE,
scheme,
SubstanceCoreUtilities
.getSkin(rootPane)
.getBackgroundColorScheme(
DecorationAreaType.PRIMARY_TITLE_PANE));
}
}, "substance.titlePane.minIcon");
button.setIcon(minIcon);
button.setToolTipText("Zkouska");
button.putClientProperty(SubstanceLookAndFeel.FLAT_PROPERTY,
Boolean.TRUE);
titlePane.remove(i);
titlePane.add(button, i);
titlePane.revalidate();
}
Window window = MainFrameRibbon.this;
trans = View.getWindowDevice(window).getDefaultConfiguration().getDefaultTransform();
if (trans == null) {
trans = new AffineTransform();
}
ComponentAdapter ad = new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
updateRect();
}
@Override
public void componentShown(ComponentEvent e) {
updateRect();
}
private void updateRect() {
int appButtonSize = (int) Math.round(trans.getScaleX() * Integer.getInteger("peacock.appButtonSize", 24));
int titleIconsWidth
= 3 + SubstanceSizeUtils.getTitlePaneIconSize() //close
+ 10 + SubstanceSizeUtils.getTitlePaneIconSize() //maximize / restore
+ 2 + SubstanceSizeUtils.getTitlePaneIconSize() //minimize
+ 2 + SubstanceSizeUtils.getTitlePaneIconSize(); //always on top
Insets insets = titlePane.getInsets();
if (insets == null) {
insets = new Insets(0, 0, 0, 0);
}
activeRect = new Rectangle(
insets.left + appButtonSize,
4,
titlePane.getWidth() - titleIconsWidth - insets.right - (insets.left + appButtonSize),
titlePane.getHeight()
);
}
};
titlePane.addComponentListener(ad);
ad.componentShown(null);
WinDef.HWND hwnd = new WinDef.HWND(Native.getComponentPointer(window));
oldWndProc = User32.INSTANCE.GetWindowLongPtr(hwnd, WinUser.GWL_WNDPROC);
newProc = new StdCallLibrary.StdCallCallback() {
public WinDef.LRESULT callback(WinDef.HWND hWnd, int uMsg, WinDef.WPARAM wParam, WinDef.LPARAM lParam) {
if (!User32.INSTANCE.IsWindow(hwnd)) {
return new WinDef.LRESULT(0);
}
if (uMsg == WinUser.WM_NCCALCSIZE) {
return new WinDef.LRESULT(0);
}
if (uMsg == WinUser.WM_NCHITTEST) {
int y = (short) ((lParam.longValue() >> 16) & 0xFFFF);
int x = (short) (lParam.longValue() & 0xFFFF);
int BORDER_WIDTH = 4;
WinDef.RECT winRect = new WinDef.RECT();
User32.INSTANCE.GetWindowRect(hWnd, winRect);
boolean left = x >= winRect.left - BORDER_WIDTH && x < winRect.left + BORDER_WIDTH;
boolean right = x < winRect.right + BORDER_WIDTH && x >= winRect.right - BORDER_WIDTH;
boolean top = y >= winRect.top - BORDER_WIDTH && y < winRect.top + BORDER_WIDTH;
boolean bottom = y < winRect.bottom + BORDER_WIDTH && y >= winRect.bottom - BORDER_WIDTH;
if (left && top) {
return new WinDef.LRESULT(WinUser.HTTOPLEFT);
}
if (right && top) {
return new WinDef.LRESULT(WinUser.HTTOPRIGHT);
}
if (left && bottom) {
return new WinDef.LRESULT(WinUser.HTBOTTOMLEFT);
}
if (right && bottom) {
return new WinDef.LRESULT(WinUser.HTBOTTOMRIGHT);
}
if (top) {
return new WinDef.LRESULT(WinUser.HTTOP);
}
if (bottom) {
return new WinDef.LRESULT(WinUser.HTBOTTOM);
}
if (left) {
return new WinDef.LRESULT(WinUser.HTLEFT);
}
if (right) {
return new WinDef.LRESULT(WinUser.HTRIGHT);
}
Point p = new Point(x, y);
p.x = (int) Math.round(p.x / trans.getScaleX());
p.y = (int) Math.round(p.y / trans.getScaleY());
p.x -= posOnScreen.x;
p.y -= posOnScreen.y;
if (activeRect.contains(p)) {
return new WinDef.LRESULT(WinUser.HTCAPTION);
}
//return new WinDef.LRESULT(WinUser.HTCLIENT);
}
return User32.INSTANCE.CallWindowProc(oldWndProc.toPointer(), hWnd, uMsg, wParam, lParam);
}
};
User32.INSTANCE.SetWindowLongPtr(hwnd, WinUser.GWL_WNDPROC, newProc);
int style = User32.INSTANCE.GetWindowLong(hwnd, WinUser.GWL_STYLE);
style |= WinUser.WS_THICKFRAME;
User32.INSTANCE.SetWindowLong(hwnd, WinUser.GWL_STYLE, style);
User32.INSTANCE.SetWindowPos(hwnd, null, 0, 0, 0, 0,
WinUser.SWP_NOMOVE | WinUser.SWP_NOSIZE | WinUser.SWP_NOZORDER | WinUser.SWP_FRAMECHANGED);
Dwmapi.MARGINS margins = new Dwmapi.MARGINS();
margins.cxLeftWidth = 0;
margins.cxRightWidth = 0;
margins.cyTopHeight = 0;
margins.cyBottomHeight = 0;
Dwmapi.INSTANCE.DwmExtendFrameIntoClientArea(hwnd, margins);
}
}
});*/
}
}
});
}
@Override
public void setExtendedState(int state) {
if ((state & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH) {