mirror of
https://github.com/fltk/fltk.git
synced 2026-05-10 05:27:55 +08:00
Wayland: dispatch socket data with function libdecor_dispatch() as required by libdecor.
Many thanks to Jonas Ådahl for pointing out FLTK didn't follow this requirement and suggesting code changes (#1390).
This commit is contained in:
@@ -1422,31 +1422,12 @@ static const struct wl_registry_listener registry_listener = {
|
||||
};
|
||||
|
||||
|
||||
static void wayland_socket_callback(int fd, struct wl_display *display)
|
||||
static void libdecor_fd_callback(int fd, struct libdecor *libdecor_context)
|
||||
{
|
||||
if (wl_display_prepare_read(display) == -1) {
|
||||
wl_display_dispatch_pending(display);
|
||||
return;
|
||||
}
|
||||
wl_display_flush(display);
|
||||
struct pollfd fds = (struct pollfd) { fd, POLLIN, 0 };
|
||||
if (poll(&fds, 1, 0) <= 0) {
|
||||
wl_display_cancel_read(display);
|
||||
return;
|
||||
}
|
||||
if (fds.revents & (POLLERR | POLLHUP)) {
|
||||
wl_display_cancel_read(display);
|
||||
goto fatal;
|
||||
}
|
||||
if (wl_display_read_events(display) == -1)
|
||||
goto fatal;
|
||||
if (wl_display_dispatch_pending(display) == -1)
|
||||
goto fatal;
|
||||
return;
|
||||
fatal:
|
||||
if (wl_display_get_error(display) == EPROTO) {
|
||||
if (libdecor_dispatch(libdecor_context, 0) >= 0) return;
|
||||
if (wl_display_get_error(Fl_Wayland_Screen_Driver::wl_display) == EPROTO) {
|
||||
const struct wl_interface *interface;
|
||||
int code = wl_display_get_protocol_error(display, &interface, NULL);
|
||||
int code = wl_display_get_protocol_error(Fl_Wayland_Screen_Driver::wl_display, &interface, NULL);
|
||||
Fl::fatal("Fatal error %d in Wayland protocol: %s",
|
||||
code, (interface ? interface->name : "unknown") );
|
||||
} else {
|
||||
@@ -1511,6 +1492,16 @@ static void do_atexit() {
|
||||
}
|
||||
|
||||
|
||||
static void handle_error(struct libdecor *libdecor_context, enum libdecor_error error, const char *message)
|
||||
{
|
||||
Fl::fatal("Caught error (%d): %s\n", error, message);
|
||||
}
|
||||
|
||||
static struct libdecor_interface libdecor_iface = {
|
||||
.error = handle_error,
|
||||
};
|
||||
|
||||
|
||||
void Fl_Wayland_Screen_Driver::open_display_platform() {
|
||||
static bool beenHereDoneThat = false;
|
||||
if (beenHereDoneThat)
|
||||
@@ -1533,8 +1524,9 @@ void Fl_Wayland_Screen_Driver::open_display_platform() {
|
||||
struct wl_callback *registry_cb = wl_display_sync(wl_display);
|
||||
wl_callback_add_listener(registry_cb, &sync_listener, ®istry_cb);
|
||||
while (registry_cb) wl_display_dispatch(wl_display);
|
||||
Fl::add_fd(wl_display_get_fd(wl_display), FL_READ, (Fl_FD_Handler)wayland_socket_callback,
|
||||
wl_display);
|
||||
libdecor_context = libdecor_new(wl_display, &libdecor_iface);
|
||||
Fl::add_fd(libdecor_get_fd(libdecor_context), FL_READ, (Fl_FD_Handler)libdecor_fd_callback,
|
||||
libdecor_context);
|
||||
fl_create_print_window();
|
||||
/* This is useful to avoid crash of the Wayland compositor after
|
||||
FLTK apps terminate in certain situations:
|
||||
@@ -1621,10 +1613,6 @@ void Fl_Wayland_Screen_Driver::close_display() {
|
||||
wl_seat_destroy(seat->wl_seat); seat->wl_seat = NULL;
|
||||
if (seat->name) free(seat->name);
|
||||
free(seat); seat = NULL;
|
||||
if (libdecor_context) {
|
||||
libdecor_unref(libdecor_context);
|
||||
libdecor_context = NULL;
|
||||
}
|
||||
xdg_wm_base_destroy(xdg_wm_base); xdg_wm_base = NULL;
|
||||
Fl_Wayland_Plugin *plugin = Fl_Wayland_Window_Driver::gl_plugin();
|
||||
if (plugin) plugin->terminate();
|
||||
@@ -1645,7 +1633,11 @@ void Fl_Wayland_Screen_Driver::close_display() {
|
||||
}
|
||||
#endif // HAVE_CURSOR_SHAPE
|
||||
|
||||
Fl::remove_fd(wl_display_get_fd(Fl_Wayland_Screen_Driver::wl_display));
|
||||
if (libdecor_context) {
|
||||
Fl::remove_fd(libdecor_get_fd(libdecor_context));
|
||||
libdecor_unref(libdecor_context);
|
||||
libdecor_context = NULL;
|
||||
}
|
||||
wl_registry_destroy(wl_registry); wl_registry = NULL;
|
||||
wl_display_disconnect(Fl_Wayland_Screen_Driver::wl_display);
|
||||
Fl_Wayland_Screen_Driver::wl_display = NULL;
|
||||
|
||||
@@ -659,18 +659,6 @@ int Fl_Wayland_Window_Driver::scroll(int src_x, int src_y, int src_w, int src_h,
|
||||
}
|
||||
|
||||
|
||||
static void handle_error(struct libdecor *libdecor_context, enum libdecor_error error, const char *message)
|
||||
{
|
||||
Fl::fatal("Caught error (%d): %s\n", error, message);
|
||||
}
|
||||
|
||||
|
||||
static struct libdecor_interface libdecor_iface = {
|
||||
.error = handle_error,
|
||||
};
|
||||
|
||||
|
||||
|
||||
static void delayed_rescale(Fl_Window *win) {
|
||||
Fl_Window_Driver::driver(win)->is_a_rescale(true);
|
||||
win->size(win->w(), win->h());
|
||||
@@ -1054,11 +1042,12 @@ void Fl_Wayland_Window_Driver::wait_for_expose()
|
||||
Fl_Window_Driver::wait_for_expose();
|
||||
struct wld_window * xid = fl_wl_xid(pWindow);
|
||||
if (!xid) return;
|
||||
Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
|
||||
if (pWindow->fullscreen_active()) {
|
||||
if (xid->kind == DECORATED) {
|
||||
while (!(xid->state & LIBDECOR_WINDOW_STATE_FULLSCREEN) ||
|
||||
!(xid->state & LIBDECOR_WINDOW_STATE_ACTIVE)) {
|
||||
wl_display_dispatch(Fl_Wayland_Screen_Driver::wl_display);
|
||||
libdecor_dispatch(scr_driver->libdecor_context, 0);
|
||||
}
|
||||
} else if (xid->kind == UNFRAMED) {
|
||||
wl_display_roundtrip(Fl_Wayland_Screen_Driver::wl_display);
|
||||
@@ -1066,7 +1055,7 @@ void Fl_Wayland_Window_Driver::wait_for_expose()
|
||||
} else if (xid->kind == DECORATED) {
|
||||
// necessary for the windowfocus demo program with recent Wayland versions
|
||||
if (!(xid->state & LIBDECOR_WINDOW_STATE_ACTIVE)) {
|
||||
wl_display_dispatch(Fl_Wayland_Screen_Driver::wl_display);
|
||||
libdecor_dispatch(scr_driver->libdecor_context, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1527,9 +1516,6 @@ void Fl_Wayland_Window_Driver::makeWindow()
|
||||
|
||||
} else if (pWindow->border() && !pWindow->parent() ) { // a decorated window
|
||||
new_window->kind = DECORATED;
|
||||
if (!scr_driver->libdecor_context)
|
||||
scr_driver->libdecor_context = libdecor_new(Fl_Wayland_Screen_Driver::wl_display,
|
||||
&libdecor_iface);
|
||||
new_window->frame = libdecor_decorate(scr_driver->libdecor_context, new_window->wl_surface,
|
||||
&libdecor_frame_iface, new_window);
|
||||
// appears in the Gnome desktop menu bar
|
||||
|
||||
Reference in New Issue
Block a user