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

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()
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
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.
with calls to <tt>eglGetDisplay(), eglInitialize()</tt>, and \c eglBindAPI().
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(),
@ -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
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
\c draw_overlay() member function.
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).
\c draw_overlay() member function. Then, it calls function \c eglSwapBuffers().
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().

View File

@ -1,7 +1,7 @@
//
// 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
// the file "COPYING" which should have been included with this file. If this
@ -39,7 +39,6 @@ private:
static EGLDisplay egl_display;
struct wl_egl_window *egl_window;
EGLSurface egl_surface;
bool egl_swap_in_progress;
Fl_Wayland_Gl_Window_Driver(Fl_Gl_Window *win);
float pixels_per_unit() FL_OVERRIDE;
void make_current_before() FL_OVERRIDE;

View File

@ -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();
egl_window = 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 (egl_surface && !egl_swap_in_progress) {
egl_swap_in_progress = true; // prevents crash while down resizing rotating glpuzzle
wl_display_dispatch_pending(Fl_Wayland_Screen_Driver::wl_display);
if (egl_surface) {
eglSwapBuffers(Fl_Wayland_Gl_Window_Driver::egl_display, egl_surface);
egl_swap_in_progress = false;
}
}

View File

@ -168,6 +168,10 @@ public:
int get_key(int k) FL_OVERRIDE;
void enable_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
void screen_count_set(int count) {num_screens = count;}

View File

@ -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) {
if (k >= 'A' && k <= 'Z') k += 32;
return (search_int_vector(key_vector, k) >= 0);

View File

@ -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() {
Fl_X* ip = Fl_X::flx(pWindow);
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);
free(wld_win);
}
if (pWindow->as_gl_window() && in_flush_) {
// 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;
}
delete ip;
}