diff options
author | Eric Williams | 2018-01-23 20:47:56 +0000 |
---|---|---|
committer | Eric Williams | 2018-01-26 20:07:46 +0000 |
commit | 931aef681a2316e9fe2a414072464b0126f40ff8 (patch) | |
tree | 7fafa2114f88e840cd9c68cca4c597cca48eeee4 | |
parent | be67e7a453048309b3d338b0f6f24c60f69e6f1a (diff) | |
download | eclipse.platform.swt-931aef681a2316e9fe2a414072464b0126f40ff8.tar.gz eclipse.platform.swt-931aef681a2316e9fe2a414072464b0126f40ff8.tar.xz eclipse.platform.swt-931aef681a2316e9fe2a414072464b0126f40ff8.zip |
Bug 530059: [Wayland] Show In menu appears in the wrong place
Events used to spawn menus can contain inaccurate window information on
Wayland. If we are running on Wayland, set the event window to be that
of the mouse pointer location.
Tested on GTK3.22 using the Wayland backend. X11 is unaffected by this
fix. No AllNonBrowser JUnit tests fail.
Change-Id: I6410694a88faacc672144d9f57e6c61032ea33cf
Signed-off-by: Eric Williams <ericwill@redhat.com>
6 files changed, 143 insertions, 0 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c index 21535dfb98..7d440c0a8f 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c @@ -5021,6 +5021,26 @@ fail: } #endif +#ifndef NO__1gdk_1event_1get_1event_1type +JNIEXPORT jint JNICALL OS_NATIVE(_1gdk_1event_1get_1event_1type) + (JNIEnv *env, jclass that, jintLong arg0) +{ + jint rc = 0; + OS_NATIVE_ENTER(env, that, _1gdk_1event_1get_1event_1type_FUNC); +/* + rc = (jint)gdk_event_get_event_type((GdkEvent *)arg0); +*/ + { + OS_LOAD_FUNCTION(fp, gdk_event_get_event_type) + if (fp) { + rc = (jint)((jint (CALLING_CONVENTION*)(GdkEvent *))fp)((GdkEvent *)arg0); + } + } + OS_NATIVE_EXIT(env, that, _1gdk_1event_1get_1event_1type_FUNC); + return rc; +} +#endif + #ifndef NO__1gdk_1event_1get_1scroll_1deltas JNIEXPORT jboolean JNICALL OS_NATIVE(_1gdk_1event_1get_1scroll_1deltas) (JNIEnv *env, jclass that, jintLong arg0, jdoubleArray arg1, jdoubleArray arg2) @@ -6269,6 +6289,26 @@ JNIEXPORT jint JNICALL OS_NATIVE(_1gdk_1screen_1width_1mm) } #endif +#ifndef NO__1gdk_1seat_1get_1pointer +JNIEXPORT jintLong JNICALL OS_NATIVE(_1gdk_1seat_1get_1pointer) + (JNIEnv *env, jclass that, jintLong arg0) +{ + jintLong rc = 0; + OS_NATIVE_ENTER(env, that, _1gdk_1seat_1get_1pointer_FUNC); +/* + rc = (jintLong)gdk_seat_get_pointer(arg0); +*/ + { + OS_LOAD_FUNCTION(fp, gdk_seat_get_pointer) + if (fp) { + rc = (jintLong)((jintLong (CALLING_CONVENTION*)(jintLong))fp)(arg0); + } + } + OS_NATIVE_EXIT(env, that, _1gdk_1seat_1get_1pointer_FUNC); + return rc; +} +#endif + #ifndef NO__1gdk_1seat_1grab JNIEXPORT jint JNICALL OS_NATIVE(_1gdk_1seat_1grab) (JNIEnv *env, jclass that, jintLong arg0, jintLong arg1, jint arg2, jboolean arg3, jintLong arg4, jintLong arg5, jintLong arg6, jintLong arg7) @@ -19405,6 +19445,30 @@ fail: } #endif +#if (!defined(NO_memmove__ILorg_eclipse_swt_internal_gtk_GdkEventKey_2I) && !defined(JNI64)) || (!defined(NO_memmove__JLorg_eclipse_swt_internal_gtk_GdkEventKey_2J) && defined(JNI64)) +#ifndef JNI64 +JNIEXPORT void JNICALL OS_NATIVE(memmove__ILorg_eclipse_swt_internal_gtk_GdkEventKey_2I)(JNIEnv *env, jclass that, jintLong arg0, jobject arg1, jintLong arg2) +#else +JNIEXPORT void JNICALL OS_NATIVE(memmove__JLorg_eclipse_swt_internal_gtk_GdkEventKey_2J)(JNIEnv *env, jclass that, jintLong arg0, jobject arg1, jintLong arg2) +#endif +{ + GdkEventKey _arg1, *lparg1=NULL; +#ifndef JNI64 + OS_NATIVE_ENTER(env, that, memmove__ILorg_eclipse_swt_internal_gtk_GdkEventKey_2I_FUNC); +#else + OS_NATIVE_ENTER(env, that, memmove__JLorg_eclipse_swt_internal_gtk_GdkEventKey_2J_FUNC); +#endif + if (arg1) if ((lparg1 = getGdkEventKeyFields(env, arg1, &_arg1)) == NULL) goto fail; + memmove((void *)arg0, (const void *)lparg1, (size_t)arg2); +fail: +#ifndef JNI64 + OS_NATIVE_EXIT(env, that, memmove__ILorg_eclipse_swt_internal_gtk_GdkEventKey_2I_FUNC); +#else + OS_NATIVE_EXIT(env, that, memmove__JLorg_eclipse_swt_internal_gtk_GdkEventKey_2J_FUNC); +#endif +} +#endif + #if (!defined(NO_memmove__ILorg_eclipse_swt_internal_gtk_GdkEventMotion_2I) && !defined(JNI64)) || (!defined(NO_memmove__JLorg_eclipse_swt_internal_gtk_GdkEventMotion_2J) && defined(JNI64)) #ifndef JNI64 JNIEXPORT void JNICALL OS_NATIVE(memmove__ILorg_eclipse_swt_internal_gtk_GdkEventMotion_2I)(JNIEnv *env, jclass that, jintLong arg0, jobject arg1, jintLong arg2) diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h index 9a040590de..f3a552b8b1 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h @@ -296,12 +296,14 @@ #define gdk_screen_get_monitor_workarea_LIB LIB_GDK #define gdk_seat_grab_LIB LIB_GDK #define gdk_seat_ungrab_LIB LIB_GDK +#define gdk_seat_get_pointer_LIB LIB_GDK #define gdk_window_set_background_pattern_LIB LIB_GTK #define gtk_widget_input_shape_combine_region_LIB LIB_GTK #define gtk_entry_set_placeholder_text_LIB LIB_GTK #define gtk_entry_get_icon_area_LIB LIB_GTK #define gdk_event_get_scroll_deltas_LIB LIB_GTK #define gdk_event_get_seat_LIB LIB_GDK +#define gdk_event_get_event_type_LIB LIB_GDK #define gtk_cell_renderer_get_preferred_height_for_width_LIB LIB_GTK #define gtk_css_provider_load_from_data_LIB LIB_GTK #define gtk_css_provider_new_LIB LIB_GTK diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c index 2e67575423..cf6835baa8 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c @@ -454,6 +454,7 @@ char * OS_nativeFunctionNames[] = { "_1gdk_1event_1free", "_1gdk_1event_1get", "_1gdk_1event_1get_1coords", + "_1gdk_1event_1get_1event_1type", "_1gdk_1event_1get_1scroll_1deltas", "_1gdk_1event_1get_1seat", "_1gdk_1event_1get_1state", @@ -531,6 +532,7 @@ char * OS_nativeFunctionNames[] = { "_1gdk_1screen_1height", "_1gdk_1screen_1width", "_1gdk_1screen_1width_1mm", + "_1gdk_1seat_1get_1pointer", "_1gdk_1seat_1grab", "_1gdk_1seat_1ungrab", "_1gdk_1selection_1owner_1get", @@ -1609,6 +1611,11 @@ char * OS_nativeFunctionNames[] = { "memmove__JLorg_eclipse_swt_internal_gtk_GdkEventExpose_2J", #endif #ifndef JNI64 + "memmove__ILorg_eclipse_swt_internal_gtk_GdkEventKey_2I", +#else + "memmove__JLorg_eclipse_swt_internal_gtk_GdkEventKey_2J", +#endif +#ifndef JNI64 "memmove__ILorg_eclipse_swt_internal_gtk_GdkEventMotion_2I", #else "memmove__JLorg_eclipse_swt_internal_gtk_GdkEventMotion_2J", diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h index 61a1ca03e1..0b17e4ecd9 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h @@ -464,6 +464,7 @@ typedef enum { _1gdk_1event_1free_FUNC, _1gdk_1event_1get_FUNC, _1gdk_1event_1get_1coords_FUNC, + _1gdk_1event_1get_1event_1type_FUNC, _1gdk_1event_1get_1scroll_1deltas_FUNC, _1gdk_1event_1get_1seat_FUNC, _1gdk_1event_1get_1state_FUNC, @@ -541,6 +542,7 @@ typedef enum { _1gdk_1screen_1height_FUNC, _1gdk_1screen_1width_FUNC, _1gdk_1screen_1width_1mm_FUNC, + _1gdk_1seat_1get_1pointer_FUNC, _1gdk_1seat_1grab_FUNC, _1gdk_1seat_1ungrab_FUNC, _1gdk_1selection_1owner_1get_FUNC, @@ -1619,6 +1621,11 @@ typedef enum { memmove__JLorg_eclipse_swt_internal_gtk_GdkEventExpose_2J_FUNC, #endif #ifndef JNI64 + memmove__ILorg_eclipse_swt_internal_gtk_GdkEventKey_2I_FUNC, +#else + memmove__JLorg_eclipse_swt_internal_gtk_GdkEventKey_2J_FUNC, +#endif +#ifndef JNI64 memmove__ILorg_eclipse_swt_internal_gtk_GdkEventMotion_2I_FUNC, #else memmove__JLorg_eclipse_swt_internal_gtk_GdkEventMotion_2J_FUNC, diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java index 11043ae4d4..959aa999a8 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java @@ -4239,6 +4239,20 @@ public static final int gdk_event_get_time(long /*int*/ event) { } } /** + * @method flags=dynamic + * @param event cast=(GdkEvent *) + */ +public static final native int _gdk_event_get_event_type(long /*int*/ event); +/** [GTK3.10+] */ +public static final int gdk_event_get_event_type(long /*int*/ event) { + lock.lock(); + try { + return _gdk_event_get_event_type(event); + } finally { + lock.unlock(); + } +} +/** * @param func cast=(GdkEventFunc) * @param data cast=(gpointer) * @param notify cast=(GDestroyNotify) @@ -5238,6 +5252,18 @@ public static final void gdk_seat_ungrab(long /*int*/ seat) { lock.unlock(); } } +/** + * @method flags=dynamic + */ +public static final native long /*int*/ _gdk_seat_get_pointer(long /*int*/ seat); +public static final long /*int*/ gdk_seat_get_pointer(long /*int*/ seat) { + lock.lock(); + try { + return _gdk_seat_get_pointer(seat); + } finally { + lock.unlock(); + } +} /** @param program_class cast=(const char *) */ public static final native void _gdk_set_program_class(byte[] program_class); public static final void gdk_set_program_class(byte[] program_class) { @@ -15292,6 +15318,12 @@ public static final native void memmove(long /*int*/ dest, GdkEventButton src, l * @param src cast=(const void *),flags=no_out * @param size cast=(size_t) */ +public static final native void memmove(long /*int*/ dest, GdkEventKey src, long /*int*/ size); +/** + * @param dest cast=(void *) + * @param src cast=(const void *),flags=no_out + * @param size cast=(size_t) + */ public static final native void memmove(long /*int*/ dest, GdkEventExpose src, long /*int*/ size); /** * @param dest cast=(void *) diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Menu.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Menu.java index 26fe500029..7fbc335e74 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Menu.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Menu.java @@ -246,6 +246,37 @@ void _setVisible (boolean visible) { event.device = OS.gdk_device_manager_get_client_pointer (device_manager); event.time = display.getLastEventTime (); OS.memmove (eventPtr, event, GdkEventButton.sizeof); + OS.gtk_menu_popup_at_pointer (handle, eventPtr); + } else { + if (!OS.isX11()) { + /* + * Lack of absolute coordinates make Wayland event windows inaccurate. + * If we are running on the Wayland the best way to pop-up a menu + * is by using the location of the mouse pointer. See bug 530059. + */ + long /*int*/ seat = OS.gdk_event_get_seat(eventPtr); + long /*int*/ pointer = OS.gdk_seat_get_pointer(seat); + long /*int*/ deviceWindow = OS.gdk_device_get_window_at_position(pointer, null, null); + OS.g_object_ref(deviceWindow); + /* + * The event is most likely a button or key press. If it isn't + * we don't want it -- fall back to the event found with + * gtk_get_current_event(). + */ + int eventType = OS.gdk_event_get_event_type(eventPtr); + switch (eventType) { + case OS.GDK_BUTTON_PRESS: + GdkEventButton eventButton = new GdkEventButton(); + OS.memmove (eventButton, eventPtr, GdkEventButton.sizeof); + eventButton.window = deviceWindow; + OS.memmove(eventPtr, eventButton, GdkEventButton.sizeof); + case OS.GDK_KEY_PRESS: + GdkEventKey eventKey = new GdkEventKey(); + OS.memmove (eventKey, eventPtr, GdkEventKey.sizeof); + eventKey.window = deviceWindow; + OS.memmove(eventPtr, eventKey, GdkEventKey.sizeof); + } + } } OS.gtk_menu_popup_at_pointer (handle, eventPtr); OS.gdk_event_free (eventPtr); |