Skip to content

Commit

Permalink
Merge branch 'JFormDesigner:main' into classx
Browse files Browse the repository at this point in the history
  • Loading branch information
dar-dev authored Nov 18, 2024
2 parents 27969e0 + c37712b commit 27f6d4f
Show file tree
Hide file tree
Showing 14 changed files with 263 additions and 20 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ FlatLaf Change Log

- HTML: Fixed wrong rendering if HTML text contains `<style>` tag with
attributes (e.g. `<style type='text/css'>`). (issue #905; regression in 3.5.1)
- FlatLaf window decorations:
- Windows: Fixed possible deadlock with TabbedPane in window title area in
"full window content" mode. (issue #909)
- Windows: Fixed wrong layout in maximized frame after changing screen scale
factor. (issue #904)
- Linux: Fixed continuous cursor toggling between resize and standard cursor
when resizing window. (issue #907)


## 3.5.2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2306,8 +2306,23 @@ private int rectsTotalHeight() {
/** @since 3.4 */
@Override
public Boolean isTitleBarCaptionAt( int x, int y ) {
if( tabForCoordinate( tabPane, x, y ) >= 0 )
return false;
// Note: not using tabForCoordinate() here because this may validate layout and cause dead lock

if( moreTabsButton != null ) {
// convert x,y from JTabbedPane coordinate space to ScrollableTabPanel coordinate space
Point viewPosition = tabViewport.getViewPosition();
x = x - tabViewport.getX() + viewPosition.x;
y = y - tabViewport.getY() + viewPosition.y;

// check whether point is within viewport
if( !tabViewport.getViewRect().contains( x, y ) )
return null; // check children
}

for( int i = 0; i < rects.length; i++ ) {
if( rects[i].contains( x, y ) )
return false;
}

return null; // check children
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1058,10 +1058,11 @@ private Rectangle boundsInWindow( JComponent c ) {
* <p>
* Note:
* <ul>
* <li>This method is invoked often when mouse is moved over title bar
* <li>This method is invoked often when mouse is moved over window title bar area
* and should therefore return quickly.
* <li>This method is invoked on 'AWT-Windows' thread (not 'AWT-EventQueue' thread)
* while processing Windows messages.
* It <b>must not</b> change any component property or layout because this could cause a dead lock.
* </ul>
*/
private boolean captionHitTest( Point pt ) {
Expand Down Expand Up @@ -1578,6 +1579,15 @@ public interface TitleBarCaptionHitTest {
* Useful for components that do not use mouse input on whole component bounds.
* E.g. a tabbed pane with a few tabs has some empty space beside the tabs
* that can be used to move the window.
* <p>
* Note:
* <ul>
* <li>This method is invoked often when mouse is moved over window title bar area
* and should therefore return quickly.
* <li>This method is invoked on 'AWT-Windows' thread (not 'AWT-EventQueue' thread)
* while processing Windows messages.
* It <b>must not</b> change any component property or layout because this could cause a dead lock.
* </ul>
*
* @return {@code true} if the component is not interested in mouse input at the given location
* {@code false} if the component wants process mouse input at the given location
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import javax.swing.JComponent;
import javax.swing.JInternalFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
Expand Down Expand Up @@ -191,7 +192,7 @@ boolean isDialog() {
protected abstract Dimension getWindowMinimumSize();
protected abstract Dimension getWindowMaximumSize();

protected void beginResizing( int direction ) {}
protected void beginResizing( int resizeDir ) {}
protected void endResizing() {}

//---- interface PropertyChangeListener ----
Expand Down Expand Up @@ -234,17 +235,46 @@ public static class WindowResizer
{
protected Window window;

private final JComponent centerComp;
private final boolean limitResizeToScreenBounds;

public WindowResizer( JRootPane rootPane ) {
super( rootPane );

// Transparent "center" component that is made visible only while resizing window.
// It uses same cursor as the area where resize dragging started.
// This ensures that the cursor shape stays stable while dragging mouse
// into the window to make window smaller. Otherwise it would toggling between
// resize and standard cursor because the component layout is not updated
// fast enough and the mouse cursor is always updated from the component
// at the mouse location.
centerComp = new JPanel();
centerComp.setOpaque( false );
centerComp.setVisible( false );
Container cont = rootPane.getLayeredPane();
cont.add( centerComp, WINDOW_RESIZER_LAYER, 4 );

// On Linux, limit window resizing to screen bounds because otherwise
// there would be a strange effect when the mouse is moved over a sidebar
// while resizing and the opposite window side is also resized.
limitResizeToScreenBounds = SystemInfo.isLinux;
}

@Override
public void uninstall() {
Container cont = topDragComp.getParent();
cont.remove( centerComp );

super.uninstall();
}

@Override
public void doLayout() {
super.doLayout();

centerComp.setBounds( 0, 0, resizeComp.getWidth(), resizeComp.getHeight() );
}

@Override
protected void addNotify() {
Container parent = resizeComp.getParent();
Expand Down Expand Up @@ -346,6 +376,18 @@ boolean isDialog() {
public void windowStateChanged( WindowEvent e ) {
updateVisibility();
}

@Override
protected void beginResizing( int resizeDir ) {
centerComp.setCursor( getPredefinedCursor( resizeDir ) );
centerComp.setVisible( true );
}

@Override
protected void endResizing() {
centerComp.setVisible( false );
centerComp.setCursor( null );
}
}

//---- class InternalFrameResizer -----------------------------------------
Expand Down Expand Up @@ -427,7 +469,18 @@ protected Dimension getWindowMaximumSize() {
}

@Override
protected void beginResizing( int direction ) {
protected void beginResizing( int resizeDir ) {
int direction = 0;
switch( resizeDir ) {
case N_RESIZE_CURSOR: direction = NORTH; break;
case S_RESIZE_CURSOR: direction = SOUTH; break;
case W_RESIZE_CURSOR: direction = WEST; break;
case E_RESIZE_CURSOR: direction = EAST; break;
case NW_RESIZE_CURSOR: direction = NORTH_WEST; break;
case NE_RESIZE_CURSOR: direction = NORTH_EAST; break;
case SW_RESIZE_CURSOR: direction = SOUTH_WEST; break;
case SE_RESIZE_CURSOR: direction = SOUTH_EAST; break;
}
desktopManager.get().beginResizingFrame( getFrame(), direction );
}

Expand Down Expand Up @@ -535,18 +588,7 @@ public void mousePressed( MouseEvent e ) {
dragRightOffset = windowBounds.x + windowBounds.width - xOnScreen;
dragBottomOffset = windowBounds.y + windowBounds.height - yOnScreen;

int direction = 0;
switch( resizeDir ) {
case N_RESIZE_CURSOR: direction = NORTH; break;
case S_RESIZE_CURSOR: direction = SOUTH; break;
case W_RESIZE_CURSOR: direction = WEST; break;
case E_RESIZE_CURSOR: direction = EAST; break;
case NW_RESIZE_CURSOR: direction = NORTH_WEST; break;
case NE_RESIZE_CURSOR: direction = NORTH_EAST; break;
case SW_RESIZE_CURSOR: direction = SOUTH_WEST; break;
case SE_RESIZE_CURSOR: direction = SOUTH_EAST; break;
}
beginResizing( direction );
beginResizing( resizeDir );
}

@Override
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,8 @@ private class WndProc
WM_ENTERSIZEMOVE = 0x0231,
WM_EXITSIZEMOVE = 0x0232,

WM_DPICHANGED = 0x02E0,

WM_DWMCOLORIZATIONCOLORCHANGED = 0x0320;

// WM_SIZE wParam
Expand Down Expand Up @@ -501,6 +503,22 @@ public LRESULT callback( HWND hwnd, int uMsg, WPARAM wParam, LPARAM lParam ) {
isMoving = true;
break;

case WM_DPICHANGED:
LRESULT lResult = User32Ex.INSTANCE.CallWindowProc( defaultWndProc, hwnd, uMsg, wParam, lParam );

// if window is maximized and DPI/scaling changed, then Windows
// does not send a subsequent WM_SIZE message and Java window bounds,
// which depend on scale factor, are not updated
boolean isMaximized = User32Ex.INSTANCE.IsZoomed( hwnd );
if( isMaximized ) {
MyRECT r = new MyRECT( new Pointer( lParam.longValue() ) );
int width = r.right - r.left;
int height = r.bottom - r.top;
User32Ex.INSTANCE.CallWindowProc( defaultWndProc, hwnd, WM_SIZE, new WPARAM( SIZE_MAXIMIZED ), MAKELPARAM( width, height ) );
}

return lResult;

case WM_ERASEBKGND:
// do not erase background while the user is moving the window,
// otherwise there may be rendering artifacts on HiDPI screens with Java 9+
Expand Down Expand Up @@ -818,6 +836,13 @@ private long MAKELONG( int low, int high ) {
return (low & 0xffff) | ((high & 0xffff) << 16);
}

/**
* Same implementation as MAKELPARAM(l, h) macro in winuser.h.
*/
private LPARAM MAKELPARAM( int low, int high ) {
return new LPARAM( MAKELONG( low, high ) );
}

/**
* Same implementation as RGB(r,g,b) macro in wingdi.h.
*/
Expand Down Expand Up @@ -937,6 +962,23 @@ public NCCALCSIZE_PARAMS( Pointer pointer ) {
}
}

//---- class MyRECT -------------------------------------------------------

@FieldOrder( { "left", "top", "right", "bottom" } )
public static class MyRECT
extends Structure
{
public int left;
public int top;
public int right;
public int bottom;

public MyRECT( Pointer pointer ) {
super( pointer );
read();
}
}

//---- class MENUITEMINFO -------------------------------------------------

@FieldOrder( { "cbSize", "fMask", "fType", "fState", "wID", "hSubMenu",
Expand Down
29 changes: 29 additions & 0 deletions flatlaf-natives/flatlaf-natives-windows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,32 @@ The DLLs were built on a GitHub server with the help of GitHub Actions. See:
[Native Libraries](https://github.com/JFormDesigner/FlatLaf/actions/workflows/natives.yml)
workflow. Then the produced Artifacts ZIP was downloaded, signed DLLs with
FormDev Software code signing certificate and committed the DLLs to Git.


## Development

To build the library on Windows using Gradle, (parts of)
[Visual Studio Community
2022](https://visualstudio.microsoft.com/downloads/)
needs to be installed. After downloading and running `VisualStudioSetup.exe` the
**Visual Studio Installer** is installed and started. Once running, it shows the
**Workloads** tab that allows you to install additional packages. Either choose
**Desktop development with C++**, or to save some disk space switch to the
**Single Components** tab and choose following components (newest versions):

- MSVC v143 - VS 2022 C++ x64/x86 Buildtools
- MSVC v143 - VS 2022 C++ ARM64/ARM64EC Buildtools
- Windows 11 SDK

Note that the Visual Studio Installer shows many similar named components for
MSVC. Make sure to choose exactly those components listed above.

Using
[Build Tools for Visual Studio 2022](https://visualstudio.microsoft.com/downloads/#remote-tools-for-visual-studio-2022)
(installs only compiler and SDKs) instead of
[Visual Studio Community
2022](https://visualstudio.microsoft.com/downloads/)
does not work with Gradle.

[Visual Studio Code](https://code.visualstudio.com/) with **C/C++** extension
can be used for C++ code editing.
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,23 @@ LRESULT CALLBACK FlatWndProc::WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, L
isMoving = true;
break;

case WM_DPICHANGED: {
LRESULT lResult = ::CallWindowProc( defaultWndProc, hwnd, uMsg, wParam, lParam );

// if window is maximized and DPI/scaling changed, then Windows
// does not send a subsequent WM_SIZE message and Java window bounds,
// which depend on scale factor, are not updated
bool isMaximized = ::IsZoomed( hwnd );
if( isMaximized ) {
RECT* r = reinterpret_cast<RECT*>( lParam );
int width = r->right - r->left;
int height = r->bottom - r->top;
::CallWindowProc( defaultWndProc, hwnd, WM_SIZE, SIZE_MAXIMIZED, MAKELPARAM( width, height ) );
}

return lResult;
}

case WM_ERASEBKGND:
// do not erase background while the user is moving the window,
// otherwise there may be rendering artifacts on HiDPI screens with Java 9+
Expand Down
Loading

0 comments on commit 27f6d4f

Please sign in to comment.