Skip to content

Commit f03d65d

Browse files
committed
[Gtk4] Hook dropdown arrow clicked signal in ToolItem
Make sure that coordinates are translated as best as possible so menus appear in correct places.
1 parent 73d6346 commit f03d65d

2 files changed

Lines changed: 66 additions & 3 deletions

File tree

bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Menu.java

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,35 @@ void _setVisible (boolean visible) {
308308
if (ableToSetLocation()) {
309309
if (GTK.GTK4) {
310310
GdkRectangle popoverPosition = new GdkRectangle();
311-
popoverPosition.x = x;
312-
popoverPosition.y = y;
311+
/*
312+
* gtk_popover_set_pointing_to expects coordinates in the coordinate
313+
* space of the popover's current parent widget.
314+
*
315+
* When the popover is parented to parent.handle (Shell's GtkFixed),
316+
* setLocation() coordinates need to be translated from the shell
317+
* window's coordinate space (shellHandle / GtkWindow) into the
318+
* GtkFixed's coordinate space. On GTK4 with a header bar, the
319+
* GtkWindow origin is above the client area by the title bar height.
320+
*
321+
* Menus may also be reparented to a control (for example by
322+
* Control.showMenu()), in which case setLocation() can already be
323+
* relative to that control - do not apply the shell to
324+
* parent.handle translation.
325+
*/
326+
long currentParent = GTK.gtk_widget_get_parent(handle);
327+
if (currentParent == parent.handle) {
328+
double[] relX = new double[1], relY = new double[1];
329+
if (GTK4.gtk_widget_translate_coordinates(parent.getShell().topHandle(), parent.handle, x, y, relX, relY)) {
330+
popoverPosition.x = (int) relX[0];
331+
popoverPosition.y = (int) relY[0];
332+
} else {
333+
popoverPosition.x = x;
334+
popoverPosition.y = y;
335+
}
336+
} else {
337+
popoverPosition.x = x;
338+
popoverPosition.y = y;
339+
}
313340
popoverPosition.width = popoverPosition.height = 1;
314341
GTK.gtk_popover_set_pointing_to(handle, popoverPosition);
315342

bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ToolItem.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,42 @@ long gtk_mnemonic_activate (long widget, long arg1) {
868868
return parent.gtk_mnemonic_activate (widget, arg1);
869869
}
870870

871+
@Override
872+
int gtk_gesture_press_event(long gesture, int n_press, double x, double y, long event) {
873+
/*
874+
* GTK4: For DROP_DOWN items, the arrow portion is a GtkMenuButton
875+
* (arrowHandle) that is separate from the main button. Attach a gesture
876+
* controller to arrowHandle and detect it here in order to send the
877+
* SWT.ARROW selection detail to the listener (e.g. to open a drop-down menu).
878+
*/
879+
if ((style & SWT.DROP_DOWN) != 0 && arrowHandle != 0
880+
&& GTK.gtk_event_controller_get_widget(gesture) == arrowHandle
881+
&& n_press == 1
882+
&& GTK.gtk_gesture_single_get_current_button(gesture) == 1) {
883+
Event e = new Event();
884+
e.detail = SWT.ARROW;
885+
GtkAllocation allocation = new GtkAllocation();
886+
GTK.gtk_widget_get_allocation(arrowHandle, allocation);
887+
/*
888+
* On GTK4 gtk_widget_get_allocation returns parent-widget-relative
889+
* coordinates, but the SWT event x/y must be in ToolBar-relative
890+
* coordinates so that callers can use toolBar.toDisplay(event.x, event.y).
891+
* Translate the arrow button's origin into the ToolBar's coordinate space.
892+
* If translation fails, fall back to the parent-relative allocation.
893+
*/
894+
double[] destX = new double[1];
895+
double[] destY = new double[1];
896+
boolean translated = GTK4.gtk_widget_translate_coordinates(arrowHandle, parent.handle, 0, 0, destX, destY);
897+
e.x = translated ? (int) destX[0] : allocation.x;
898+
if ((parent.style & SWT.MIRRORED) != 0) e.x = parent.getClientWidth() - allocation.width - e.x;
899+
System.out.println(e.x);
900+
e.y = translated ? (int) destY[0] + allocation.height : allocation.y + allocation.height;
901+
sendSelectionEvent(SWT.Selection, e, false);
902+
return GTK4.GTK_EVENT_SEQUENCE_CLAIMED;
903+
}
904+
return GTK4.GTK_EVENT_SEQUENCE_NONE;
905+
}
906+
871907
@Override
872908
void hookEvents () {
873909
super.hookEvents ();
@@ -1664,4 +1700,4 @@ private void recreateMenuProxy() {
16641700
}
16651701
}
16661702
}
1667-
}
1703+
}

0 commit comments

Comments
 (0)