Skip to content

[GTK4] Cleanup GtkEventControllerMotion Enter/Leave events #2008

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

Merged
merged 1 commit into from
Apr 15, 2025

Conversation

ptziegler
Copy link
Contributor

@ptziegler ptziegler commented Apr 13, 2025

Support for mouse motion events was already implemented with b70cd16. However, following edge cases were missed:

  • Moving the cursor out of the shell and back in doesn't fire a " mouse enter" event.

Similarly to the way motion events are handled in GTK3, the current control needs to be cleared on a "leave" event. Otherwise the "enter" event is suppressed when the cursor is moved out of and back in a shell again.

  • Moving from one widget to another fires two "mouse exit" events.

One event is fired by "gtk4_motion_event()", the other by "leaveProc()". Only the former should be fired, as it contains the proper "x" and "y" coordinates.

Latter is fired because "getCursorControl()" always returns "null". This has been fixed by first calculating the GtkWindow from the GdkSurface and then selecting the widget at the mouse coordinates. The whole implementation has also been restructured so that the X11-based heuristic via the XQueryPointer is only used for GTK3 (because it would simply return early for GTK4 anyway).

  • The tooltip window isn't moved when hovering over different widget

This is because the tooltip is set for the shell, even though it should be set for the individual widgets. As a result, only the text is updated but the window remains where it was initially shown.

Closes #219

@ptziegler
Copy link
Contributor Author

You can use the following snippet for testing:

public class Snippet {

	public static void main (String [] args) {
		Display display = new Display ();
		Shell shell = new Shell(display);
		shell.setSize(200, 200);
		shell.setText("Mouse Enter/Exit");
		shell.setToolTipText("Shell");
		shell.setLayout(new GridLayout(2, true));
		shell.addMouseTrackListener(new MouseTrackAdapter() {
			@Override
			public void mouseEnter(MouseEvent e) {
				System.out.println("mouseEnter: %s, x=%d, y=%d".formatted("Shell", e.x, e.y));
			}

			@Override
			public void mouseExit(MouseEvent e) {
				System.out.println("mouseExit: %s, x=%d, y=%d".formatted("Shell", e.x, e.y));
			}
		});

		createButton(shell, "Button 1");
		createButton(shell, "Button 2");
		createButton(shell, "Button 3");
		createButton(shell, "Button 4");

		shell.open ();
		while (!shell.isDisposed ()) {
			if (!display.readAndDispatch ()) display.sleep ();
		}
		display.dispose ();
	}

	private static void createButton(Shell parent, String text) {
		GridData gd = new GridData();
		gd.horizontalIndent = 20;
		gd.verticalIndent = 20;
		gd.widthHint = 60;
		gd.heightHint = 60;

		Button b = new Button(parent, SWT.PUSH);
		b.setText(text);
		b.setToolTipText(text);
		b.setLayoutData(gd);
		b.addMouseTrackListener(new MouseTrackAdapter() {
			@Override
			public void mouseEnter(MouseEvent e) {
				System.out.println("mouseEnter: %s, x=%d, y=%d".formatted(text, e.x, e.y));
			}

			@Override
			public void mouseExit(MouseEvent e) {
				System.out.println("mouseExit: %s, x=%d, y=%d".formatted(text, e.x, e.y));
			}
		});
	}
}

Expectation:

When moving the mouse cursor from the shell to one of the buttons, exactly two events should be fired:

  • mouseExit (Shell)
  • mouseEnter (Button)

When moving the mouse cursor from one of the buttons back to the shell, exactly two events should be fired:

  • mouseExit (Button)
  • mouseEnter (Shell)

When moving the mouse cursor in and out of the shell, exactly two events should be fired:

  • mouseExit (Shell)
  • mouseEnter (Shell)

@ptziegler
Copy link
Contributor Author

The tooltip window isn't moved when hovering over different widget

Recording.webm

@ptziegler ptziegler added the gtk4 GTK4 issues label Apr 13, 2025
Copy link
Contributor

github-actions bot commented Apr 13, 2025

Test Results

   408 files   -   137     408 suites   - 137   19m 41s ⏱️ - 12m 32s
 4 334 tests  -    37   4 324 ✅  -    35  10 💤  -  2  0 ❌ ±0 
12 525 runs   - 4 104  12 432 ✅  - 4 091  93 💤  - 13  0 ❌ ±0 

Results for commit 74edbbd. ± Comparison against base commit 81f9bd1.

This pull request removes 37 tests.
AllGTKTests org.eclipse.swt.tests.gtk.Test_GtkConverter ‑ test_HeuristicASCII_dollarSign
AllGTKTests org.eclipse.swt.tests.gtk.Test_GtkConverter ‑ test_HeuristicASCII_emptyString
AllGTKTests org.eclipse.swt.tests.gtk.Test_GtkConverter ‑ test_HeuristicASCII_letterA
AllGTKTests org.eclipse.swt.tests.gtk.Test_GtkConverter ‑ test_HeuristicASCII_letters
AllGTKTests org.eclipse.swt.tests.gtk.Test_GtkConverter ‑ test_HeuristicUTF16LE_null
AllGTKTests org.eclipse.swt.tests.gtk.Test_GtkConverter ‑ test_HeuristicUTF16_AsciiLetters
AllGTKTests org.eclipse.swt.tests.gtk.Test_GtkConverter ‑ test_HeuristicUTF16_Asciiletter
AllGTKTests org.eclipse.swt.tests.gtk.Test_GtkConverter ‑ test_HeuristicUTF16_LotsOfLetters
AllGTKTests org.eclipse.swt.tests.gtk.Test_GtkConverter ‑ test_HeuristicUTF16_letter
AllGTKTests org.eclipse.swt.tests.gtk.Test_GtkConverter ‑ test_HeuristicUTF16_letters
…

♻️ This comment has been updated with latest results.

@ptziegler ptziegler force-pushed the issue219 branch 2 times, most recently from c8e7f2a to e64db67 Compare April 13, 2025 19:22
Support for mouse motion events was already implemented with
b70cd16. However, following
edge cases were missed:

- Moving the cursor out of the shell and back in doesn't fire a "mouse
enter" event.

Similarly to the way motion events are handled in GTK3, the current
control needs to be cleared on a "leave" event. Otherwise the "enter"
event is suppressed when the cursor is moved out of and back in a shell
again.

- Moving from one widget to another fires two "mouse exit" events.

One event is fired by "gtk4_motion_event()", the other by "leaveProc()".
Only the former should be fired, as it contains the proper "x" and "y"
coordinates.

Latter is fired because "getCursorControl()" always returns "null". This
has been fixed by first calculating the GtkWindow from the GdkSurface
and then selecting the widget at the mouse coordinates. The whole
implementation has also been restructured so that the X11-based
heuristic via the XQueryPointer is only used for GTK3 (because it would
simply return early for GTK4 anyway).

- The tooltip window isn't moved when hovering over different widgets

This is because the tooltip is set for the shell, even though it should
be set for the individual widgets. As a result, only the text is updated
but the window remains where it was initially shown.

Closes eclipse-platform#219
@akurtakov
Copy link
Member

Very nice fix. Failure is due to #2014 . Merging.

@akurtakov akurtakov merged commit f734dc6 into eclipse-platform:master Apr 15, 2025
14 of 17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
gtk4 GTK4 issues
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[GTK4] GtkEventControllerMotion Enter/Leave events are not handled
2 participants