mirror of
https://github.com/fltk/fltk.git
synced 2026-05-10 05:27:55 +08:00
Wayland: call libdecor_dispatch(), libdecor_unref(), libdecor_get_fd() as expected by libdecor.
Corresponds to these commits to master:8e9e2b7,f121bc1,e8e5e61,d816da5.
This commit is contained in:
@@ -1352,30 +1352,30 @@ static const struct wl_registry_listener registry_listener = {
|
||||
};
|
||||
|
||||
|
||||
extern int fl_send_system_handlers(void *);
|
||||
|
||||
|
||||
static void wayland_socket_callback(int fd, struct wl_display *display) {
|
||||
if (fl_send_system_handlers(NULL)) return;
|
||||
struct pollfd fds = (struct pollfd) { fd, POLLIN, 0 };
|
||||
do {
|
||||
if (wl_display_dispatch(display) == -1) {
|
||||
int err = wl_display_get_error(display);
|
||||
if (err == EPROTO) {
|
||||
const struct wl_interface *interface;
|
||||
int code = wl_display_get_protocol_error(display, &interface, NULL);
|
||||
Fl::fatal("Fatal error no %d in Wayland protocol: %s", code,
|
||||
(interface ? interface->name : "unknown") );
|
||||
} else {
|
||||
Fl::fatal("Fatal error while communicating with the Wayland server: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
static void libdecor_fd_callback(int fd, struct libdecor *libdecor_context) {
|
||||
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(Fl_Wayland_Screen_Driver::wl_display, &interface, NULL);
|
||||
Fl::fatal("Fatal error no %d in Wayland protocol: %s", code,
|
||||
(interface ? interface->name : "unknown") );
|
||||
} else {
|
||||
Fl::fatal("Fatal error while communicating with the Wayland server: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
while (poll(&fds, 1, 0) > 0);
|
||||
}
|
||||
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
|
||||
Fl_Wayland_Screen_Driver::Fl_Wayland_Screen_Driver() : Fl_Unix_Screen_Driver() {
|
||||
libdecor_context = NULL;
|
||||
seat = NULL;
|
||||
@@ -1404,8 +1404,11 @@ static const struct wl_callback_listener sync_listener = {
|
||||
|
||||
|
||||
static void do_atexit() {
|
||||
if (Fl_Wayland_Screen_Driver::wl_display) {
|
||||
wl_display_roundtrip(Fl_Wayland_Screen_Driver::wl_display);
|
||||
// Issue #821 no longer seems to require extra operations under gnome version < 44.
|
||||
Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
|
||||
if (scr_driver->libdecor_context) { // libdecor recommends a call to libdecor_unref()
|
||||
libdecor_unref(scr_driver->libdecor_context);
|
||||
scr_driver->libdecor_context = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1431,15 +1434,10 @@ 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:
|
||||
- gnome-shell version < 44 (e.g. version 42.9)
|
||||
- focus set to "follow-mouse"
|
||||
See issue #821 for details.
|
||||
*/
|
||||
atexit(do_atexit);
|
||||
}
|
||||
|
||||
@@ -1519,21 +1517,20 @@ 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();
|
||||
|
||||
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;
|
||||
delete Fl_Display_Device::display_device()->driver();
|
||||
delete Fl_Display_Device::display_device();
|
||||
delete Fl::system_driver();
|
||||
delete this;
|
||||
}
|
||||
|
||||
|
||||
@@ -648,17 +648,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,
|
||||
};
|
||||
|
||||
|
||||
void change_scale(Fl_Wayland_Screen_Driver::output *output, struct wld_window *window,
|
||||
float pre_scale) {
|
||||
Fl_Wayland_Window_Driver *win_driver = Fl_Wayland_Window_Driver::driver(window->fl_win);
|
||||
@@ -1007,11 +996,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);
|
||||
@@ -1019,7 +1009,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1465,9 +1455,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