diff options
Diffstat (limited to 'bundles')
5 files changed, 85 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 428d448027..7cddab1bdb 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 @@ -13328,6 +13328,31 @@ JNIEXPORT jintLong JNICALL GTK_NATIVE(_1gtk_1widget_1get_1parent_1window) } #endif +#ifndef NO__1gtk_1widget_1get_1preferred_1height +JNIEXPORT void JNICALL GTK_NATIVE(_1gtk_1widget_1get_1preferred_1height) + (JNIEnv *env, jclass that, jintLong arg0, jintArray arg1, jintArray arg2) +{ + jint *lparg1=NULL; + jint *lparg2=NULL; + GTK_NATIVE_ENTER(env, that, _1gtk_1widget_1get_1preferred_1height_FUNC); + if (arg1) if ((lparg1 = (*env)->GetIntArrayElements(env, arg1, NULL)) == NULL) goto fail; + if (arg2) if ((lparg2 = (*env)->GetIntArrayElements(env, arg2, NULL)) == NULL) goto fail; +/* + gtk_widget_get_preferred_height(arg0, lparg1, lparg2); +*/ + { + GTK_LOAD_FUNCTION(fp, gtk_widget_get_preferred_height) + if (fp) { + ((void (CALLING_CONVENTION*)(jintLong, jint *, jint *))fp)(arg0, lparg1, lparg2); + } + } +fail: + if (arg2 && lparg2) (*env)->ReleaseIntArrayElements(env, arg2, lparg2, 0); + if (arg1 && lparg1) (*env)->ReleaseIntArrayElements(env, arg1, lparg1, 0); + GTK_NATIVE_EXIT(env, that, _1gtk_1widget_1get_1preferred_1height_FUNC); +} +#endif + #ifndef NO__1gtk_1widget_1get_1preferred_1height_1for_1width JNIEXPORT void JNICALL GTK_NATIVE(_1gtk_1widget_1get_1preferred_1height_1for_1width) (JNIEnv *env, jclass that, jintLong arg0, jint arg1, jintArray arg2, jintArray arg3) 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 ddb326eacf..43acdb330e 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 @@ -1068,6 +1068,7 @@ char * GTK_nativeFunctionNames[] = { "_1gtk_1widget_1get_1pango_1context", "_1gtk_1widget_1get_1parent", "_1gtk_1widget_1get_1parent_1window", + "_1gtk_1widget_1get_1preferred_1height", "_1gtk_1widget_1get_1preferred_1height_1for_1width", "_1gtk_1widget_1get_1preferred_1size", "_1gtk_1widget_1get_1preferred_1width_1for_1height", 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 f8fd88f489..2038eea393 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 @@ -1066,6 +1066,7 @@ typedef enum { _1gtk_1widget_1get_1pango_1context_FUNC, _1gtk_1widget_1get_1parent_FUNC, _1gtk_1widget_1get_1parent_1window_FUNC, + _1gtk_1widget_1get_1preferred_1height_FUNC, _1gtk_1widget_1get_1preferred_1height_1for_1width_FUNC, _1gtk_1widget_1get_1preferred_1size_FUNC, _1gtk_1widget_1get_1preferred_1width_1for_1height_FUNC, diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GTK.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GTK.java index a343cfef7f..a324248031 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GTK.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GTK.java @@ -1143,6 +1143,18 @@ public class GTK extends OS { /** * @method flags=dynamic */ + public static final native void _gtk_widget_get_preferred_height(long /*int*/ widget, int[] minimum_size, int[] natural_size); + public static final void gtk_widget_get_preferred_height(long /*int*/ widget, int[] minimum_size, int[] natural_size) { + lock.lock(); + try { + _gtk_widget_get_preferred_height(widget, minimum_size, natural_size); + } finally { + lock.unlock(); + } + } + /** + * @method flags=dynamic + */ public static final native void _gtk_widget_get_preferred_width_for_height(long /*int*/ widget, int height, int[] minimum_size, int[] natural_size); public static final void gtk_widget_get_preferred_width_for_height(long /*int*/ widget, int height, int[] minimum_size, int[] natural_size) { lock.lock(); 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 d6ddbbcd35..6620fbc796 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 @@ -45,6 +45,7 @@ public class Menu extends Widget { Decorations parent; long /*int*/ imItem, imSeparator, imHandle; ImageList imageList; + int poppedUpCount; /** * Constructs a new instance of this class given its parent, @@ -278,9 +279,11 @@ void _setVisible (boolean visible) { } } } + verifyMenuPosition(getItemCount()); GTK.gtk_menu_popup_at_pointer (handle, eventPtr); GDK.gdk_event_free (eventPtr); } + poppedUpCount = getItemCount(); } else { sendEvent (SWT.Hide); } @@ -1125,6 +1128,49 @@ void setOrientation (boolean create) { } /** + * Feature in GTK3 on X11: context menus in SWT are populated + * dynamically, sometimes asynchronously outside of SWT + * (i.e. in Platform UI). This means that items are added and + * removed just before the menu is shown. This method of + * changing the menu content can sometimes cause sizing issues + * internally in GTK, specifically with the height of the + * toplevel GdkWindow. <p> + * + * The fix is to cache the number of items popped up previously, + * and if the number of items in the current menu (to be popped up) + * is different, then:<ul> + * <li>get the preferred height of the menu</li> + * <li>set the toplevel GdkWindow to that height</li></ul> + * + * @param itemCount the current number of items in the menu, just + * before it's about to be shown/popped-up + */ +void verifyMenuPosition (int itemCount) { + if (GTK.GTK3 && OS.isX11()) { + if (itemCount != poppedUpCount && poppedUpCount != 0) { + int [] naturalHeight = new int [1]; + /* + * We need to "show" the menu before fetching the preferred height. + * Note, this does not actually pop-up the menu. + */ + GTK.gtk_widget_show(handle); + /* + * Menus are height-for-width only: use gtk_widget_get_preferred_height() + * instead of gtk_widget_get_preferred_size(). + */ + GTK.gtk_widget_get_preferred_height(handle, null, naturalHeight); + if (naturalHeight[0] > 0) { + long /*int*/ topLevelWidget = GTK.gtk_widget_get_toplevel(handle); + long /*int*/ topLevelWindow = GTK.gtk_widget_get_window(topLevelWidget); + int width = GDK.gdk_window_get_width(topLevelWindow); + GDK.gdk_window_resize(topLevelWindow, width, naturalHeight[0]); + } + } + } + return; +} + +/** * Marks the receiver as visible if the argument is <code>true</code>, * and marks it invisible otherwise. * <p> |