diff --git a/src/backend/wayland.c b/src/backend/wayland.c index fd8c6bc..77669f1 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -5,7 +5,6 @@ #include #include -#include #include #include #include @@ -339,6 +338,75 @@ static void xdg_surface_configure( self->wayland.configured = MwTRUE; } +static int event_loop(struct _MwLLWayland* wayland) { + enum { + DISPLAY_FD, + KEYREPEAT_FD, + CURSOR_FD + }; + struct pollfd fd; + int timeout = 100; + + if(wayland->force_redraw) { + return 1; + } + + if(wayland->display == NULL) { + return 0; + } + fd.fd = wl_display_get_fd(wayland->display); + fd.events = POLLIN; + + while(wl_display_prepare_read(wayland->display) != 0) { + if(wl_display_dispatch_pending(wayland->display) > 0) { + return 0; + } + } + + /* If an error other than EAGAIN happens, we have likely been disconnected from the Wayland session */ + while(wl_display_flush(wayland->display) == -1) { + if(errno != EAGAIN) { + return MwFALSE; + } + + while(poll(&fd, 1, -1) == -1) { + if(errno != EINTR && errno != EAGAIN) { + wl_display_cancel_read(wayland->display); + + wayland->toplevel->running = MwFALSE; + return 0; + } + } + } + + /* + IOI: + I took this from ioilib which I in turn adapted from SDL. I think this is meant to be required? + But doing this on my main machine causes the decorations manager to be null...? This doesn't show up on the project currently using ioilib. + Race condition? Random KDE bug? Who knows, but it seems that not polling for this works anyways (possibly because we already flush events above and then cancel reads when we actually need to close). + */ + /* + + // Condition where no events are being sent. + if(!poll(&fd, 1, timeout)) { + wl_display_cancel_read(wayland->display); + // In this case, we need to commit the surface for any animations, etc. + wl_surface_commit(wayland->surface); + return 0; + } + + */ + + if(fd.revents & POLLIN) { + wl_display_read_events(wayland->display); + if(wl_display_dispatch_pending(wayland->display) > 0) { + } + } else { + wl_display_cancel_read(wayland->display); + } + return 0; +} + #define WL_INTERFACE(interface) \ shput(wayland->wl_protocol_setup_map, interface##_interface.name, (wl_setup_func*)interface##_setup); @@ -361,23 +429,9 @@ static void setup_callbacks(struct _MwLLWayland* wayland) { #undef WL_INTERFACE -static MwBool flush_display(struct wl_display* display) { - while(wl_display_flush(display) == -1) { - if(errno != EAGAIN) { - return MwFALSE; - } - - struct pollfd fd = {wl_display_get_fd(display), POLL_OUT}; - - while(poll(&fd, 1, -1) == -1) { - if(errno != EINTR && errno != EAGAIN) - return MwFALSE; - } - } - return MwTRUE; -} - static void setup_toplevel(MwLL r, int x, int y, int width, int height) { + int i; + r->wayland.type = MWLL_WAYLAND_TOPLEVEL; r->wayland.toplevel = malloc(sizeof(struct _MwLLWaylandTopLevel)); @@ -400,6 +454,16 @@ static void setup_toplevel(MwLL r, int x, int y, int width, int height) { return; } + printf("Found globals: \n"); + for(i = 0; i < shlen(r->wayland.wl_protocol_map); i++) { + wayland_protocol_t* proto = shget(r->wayland.wl_protocol_map, r->wayland.wl_protocol_map[i].key); + if(proto != NULL) { + printf("%s (%p)\n", r->wayland.wl_protocol_map[i].key, r->wayland.wl_protocol_map[i].value); + } else { + printf("%s (proto is null)\n", r->wayland.wl_protocol_map[i].key, r->wayland.wl_protocol_map[i].value); + } + } + // Check that all globals we require are available if( r->wayland.compositor == NULL || @@ -433,11 +497,12 @@ static void setup_toplevel(MwLL r, int x, int y, int width, int height) { // Perform the initial commit and wait for the first configure event wl_surface_commit(r->wayland.surface); - while(wl_display_dispatch(r->wayland.display) != -1 && !r->wayland.configured) { - } + event_loop(&r->wayland); + + printf("%p\n", shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name)); // setup decorations if we can - if(WAYLAND_GET_INTERFACE(r->wayland, zxdg_decoration_manager_v1)->context != NULL) { + if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL) { zxdg_decoration_manager_v1_context_t* dec = WAYLAND_GET_INTERFACE(r->wayland, zxdg_decoration_manager_v1)->context; dec->decoration = zxdg_decoration_manager_v1_get_toplevel_decoration( @@ -537,7 +602,6 @@ static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsign } static void MwLLSetXYImpl(MwLL handle, int x, int y) { - if(handle->wayland.type != MWLL_WAYLAND_TOPLEVEL) { handle->wayland.x = x; handle->wayland.y = y; @@ -645,56 +709,7 @@ static void MwLLFreeColorImpl(MwLLColor color) { } static int MwLLPendingImpl(MwLL handle) { - enum { - DISPLAY_FD, - KEYREPEAT_FD, - CURSOR_FD - }; - struct pollfd fd; - int timeout = 1; - - if(handle->wayland.force_redraw) { - return 1; - } - - if(handle->wayland.display == NULL) { - return 0; - } - fd.fd = wl_display_get_fd(handle->wayland.display); - fd.events = POLLIN; - - while(wl_display_prepare_read(handle->wayland.display) != 0) { - if(wl_display_dispatch_pending(handle->wayland.display) > 0) { - return 0; - } - } - - // If an error other than EAGAIN happens, we have likely been disconnected - // from the Wayland session - if(!flush_display(handle->wayland.display)) { - wl_display_cancel_read(handle->wayland.display); - - handle->wayland.toplevel->running = MwFALSE; - return 0; - } - - // Condition where no events are being sent. - if(!poll(&fd, 1, timeout)) { - wl_display_cancel_read(handle->wayland.display); - // In this case, we need to commit the surface for any animations, etc. - wl_surface_commit(handle->wayland.surface); - return 0; - } - - if(fd.revents & POLLIN) { - wl_display_read_events(handle->wayland.display); - if(wl_display_dispatch_pending(handle->wayland.display) > 0) { - } - } else { - wl_display_cancel_read(handle->wayland.display); - } - - return 1; + return event_loop(&handle->wayland); } static void MwLLNextEventImpl(MwLL handle) {