Implement Fl_Wayland_Screen_Driver::poll_or_select_with_delay(double)

This commit is contained in:
ManoloFLTK
2023-07-31 16:29:15 +02:00
parent b1ab37eeff
commit 7feddabd24
6 changed files with 24 additions and 43 deletions
+2 -14
View File
@@ -1056,10 +1056,7 @@ native platform window system. OpenGL-using FLTK apps are therefore linked to \c
EGL is initialized calling member function \c Fl_Wayland_Gl_Window_Driver::init() EGL is initialized calling member function \c Fl_Wayland_Gl_Window_Driver::init()
once, the first time the \c Fl_Wayland_Gl_Window_Driver c'tor runs. That is done once, the first time the \c Fl_Wayland_Gl_Window_Driver c'tor runs. That is done
with calls to <tt>eglGetDisplay(), eglInitialize(), eglGetConfigs(), and with calls to <tt>eglGetDisplay(), eglInitialize()</tt>, and \c eglBindAPI().
eglBindAPI()</tt>. Function \c eglGetConfigs() computes the number of usable
EGL frame buffer configurations for the display and stores it in static member variable
\c Fl_Wayland_Gl_Window_Driver::configs_count.
Member function \c Fl_Wayland_Gl_Window_Driver::find() calls \c eglChooseConfig() Member function \c Fl_Wayland_Gl_Window_Driver::find() calls \c eglChooseConfig()
to filter the set of GL configurations that match the \c Fl_Gl_Window's mode(), to filter the set of GL configurations that match the \c Fl_Gl_Window's mode(),
@@ -1089,16 +1086,7 @@ FLTK function \c Fl_Gl_Window::make_current() calls overridden function
FLTK calls function \c Fl_Wayland_Gl_Window_Driver::swap_buffers() each time it wants a FLTK calls function \c Fl_Wayland_Gl_Window_Driver::swap_buffers() each time it wants a
GL context to be sent to the display. This function contains some pure GL code to GL context to be sent to the display. This function contains some pure GL code to
emulate an overlay buffer to support Fl_Gl_Window objects overriding their emulate an overlay buffer to support Fl_Gl_Window objects overriding their
\c draw_overlay() member function. \c draw_overlay() member function. Then, it calls function \c eglSwapBuffers().
Then, it calls function \c eglSwapBuffers() after having called
\c wl_display_dispatch_pending() to synchronize EGL use
with the rest of the Wayland compositor's activity.
Function \c wl_display_dispatch_pending() calls the listeners attached to
commands the Wayland compositor recently sent to the client.
The fact that this function gets called during the process of drawing an Fl_Gl_Window
makes possible a scenario that cannot occur with other FLTK platforms : a GL window can be
closed while being drawn. Function \c Fl_Wayland_Window_Driver::hide() is written to
handle such scenario without error (see comments therein).
The overridden \c Fl_Wayland_Gl_Window_Driver::resize() function is implemented with The overridden \c Fl_Wayland_Gl_Window_Driver::resize() function is implemented with
calls to \c wl_egl_window_get_attached_size() and \c wl_egl_window_resize(). calls to \c wl_egl_window_get_attached_size() and \c wl_egl_window_resize().
@@ -1,7 +1,7 @@
// //
// Class Fl_Wayland_Gl_Window_Driver for the Fast Light Tool Kit (FLTK). // Class Fl_Wayland_Gl_Window_Driver for the Fast Light Tool Kit (FLTK).
// //
// Copyright 2021-2022 by Bill Spitzak and others. // Copyright 2021-2023 by Bill Spitzak and others.
// //
// This library is free software. Distribution and use rights are outlined in // This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this // the file "COPYING" which should have been included with this file. If this
@@ -39,7 +39,6 @@ private:
static EGLDisplay egl_display; static EGLDisplay egl_display;
struct wl_egl_window *egl_window; struct wl_egl_window *egl_window;
EGLSurface egl_surface; EGLSurface egl_surface;
bool egl_swap_in_progress;
Fl_Wayland_Gl_Window_Driver(Fl_Gl_Window *win); Fl_Wayland_Gl_Window_Driver(Fl_Gl_Window *win);
float pixels_per_unit() FL_OVERRIDE; float pixels_per_unit() FL_OVERRIDE;
void make_current_before() FL_OVERRIDE; void make_current_before() FL_OVERRIDE;
@@ -69,7 +69,6 @@ Fl_Wayland_Gl_Window_Driver::Fl_Wayland_Gl_Window_Driver(Fl_Gl_Window *win) : Fl
if (egl_display == EGL_NO_DISPLAY) init(); if (egl_display == EGL_NO_DISPLAY) init();
egl_window = NULL; egl_window = NULL;
egl_surface = NULL; egl_surface = NULL;
egl_swap_in_progress = false;
} }
@@ -342,11 +341,8 @@ void Fl_Wayland_Gl_Window_Driver::swap_buffers() {
if (!overlay_buffer) return; // don't call eglSwapBuffers until overlay has been drawn if (!overlay_buffer) return; // don't call eglSwapBuffers until overlay has been drawn
} }
if (egl_surface && !egl_swap_in_progress) { if (egl_surface) {
egl_swap_in_progress = true; // prevents crash while down resizing rotating glpuzzle
wl_display_dispatch_pending(Fl_Wayland_Screen_Driver::wl_display);
eglSwapBuffers(Fl_Wayland_Gl_Window_Driver::egl_display, egl_surface); eglSwapBuffers(Fl_Wayland_Gl_Window_Driver::egl_display, egl_surface);
egl_swap_in_progress = false;
} }
} }
@@ -168,6 +168,10 @@ public:
int get_key(int k) FL_OVERRIDE; int get_key(int k) FL_OVERRIDE;
void enable_im() FL_OVERRIDE; void enable_im() FL_OVERRIDE;
void disable_im() FL_OVERRIDE; void disable_im() FL_OVERRIDE;
// overridden functions from parent class Fl_Unix_Screen_Driver
int poll_or_select_with_delay(double time_to_wait) FL_OVERRIDE;
int poll_or_select() FL_OVERRIDE;
// Wayland-specific member functions // Wayland-specific member functions
void screen_count_set(int count) {num_screens = count;} void screen_count_set(int count) {num_screens = count;}
@@ -1681,6 +1681,21 @@ void *Fl_Wayland_Screen_Driver::control_maximize_button(void *data) {
} }
int Fl_Wayland_Screen_Driver::poll_or_select_with_delay(double time_to_wait) {
wl_display_dispatch_pending(wl_display);
return Fl_Unix_Screen_Driver::poll_or_select_with_delay(time_to_wait);
}
// like Fl_Wayland_Screen_Driver::poll_or_select_with_delay(0.0) except no callbacks are done:
int Fl_Wayland_Screen_Driver::poll_or_select() {
int ret = wl_display_prepare_read(wl_display);
if (ret == 0) wl_display_cancel_read(wl_display);
else return 1;
return Fl_Unix_Screen_Driver::poll_or_select();
}
int Fl_Wayland_Screen_Driver::event_key(int k) { int Fl_Wayland_Screen_Driver::event_key(int k) {
if (k >= 'A' && k <= 'Z') k += 32; if (k >= 'A' && k <= 'Z') k += 32;
return (search_int_vector(key_vector, k) >= 0); return (search_int_vector(key_vector, k) >= 0);
@@ -427,12 +427,6 @@ static void destroy_surface_caution_pointer_focus(struct wl_surface *surface,
} }
static void delayed_delete_Fl_X(void *data) {
Fl::remove_check(delayed_delete_Fl_X, data);
delete (Fl_X*)data;
}
void Fl_Wayland_Window_Driver::hide() { void Fl_Wayland_Window_Driver::hide() {
Fl_X* ip = Fl_X::flx(pWindow); Fl_X* ip = Fl_X::flx(pWindow);
if (hide_common()) return; if (hide_common()) return;
@@ -483,22 +477,7 @@ void Fl_Wayland_Window_Driver::hide() {
//fprintf(stderr, "After hide: sub=%p frame=%p xdg=%p top=%p pop=%p surf=%p\n", wld_win->subsurface, wld_win->frame, wld_win->xdg_surface, wld_win->xdg_toplevel, wld_win->xdg_popup, wld_win->wl_surface); //fprintf(stderr, "After hide: sub=%p frame=%p xdg=%p top=%p pop=%p surf=%p\n", wld_win->subsurface, wld_win->frame, wld_win->xdg_surface, wld_win->xdg_toplevel, wld_win->xdg_popup, wld_win->wl_surface);
free(wld_win); free(wld_win);
} }
if (pWindow->as_gl_window() && in_flush_) { delete ip;
// Under Wayland and for a GL window, this summarized scenario can occur
// when closing a window with "escape" (e.g. test/cube):
// Fl::flush() calls Fl_Wayland_Window_Driver::flush()
// calls Fl_Wayland_Gl_Window_Driver::swap_buffers()
// calls wl_display_dispatch_pending() calls Fl_Wayland_Window_Driver::hide().
// We make sure here to force exit from the loop over all damaged windows
// in Fl::flush(), and postpone deletion of the Fl_X record until after return
// from Fl::flush().
ip->xid = 0;
ip->next = NULL;
Fl::damage(1); // make sure potential remaining damaged windows get drawn
Fl::add_check(delayed_delete_Fl_X, ip);
} else {
delete ip;
}
} }