@@ -723,14 +723,6 @@ Rectangle computeTrimInPixels (int x, int y, int width, int height) {
723723 trim .y -= menuBarHeight ;
724724 trim .height += menuBarHeight ;
725725 }
726- if (GTK .GTK4 && OS .isWayland ()) {
727- long titlebar = GTK4 .gtk_window_get_titlebar (shellHandle );
728- if (titlebar != 0 ) {
729- int titleBarHeight = GTK4 .gtk_widget_get_height (titlebar );
730- trim .y -= titleBarHeight ;
731- trim .height += titleBarHeight ;
732- }
733- }
734726 return trim ;
735727}
736728
@@ -971,6 +963,7 @@ void hookEvents () {
971963 long gdkSurface = gtk_widget_get_surface (shellHandle );
972964 OS .g_signal_connect (gdkSurface , OS .notify_state , display .notifyProc , shellHandle );
973965 OS .g_signal_connect (gdkSurface , OS .compute_size , display .computeSizeProc , shellHandle );
966+ OS .g_signal_connect (gdkSurface , OS .layout , display .layoutProc , shellHandle );
974967 OS .g_signal_connect (shellHandle , OS .notify_default_height , display .notifyProc , Widget .NOTIFY_DEFAULT_HEIGHT );
975968 OS .g_signal_connect (shellHandle , OS .notify_default_width , display .notifyProc , Widget .NOTIFY_DEFAULT_WIDTH );
976969 OS .g_signal_connect (shellHandle , OS .notify_maximized , display .notifyProc , Widget .NOTIFY_MAXIMIZED );
@@ -1812,7 +1805,6 @@ long gtk3_key_press_event (long widget, long event) {
18121805@ Override
18131806long gtk_size_allocate (long widget , long allocation ) {
18141807 int width , height ;
1815- GdkRectangle monitorSize = new GdkRectangle ();
18161808 int [] widthA = new int [1 ];
18171809 int [] heightA = new int [1 ];
18181810
@@ -1840,11 +1832,14 @@ long gtk_size_allocate (long widget, long allocation) {
18401832 heightA [0 ] = Math .max (1 , heightA [0 ] - headerNaturalHeight [0 ]);
18411833 }
18421834 } else {
1843- long display = GDK .gdk_display_get_default ();
1844- long monitor = GDK .gdk_display_get_monitor_at_surface (display , paintSurface ());
1845- GDK .gdk_monitor_get_geometry (monitor , monitorSize );
1846- widthA [0 ] = monitorSize .width ;
1847- heightA [0 ] = monitorSize .height - headerNaturalHeight [0 ];
1835+ /*
1836+ * For maximized windows, neither gtk_window_get_default_size() nor
1837+ * gdk_surface_get_width/height() have the new dimensions yet when
1838+ * notify::maximized fires. The GdkSurface::layout signal fires
1839+ * synchronously after the compositor commits the new allocation;
1840+ * gtk_layout() handles the resize from there.
1841+ */
1842+ return 0 ;
18481843 }
18491844 } else {
18501845 GTK3 .gtk_window_get_size (shellHandle , widthA , heightA );
@@ -1864,6 +1859,37 @@ long gtk_size_allocate (long widget, long allocation) {
18641859 return 0 ;
18651860}
18661861
1862+ @ Override
1863+ void gtk_layout (long surface , int surfaceWidth , int surfaceHeight ) {
1864+ /*
1865+ * Used exclusively for the maximized case:
1866+ * notify::maximized fires before the compositor commits the new size, so
1867+ * gtk_size_allocate returns 0 early for maximized windows and defers here.
1868+ *
1869+ * For non-maximized resizes, sizing is already handled correctly via
1870+ * gtk_window_get_default_size, so those are skipped here to avoid overriding
1871+ * with different surface dimensions.
1872+ *
1873+ * Surface width and height - total GTK window size including the header bar.
1874+ */
1875+ if (!GTK4 .gtk_window_is_maximized (shellHandle )) return ;
1876+
1877+ long header = GTK4 .gtk_window_get_titlebar (shellHandle );
1878+ int headerH = 0 ;
1879+ if (header != 0 ) {
1880+ int [] headerNaturalHeight = new int [1 ];
1881+ GTK4 .gtk_widget_measure (header , GTK .GTK_ORIENTATION_VERTICAL , -1 , null , headerNaturalHeight , null , null );
1882+ headerH = headerNaturalHeight [0 ];
1883+ }
1884+ int newWidth = surfaceWidth ;
1885+ int newHeight = Math .max (1 , surfaceHeight - headerH );
1886+ if ((!resized || oldWidth != newWidth || oldHeight != newHeight ) && newWidth > 0 ) {
1887+ oldWidth = newWidth ;
1888+ oldHeight = newHeight ;
1889+ resizeBounds (newWidth , newHeight , true );
1890+ }
1891+ }
1892+
18671893private void updateDecorations (long gdkResource ) {
18681894 if (OS .isX11 ()) {
18691895 /*
@@ -2345,25 +2371,21 @@ int setBounds (int x, int y, int width, int height, boolean move, boolean resize
23452371 if (geometry .getMaxHeight () > 0 ) {
23462372 height = Math .min (height , geometry .getMaxHeight ());
23472373 }
2348- /*
2349- * If the shell is created without a RESIZE style bit, and the
2350- * minWidth/minHeight/maxWidth/maxHeight have been set, allow the resize.
2351- */
2352- if ((style & SWT .RESIZE ) != 0 || (geometry .getMinHeight () != 0 || geometry .getMinWidth () != 0 || geometry .getMaxHeight () != 0 || geometry .getMaxWidth () != 0 )) {
2353- if (GTK .GTK4 ) {
2354- /*
2355- * On GTK4, GtkWindow size includes the header bar. In order to keep window size allocation of the client area
2356- * consistent with previous versions of SWT, we need to include the header bar height in addition to the given height value.
2357- */
2358- long header = GTK4 .gtk_window_get_titlebar (shellHandle );
2359- int [] headerNaturalHeight = new int [1 ];
2360- if (header != 0 ) {
2361- GTK4 .gtk_widget_measure (header , GTK .GTK_ORIENTATION_VERTICAL , -1 , null , headerNaturalHeight , null , null );
2362- }
2363- GTK .gtk_window_set_default_size (shellHandle , width , height + headerNaturalHeight [0 ]);
2364- } else {
2365- GTK3 .gtk_window_resize (shellHandle , width , height );
2374+ if (GTK .GTK4 ) {
2375+ /*
2376+ * GtkWindow size includes the header bar. To stay consistent with previous
2377+ * versions of SWT, header bar height has to be added to the given height value.
2378+ * This applies to all shell styles that have a title bar (e.g. SHELL_TRIM,
2379+ * DIALOG_TRIM).
2380+ */
2381+ long header = GTK4 .gtk_window_get_titlebar (shellHandle );
2382+ int [] headerNaturalHeight = new int [1 ];
2383+ if (header != 0 ) {
2384+ GTK4 .gtk_widget_measure (header , GTK .GTK_ORIENTATION_VERTICAL , -1 , null , headerNaturalHeight , null , null );
23662385 }
2386+ GTK .gtk_window_set_default_size (shellHandle , width , height + headerNaturalHeight [0 ]);
2387+ } else if ((style & SWT .RESIZE ) != 0 || (geometry .getMinHeight () != 0 || geometry .getMinWidth () != 0 || geometry .getMaxHeight () != 0 || geometry .getMaxWidth () != 0 )) {
2388+ GTK3 .gtk_window_resize (shellHandle , width , height );
23672389 }
23682390 boolean changed = width != oldWidth || height != oldHeight ;
23692391 if (changed ) {
@@ -2520,19 +2542,17 @@ void setInitialBounds() {
25202542 height = (int ) (dest .height * SHELL_TO_MONITOR_RATIO );
25212543 }
25222544
2523- if ((style & SWT .RESIZE ) != 0 ) {
2524- /*
2525- * On GTK4, GtkWindow size includes the header bar. In order to keep window size allocation of the client area
2526- * consistent with previous versions of SWT, we need to include the header bar height in addition to the given height value.
2527- */
2528- long header = GTK4 .gtk_window_get_titlebar (shellHandle );
2529- int [] headerNaturalHeight = new int [1 ];
2530- if (header != 0 ) {
2531- GTK4 .gtk_widget_measure (header , GTK .GTK_ORIENTATION_VERTICAL , -1 , null , headerNaturalHeight , null , null );
2532- }
2533-
2534- GTK .gtk_window_set_default_size (shellHandle , width , height + headerNaturalHeight [0 ]);
2545+ /*
2546+ * GtkWindow size includes the header bar. To stay
2547+ * consistent with previous versions of SWT the header bar height is added the given height value.
2548+ * This applies to all shell styles.
2549+ */
2550+ long header = GTK4 .gtk_window_get_titlebar (shellHandle );
2551+ int [] headerNaturalHeight = new int [1 ];
2552+ if (header != 0 ) {
2553+ GTK4 .gtk_widget_measure (header , GTK .GTK_ORIENTATION_VERTICAL , -1 , null , headerNaturalHeight , null , null );
25352554 }
2555+ GTK .gtk_window_set_default_size (shellHandle , width , height + headerNaturalHeight [0 ]);
25362556 } else {
25372557 long display = GDK .gdk_display_get_default ();
25382558 if (display != 0 ) {
@@ -3158,6 +3178,24 @@ int trimHeight () {
31583178 // Shells with both ON_TOP and RESIZE set only use border, not trim.
31593179 // See bug 319612.
31603180 if (isCustomResize ()) return 0 ;
3181+ if (GTK .GTK4 && OS .isWayland ()) {
3182+ /*
3183+ * On GTK4 Wayland, window decorations are implemented as GTK CSD widgets. The
3184+ * title bar (GtkHeaderBar) is part of the GtkWindow and its height must be
3185+ * queried dynamically. Use gtk_widget_get_height() if already allocated,
3186+ * otherwise gtk_widget_measure() which works even before the window is
3187+ * realized/shown.
3188+ */
3189+ long titlebar = GTK4 .gtk_window_get_titlebar (shellHandle );
3190+ if (titlebar != 0 ) {
3191+ int height = GTK4 .gtk_widget_get_height (titlebar );
3192+ if (height > 0 ) return height ;
3193+ int [] naturalHeight = new int [1 ];
3194+ GTK4 .gtk_widget_measure (titlebar , GTK .GTK_ORIENTATION_VERTICAL , -1 , null , naturalHeight , null , null );
3195+ return naturalHeight [0 ];
3196+ }
3197+ return 0 ;
3198+ }
31613199 boolean hasTitle = false , hasResize = false , hasBorder = false ;
31623200 hasTitle = (style & (SWT .MIN | SWT .MAX | SWT .TITLE | SWT .MENU )) != 0 ;
31633201 hasResize = (style & SWT .RESIZE ) != 0 ;
@@ -3178,6 +3216,10 @@ int trimWidth () {
31783216 // Shells with both ON_TOP and RESIZE set only use border, not trim.
31793217 // See bug 319612.
31803218 if (isCustomResize ()) return 0 ;
3219+ if (GTK .GTK4 && OS .isWayland ()) {
3220+ // On GTK4 Wayland CSD, the title bar adds height only.
3221+ return 0 ;
3222+ }
31813223 boolean hasTitle = false , hasResize = false , hasBorder = false ;
31823224 hasTitle = (style & (SWT .MIN | SWT .MAX | SWT .TITLE | SWT .MENU )) != 0 ;
31833225 hasResize = (style & SWT .RESIZE ) != 0 ;
0 commit comments