Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding events to native Windows libraries #960

Open
java-pik opened this issue Jan 20, 2025 · 2 comments
Open

Adding events to native Windows libraries #960

java-pik opened this issue Jan 20, 2025 · 2 comments

Comments

@java-pik
Copy link

Hi,

Currently with native windows it doesn't seem possible to know when a user resizes or moves a window.
Indeed, no event seems to be sent to the JVM allowing to know if the user has released the mouse.
Since my application runs on Windows, one solution I found was to modify FlatWndPoc.cpp, to add a sendMessageToClientArea( hwnd, WM_MOUSEMOVE, lParam ), when WM_EXITSIZEMOVE occurs.

Can it be possible to incorporate this type of modification into the library, or do you have any tips can be help me with my problem?
please

Context:

My goal is to magnet windows on my application.
On Mac and some Linux distributions, this is already handled natively.

On Windows, there doesn't seem to be a native solution, and I've found that native window management doesn't allow me to prevent the system from moving or resizing a window.
To get around this problem, I want to magnet windows after the user has finished resizing or moving them.

@DevCharly
Copy link
Collaborator

Currently with native windows it doesn't seem possible to know when a user resizes or moves a window.

Use java.awt.event.ComponentListener, which works fine on Windows with FlatLaf window decorations and also on all other platforms:

package test;

import com.formdev.flatlaf.FlatDarkLaf;

import javax.swing.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

public class WindowsListenerTest {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            FlatDarkLaf.setup();

            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            frame.setSize(500, 500);

            frame.addComponentListener( new ComponentAdapter() {
                @Override
                public void componentResized(ComponentEvent e) {
                    System.out.println( e );
                }
                @Override
                public void componentMoved(ComponentEvent e) {
                    System.out.println( e );
                }
            } );

            frame.setVisible(true);
        });
    }
}

I want to magnet windows after the user has finished resizing or moving them.

You could use a javax.swing.Timer (e.g. 500ms) to achieve this:

  1. create and start a timer when first resized/moved event occurs
  2. on subsequent resized/moved events restart that timer
  3. if timer fires action, do "magnet window" and remove timer

My goal is to magnet windows on my application.
On Mac and some Linux distributions, this is already handled natively.

How does this work?
In Java/Swing?

@java-pik
Copy link
Author

Hey

Thanks for your answer.

I made a few mistakes in my issue, in fact the event I'm looking for is when the user releases the mouse after a resize or move.
I indicated WM_MOUSEMOVE in the event, when it should be WM_LBUTTONUP.

Yes, I'm trying to achieve a swing implementation, while keeping the native window titles and borders.

On MacOS when you resize a window to stick it onto another, when the two frame touch, the OS no longer interpret mouse movements events through several pixels.
This makes it easier for the user to stick 2 frame.
https://support.apple.com/my-mm/guide/mac-help/mchlp2469/mac#mchl7cdb2590

I can't same behaviour like macos, beucause I don't know how to block the movement or resizing of a frame, with native Windows borders.

I'd already tried your solution using a timer that modify the frame if no more events were received.
The problem is that if the user simply stops moving, the frame going to magnet, but if he moves the mouse again, the frame teleports to the original position. That's not very user-friendly.

I also tried moving the user's mouse, but again, it is not user friendly.

That's why, I try to display visual indicator to prevent the stick event, and when use releases it the two frame stick together.
So here's a linux example using FlatWindowResizer.WindowResizer endResizing

magnet_exemple.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants