FLTK logo

[master] a24bb89 - Simplify and improve function Fl_Wayland_Window_Driver::resize() (#1307)

FLTK matrix user chat room
(using Element browser app)   FLTK gitter user chat room   GitHub FLTK Project   FLTK News RSS Feed  
  FLTK Library      Forums      Links      Apps     Login 
 All Forums  |  Back to fltk.commit  ]
 
Previous Message ]Next Message ]

[master] a24bb89 - Simplify and improve function Fl_Wayland_Window_Driver::resize() (#1307) "ManoloFLTK" 03:02 Sep 30  
 
commit a24bb896c5134f543ca48a39281b28616e4739b5
Author:     ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>
AuthorDate: Tue Sep 30 12:00:18 2025 +0200
Commit:     ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>
CommitDate: Tue Sep 30 12:00:18 2025 +0200

    Simplify and improve function Fl_Wayland_Window_Driver::resize()  (#1307)
    
    This modified implementation improves support of subwindows that are moved or resized
    above their parent toplevel window. It also significantly shortens and clarifies the source code.

 src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx | 194 ++++++++---------------
 1 file changed, 70 insertions(+), 124 deletions(-)

diff --git src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
index 56a7b80..ffb33fb 100644
--- src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
+++ src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
@@ -1816,37 +1816,6 @@ int Fl_Wayland_Window_Driver::set_cursor_4args(const Fl_RGB_Image *rgb, int hotx
 }
 
 
-struct xid_and_rect {
-  struct wld_window *xid;
-  Fl_Window *win;
-  int X, Y, W, H;
-  bool need_resize;
-};
-
-
-static void surface_frame_done(void *data, struct wl_callback *cb, uint32_t time) {
-  struct xid_and_rect *xid_rect = (xid_and_rect *)data;
-  wl_callback_destroy(cb);
-  xid_rect->xid->frame_cb = NULL;
-  if (xid_rect->need_resize) {
-    xid_rect->win->Fl_Group::resize(xid_rect->X, xid_rect->Y, xid_rect->W, xid_rect->H);
-    xid_rect->win->redraw();
-  } else {
-    xid_rect->win->Fl_Widget::resize(xid_rect->X, xid_rect->Y, xid_rect->W, xid_rect->H);
-    if (xid_rect->xid->buffer && xid_rect->xid->buffer->draw_buffer_needs_commit) {
-      // for scenarios where the child window is moved and its parent is simultaneously modified
-      Fl_Wayland_Graphics_Driver::buffer_commit(xid_rect->xid);
-    }
-  }
-  delete xid_rect;
-}
-
-
-static const struct wl_callback_listener surface_frame_listener = {
-  .done = surface_frame_done,
-};
-
-
 void Fl_Wayland_Window_Driver::resize(int X, int Y, int W, int H) {
   static int depth = 0;
   struct wld_window *fl_win = fl_wl_xid(pWindow);
@@ -1872,112 +1841,89 @@ void Fl_Wayland_Window_Driver::resize(int X, int Y, int W, int H) {
   }
   Fl_Window *parent = this->parent() ? pWindow->window() : NULL;
   struct wld_window *parent_xid = parent ? fl_wl_xid(parent) : NULL;
-  xid_and_rect *xid_rect = NULL;
-  if (parent_xid && parent_xid->frame_cb && wl_proxy_get_listener((struct wl_proxy*)parent_xid->frame_cb) == &surface_frame_listener) {
-    xid_rect = (xid_and_rect*)wl_callback_get_user_data(parent_xid->frame_cb);
-    if (xid_rect->win != pWindow) xid_rect = NULL;
-  }
-  // When moving or resizing a non-GL subwindow independently from its parent, this condition
-  // delays application of X,Y,W,H values until the compositor signals
-  // it's ready for a new frame using the frame callback mechanism.
-  if ((parent && parent->damage()) || depth > 1 || pWindow->as_gl_window() || !parent_xid ||
-      wait_for_expose_value || (parent_xid->frame_cb && !xid_rect)) {
-    if (is_a_resize) {
-      if (pWindow->parent()) {
-        if (W < 1) W = 1;
-        if (H < 1) H = 1;
-      }
-      pWindow->Fl_Group::resize(X,Y,W,H);
-      //fprintf(stderr, "resize: win=%p to %dx%d\n", pWindow, W, H);
-      if (shown()) {pWindow->redraw();}
-    } else {
+  // When moving or resizing a subwindow independently from its parent, skip the move/resize
+  // operation if the parent window is being redrawn, in line with the frame callback mechanism.
+  if (depth == 1 && fl_win && parent_xid && parent_xid->frame_cb && is_a_move) {
+    depth--;
+    return;
+  }
+  if (is_a_resize) {
+    if (pWindow->parent()) {
+      if (W < 1) W = 1;
+      if (H < 1) H = 1;
+    }
+    pWindow->Fl_Group::resize(X,Y,W,H);
+    //fprintf(stderr, "resize: win=%p to %dx%d\n", pWindow, W, H);
+    if (shown()) {pWindow->redraw();}
+  } else {
       x(X); y(Y);
       //fprintf(stderr, "move win=%p to %dx%d\n", pWindow, X, Y);
-    }
   }
-
-  if (shown()) {
-    if (is_a_resize) {
-      if (pWindow->as_overlay_window() && other_xid) {
-        destroy_double_buffer();
-      }
-      if (fl_win->kind == DECORATED) { // a decorated window
-        if (fl_win->buffer) {
-          Fl_Wayland_Graphics_Driver::buffer_release(fl_win);
-        }
-        fl_win->configured_width = W;
-        fl_win->configured_height = H;
-        if (!in_handle_configure && xdg_toplevel()) {
-          if (Fl_Window::is_a_rescale()) size_range();
-          struct libdecor_state *state = libdecor_state_new(int(W * f), int(H * f));
-          // necessary only if resize is initiated by prog
-          libdecor_frame_commit(fl_win->frame, state, NULL);
-          libdecor_state_free(state);
-          if (libdecor_frame_is_floating(fl_win->frame)) {
-            fl_win->floating_width = int(W*f);
-            fl_win->floating_height = int(H*f);
-          }
-        }
-      } else if (fl_win->kind == SUBWINDOW && fl_win->subsurface) { // a subwindow
-        wl_subsurface_set_position(fl_win->subsurface, X * f, Y * f);
-        if (!pWindow->as_gl_window()) Fl_Wayland_Graphics_Driver::buffer_release(fl_win);
-        fl_win->configured_width = W;
-        fl_win->configured_height = H;
-      } else if (fl_win->xdg_surface) { // a window without border
-        if (!pWindow->as_gl_window()) Fl_Wayland_Graphics_Driver::buffer_release(fl_win);
-        fl_win->configured_width = W;
-        fl_win->configured_height = H;
-        W *= f; H *= f;
-        if (!pWindow->fullscreen_active()) {
-          xdg_toplevel_set_min_size(fl_win->xdg_toplevel, W, H);
-          xdg_toplevel_set_max_size(fl_win->xdg_toplevel, W, H);
-        }
-        xdg_surface_set_window_geometry(fl_win->xdg_surface, 0, 0, W, H);
-        //printf("xdg_surface_set_window_geometry: %dx%d\n",W, H);
+  if (!fl_win) {
+    depth--;
+    return;
+  }
+  
+  if (is_a_resize) {
+    if (pWindow->as_overlay_window() && other_xid) {
+      destroy_double_buffer();
+    }
+    if (fl_win->kind == DECORATED) { // a decorated window
+      if (fl_win->buffer) {
+        Fl_Wayland_Graphics_Driver::buffer_release(fl_win);
       }
-    } else {
+      fl_win->configured_width = W;
+      fl_win->configured_height = H;
       if (!in_handle_configure && xdg_toplevel()) {
-        // Wayland doesn't seem to provide a reliable way for the app to set the
-        // window position on screen. This is functional when the move is mouse-driven.
-        Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
-        if (Fl::e_state == FL_BUTTON1) {
-          xdg_toplevel_move(xdg_toplevel(), scr_driver->seat->wl_seat, scr_driver->seat->serial);
-          Fl::pushed(NULL);
-          Fl::e_state = 0;
+        if (Fl_Window::is_a_rescale()) size_range();
+        struct libdecor_state *state = libdecor_state_new(int(W * f), int(H * f));
+        // necessary only if resize is initiated by prog
+        libdecor_frame_commit(fl_win->frame, state, NULL);
+        libdecor_state_free(state);
+        if (libdecor_frame_is_floating(fl_win->frame)) {
+          fl_win->floating_width = int(W*f);
+          fl_win->floating_height = int(H*f);
         }
-      } else if (pWindow->as_gl_window() && fl_win->kind == SUBWINDOW && fl_win->subsurface) {
-        wl_subsurface_set_position(fl_win->subsurface, X * f, Y * f);
       }
+    } else if (fl_win->kind == SUBWINDOW && fl_win->subsurface) { // a subwindow
+      wl_subsurface_set_position(fl_win->subsurface, X * f, Y * f);
+      if (!pWindow->as_gl_window()) Fl_Wayland_Graphics_Driver::buffer_release(fl_win);
+      fl_win->configured_width = W;
+      fl_win->configured_height = H;
+    } else if (fl_win->xdg_surface) { // a window without border
+      if (!pWindow->as_gl_window()) Fl_Wayland_Graphics_Driver::buffer_release(fl_win);
+      fl_win->configured_width = W;
+      fl_win->configured_height = H;
+      W *= f; H *= f;
+      if (!pWindow->fullscreen_active()) {
+        xdg_toplevel_set_min_size(fl_win->xdg_toplevel, W, H);
+        xdg_toplevel_set_max_size(fl_win->xdg_toplevel, W, H);
+      }
+      xdg_surface_set_window_geometry(fl_win->xdg_surface, 0, 0, W, H);
+      //printf("xdg_surface_set_window_geometry: %dx%d\n",W, H);
     }
+  } else if (!in_handle_configure && xdg_toplevel() && Fl::e_state == FL_BUTTON1) {
+    // Wayland doesn't provide a way for the app to set the window position on screen.
+    // This is functional when the move is mouse-driven.
+    Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
+    xdg_toplevel_move(xdg_toplevel(), scr_driver->seat->wl_seat, scr_driver->seat->serial);
+    Fl::pushed(NULL);
+    Fl::e_state = 0;
   }
 
-  if (fl_win && parent_xid) {
-    if (pWindow->as_gl_window()) {
-      if (fl_win->frame_cb) {
-        wl_callback_destroy(fl_win->frame_cb);
-        fl_win->frame_cb = NULL;
-      }
-      if (parent_xid->buffer && !parent_xid->frame_cb) {
-        Fl_Wayland_Graphics_Driver::buffer_commit(parent_xid);
-      }
-    } else {
-      if (!(parent && parent->damage()) && !parent_xid->frame_cb) {
-        // use the frame callback mechanism and memorize current X,Y,W,H values
-        xid_rect = new xid_and_rect;
-        xid_rect->xid = parent_xid;
-        xid_rect->win = pWindow;
-        parent_xid->frame_cb = wl_surface_frame(parent_xid->wl_surface);
-        wl_callback_add_listener(parent_xid->frame_cb, &surface_frame_listener, xid_rect);
-        xid_rect->X = X; xid_rect->Y = Y; xid_rect->W = W; xid_rect->H = H;
-        xid_rect->need_resize = is_a_resize;
+  if (parent_xid) {
+    if (depth > 1) {
+      if (fl_win->subsurface) {
         wl_subsurface_set_position(fl_win->subsurface, X * f, Y * f);
         wl_surface_commit(parent_xid->wl_surface);
-      } else if (!xid_rect) {
-        if (is_a_move && fl_win->subsurface) {
-          wl_subsurface_set_position(fl_win->subsurface, X * f, Y * f);
-        }
-        wl_surface_commit(parent_xid->wl_surface);
       }
+    } else if (is_a_move && !parent_xid->frame_cb) {
+      // Use the frame callback mechanism applied to the object's parent window
+      parent_xid->frame_cb = wl_surface_frame(parent_xid->wl_surface);
+      wl_callback_add_listener(parent_xid->frame_cb,
+                               Fl_Wayland_Graphics_Driver::p_surface_frame_listener, parent_xid);
+      if (fl_win->subsurface) wl_subsurface_set_position(fl_win->subsurface, X * f, Y * f);
+      wl_surface_commit(parent_xid->wl_surface);
     }
     checkSubwindowFrame(); // make sure subwindow doesn't leak outside parent
   }
Direct Link to Message ]
 
     
Previous Message ]Next Message ]
 
 

Comments are owned by the poster. All other content is copyright 1998-2025 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.