[digesting_libdecor] remove return-spaghetti from dispatch logic, cleanup pass over dispatch logic

main
Allen Webster 2026-02-27 21:19:25 -08:00
parent 4c70db56b4
commit 913a5eb607
2 changed files with 157 additions and 194 deletions

View File

@ -91,14 +91,69 @@ GL_FUNCS_XLIST(X)
static Ctx ctx = {0};
static void
xdg_wm_base_ping(void *user_data, struct xdg_wm_base *xdg_wm_base, uint32_t serial){
xdg_wm_base_pong(xdg_wm_base, serial);
}
const struct xdg_wm_base_listener xdg_wm_base_listener = { xdg_wm_base_ping, };
static void
shm_format(void *user_data, struct wl_shm *wl_shm, uint32_t format){
if (format == WL_SHM_FORMAT_ARGB8888){
ctx.has_argb = true;
}
}
const struct wl_shm_listener shm_listener = { shm_format };
static void
output_geometry(void *data, struct wl_output *wl_output,
int32_t x, int32_t y,
int32_t physical_width, int32_t physical_height,
int32_t subpixel, const char *make, const char *model,
int32_t transform){}
static void
output_mode(void *data, struct wl_output *wl_output,
uint32_t flags, int32_t width, int32_t height,
int32_t refresh){}
static void
output_done(void *data, struct wl_output *wl_output){
struct output *output = data;
struct seat *seat;
if (ctx.decoration_type != DECORATION_TYPE_NONE){
redraw_scale(&ctx.shadow);
}
wl_list_for_each(seat, &ctx.seat_list, link){
if (update_local_cursor(seat)){
send_cursor(seat);
}
}
}
static void
output_scale(void *data, struct wl_output *wl_output, int32_t factor){
struct output *output = data;
output->scale = factor;
}
const struct wl_output_listener output_listener = {
output_geometry,
output_mode,
output_done,
output_scale
};
static void
wlevent__wl_registry_global(void *data, struct wl_registry *wl_registry,
uint32_t name, const char *interface,
uint32_t version){
if (strcmp(interface, "wl_compositor") == 0){
ctx.wl_compositor = (struct wl_compositor*)
wl_registry_bind(wl_registry, name, &wl_compositor_interface,
MIN(version, 4));
wl_registry_bind(wl_registry, name, &wl_compositor_interface, MIN(version, 4));
}
else if (!strcmp(interface, xdg_wm_base_interface.name)){
ctx.xdg_wm_base = wl_registry_bind(ctx.wl_registry, name, &xdg_wm_base_interface, MIN(version, 2));
@ -153,7 +208,7 @@ wlevent__wl_registry_global(void *data, struct wl_registry *wl_registry,
wl_list_insert(&ctx.output_list, &output->link);
output->id = name;
output->wl_output = wl_registry_bind(ctx.wl_registry, name, &wl_output_interface, MIN(version, 3));
wl_proxy_set_tag((struct wl_proxy *)output->wl_output, &libdecor_gtk_proxy_tag);
wl_proxy_set_tag((struct wl_proxy*)output->wl_output, &libdecor_gtk_proxy_tag);
wl_output_add_listener(output->wl_output, &output_listener, output);
}
}
@ -175,17 +230,6 @@ const struct wl_registry_listener wl_registry_listener = {
wlevent__wl_registry_global_remove,
};
static void
shm_format(void *user_data, struct wl_shm *wl_shm, uint32_t format){
if (format == WL_SHM_FORMAT_ARGB8888){
ctx.has_argb = true;
}
}
const struct wl_shm_listener shm_listener = {
shm_format
};
static void
init_wl_display_callback(void *user_data, struct wl_callback *callback, uint32_t time){
struct libdecor *context = user_data;
@ -547,12 +591,43 @@ int main(){
exit_loop = 1;
}
for (;!exit_loop;){
/* (libdecor.h)
** " Dispatch events. This function should be called when data is available on
** the file descriptor returned by libdecor_get_fd(). If timeout is zero, this
** function will never block. "
*/
libdecor_dispatch(0);
for (;g_main_context_iteration(0, 0);){}
{
struct pollfd fds[1] = {0};
/* register fds[0] ~ wayland events */
bool wayland_started_read = false;
bool wayland_did_read = false;
{
fds[0].fd = -1;
wl_display_dispatch_pending(ctx.wl_display);
wayland_started_read = (wl_display_prepare_read(ctx.wl_display) != -1);
if (wayland_started_read){
fds[0].fd = wl_display_get_fd(ctx.wl_display);
fds[0].events = POLLIN;
wl_display_flush(ctx.wl_display);
}
}
/* poll and handle events */
int ret = poll(fds, ARRAY_LENGTH(fds), 0);
if (ret > 0){
/* handle fds[0] ~ wayland events */
if (fds[0].revents & POLLIN){
wayland_did_read = true;
wl_display_read_events(ctx.wl_display);
wl_display_dispatch_pending(ctx.wl_display);
}
}
/* wayland event read cleanup */
if (wayland_started_read && !wayland_did_read){
wl_display_cancel_read(ctx.wl_display);
}
}
if (ctx.close_signal){
exit_loop = 1;
@ -1099,20 +1174,6 @@ libdecor_frame_commit(int w, int h, struct libdecor_configuration *configuration
}
}
static void
xdg_wm_base_ping(void *user_data, struct xdg_wm_base *xdg_wm_base, uint32_t serial){
xdg_wm_base_pong(xdg_wm_base, serial);
}
const struct xdg_wm_base_listener xdg_wm_base_listener = {
xdg_wm_base_ping,
};
int
libdecor_dispatch(int timeout){
return libdecor_plugin_gtk_dispatch(timeout);
}
void
cleanup(void){
{
@ -1612,55 +1673,6 @@ own_proxy(void *proxy){
return(result);
}
static void buffer_free(struct buffer *buffer);
static void draw_border_component(struct border_component *border_component);
static void
send_cursor(struct seat *seat);
static bool
update_local_cursor(struct seat *seat);
static int
libdecor_plugin_gtk_dispatch(int timeout){
struct wl_display *wl_display = ctx.wl_display;
struct pollfd fds[1];
int ret;
int dispatch_count = 0;
while (g_main_context_iteration(NULL, FALSE));
while (wl_display_prepare_read(wl_display) != 0)
dispatch_count += wl_display_dispatch_pending(wl_display);
if (wl_display_flush(wl_display) < 0 &&
errno != EAGAIN) {
wl_display_cancel_read(wl_display);
return -errno;
}
fds[0] = (struct pollfd) { wl_display_get_fd(wl_display), POLLIN };
ret = poll(fds, ARRAY_LENGTH(fds), timeout);
if (ret > 0) {
if (fds[0].revents & POLLIN) {
wl_display_read_events(wl_display);
dispatch_count += wl_display_dispatch_pending(wl_display);
return dispatch_count;
} else {
wl_display_cancel_read(wl_display);
return dispatch_count;
}
} else if (ret == 0) {
wl_display_cancel_read(wl_display);
return dispatch_count;
} else {
wl_display_cancel_read(wl_display);
return -errno;
}
}
static void
libdecor_plugin_gtk_set_handle_application_cursor(bool handle_cursor){
ctx.handle_cursor = handle_cursor;
@ -1765,7 +1777,7 @@ redraw_scale(struct border_component *cmpnt){
int scale = 1;
bool need_commit = false;
if (cmpnt->wl_surface != NULL){
if (cmpnt->wl_surface != 0){
wl_list_for_each(surface_output, &cmpnt->output_list, link){
scale = MAX(scale, surface_output->output->scale);
}
@ -2571,7 +2583,7 @@ static bool
update_local_cursor(struct seat *seat){
bool result = false;
if (!seat->pointer_focus){
if (seat->pointer_focus == 0){
seat->current_cursor = seat->cursor_left_ptr;
}
else{
@ -2639,26 +2651,21 @@ update_local_cursor(struct seat *seat){
}
static void
send_cursor(struct seat *seat)
{
struct wl_cursor_image *image;
struct wl_buffer *buffer;
if (seat->pointer_focus == NULL || seat->current_cursor == NULL)
return;
image = seat->current_cursor->images[0];
buffer = wl_cursor_image_get_buffer(image);
wl_surface_attach(seat->cursor_surface, buffer, 0, 0);
wl_surface_set_buffer_scale(seat->cursor_surface, seat->cursor_scale);
wl_surface_damage_buffer(seat->cursor_surface, 0, 0,
image->width * seat->cursor_scale,
image->height * seat->cursor_scale);
wl_surface_commit(seat->cursor_surface);
wl_pointer_set_cursor(seat->wl_pointer, seat->serial,
seat->cursor_surface,
image->hotspot_x / seat->cursor_scale,
image->hotspot_y / seat->cursor_scale);
send_cursor(struct seat *seat){
if (seat->pointer_focus != 0 && seat->current_cursor != 0){
struct wl_cursor_image *image = seat->current_cursor->images[0];
struct wl_buffer *buffer = wl_cursor_image_get_buffer(image);
wl_surface_attach(seat->cursor_surface, buffer, 0, 0);
wl_surface_set_buffer_scale(seat->cursor_surface, seat->cursor_scale);
wl_surface_damage_buffer(seat->cursor_surface, 0, 0,
image->width * seat->cursor_scale,
image->height * seat->cursor_scale);
wl_surface_commit(seat->cursor_surface);
wl_pointer_set_cursor(seat->wl_pointer, seat->serial,
seat->cursor_surface,
image->hotspot_x / seat->cursor_scale,
image->hotspot_y / seat->cursor_scale);
}
}
static void
@ -2692,7 +2699,7 @@ static void
pointer_leave(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface){
struct seat *seat = data;
seat->pointer_focus = NULL;
seat->pointer_focus = 0;
if (surface != 0 && own_proxy(surface)){
ctx.titlebar_gesture.state = TITLEBAR_GESTURE_STATE_INIT;
@ -2713,52 +2720,51 @@ pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time,
struct seat *seat = data;
struct header_element_data new_focus;
if (!seat->pointer_focus || !own_proxy(seat->pointer_focus))
return;
seat->pointer_x = wl_fixed_to_int(surface_x);
seat->pointer_y = wl_fixed_to_int(surface_y);
if (update_local_cursor(seat)){
send_cursor(seat);
}
/* avoid warnings after decoration has been turned off */
if (!GTK_IS_WIDGET(ctx.header) || ctx.active->type != HEADER){
ctx.hdr_focus.type = HEADER_NONE;
}
new_focus = get_header_focus(GTK_HEADER_BAR(ctx.header),
seat->pointer_x, seat->pointer_y);
/* only update if widget change so that we keep the state */
if (ctx.hdr_focus.widget != new_focus.widget) {
ctx.hdr_focus = new_focus;
}
ctx.hdr_focus.state |= GTK_STATE_FLAG_PRELIGHT;
/* redraw with updated button visuals */
draw_title_bar();
wl_surface_commit(ctx.wl_surface);
switch (ctx.titlebar_gesture.state) {
case TITLEBAR_GESTURE_STATE_BUTTON_PRESSED:
if (ctx.titlebar_gesture.first_pressed_button == BTN_LEFT) {
if (ABS((double)seat->pointer_x - (double)ctx.titlebar_gesture.pressed_x) > ctx.drag_threshold ||
ABS((double)seat->pointer_y - (double)ctx.titlebar_gesture.pressed_y) > ctx.drag_threshold){
libdecor_frame_move(seat->wl_seat, ctx.titlebar_gesture.pressed_serial);
}
if (seat->pointer_focus != 0 && own_proxy(seat->pointer_focus)){
seat->pointer_x = wl_fixed_to_int(surface_x);
seat->pointer_y = wl_fixed_to_int(surface_y);
if (update_local_cursor(seat)){
send_cursor(seat);
}
/* avoid warnings after decoration has been turned off */
if (!GTK_IS_WIDGET(ctx.header) || ctx.active->type != HEADER){
ctx.hdr_focus.type = HEADER_NONE;
}
new_focus = get_header_focus(GTK_HEADER_BAR(ctx.header),
seat->pointer_x, seat->pointer_y);
/* only update if widget change so that we keep the state */
if (ctx.hdr_focus.widget != new_focus.widget) {
ctx.hdr_focus = new_focus;
}
ctx.hdr_focus.state |= GTK_STATE_FLAG_PRELIGHT;
/* redraw with updated button visuals */
draw_title_bar();
wl_surface_commit(ctx.wl_surface);
switch (ctx.titlebar_gesture.state) {
case TITLEBAR_GESTURE_STATE_BUTTON_PRESSED:
if (ctx.titlebar_gesture.first_pressed_button == BTN_LEFT) {
if (ABS((double)seat->pointer_x - (double)ctx.titlebar_gesture.pressed_x) > ctx.drag_threshold ||
ABS((double)seat->pointer_y - (double)ctx.titlebar_gesture.pressed_y) > ctx.drag_threshold){
libdecor_frame_move(seat->wl_seat, ctx.titlebar_gesture.pressed_serial);
}
}
case TITLEBAR_GESTURE_STATE_INIT:
case TITLEBAR_GESTURE_STATE_CONSUMED:
case TITLEBAR_GESTURE_STATE_DISCARDED:
break;
}
case TITLEBAR_GESTURE_STATE_INIT:
case TITLEBAR_GESTURE_STATE_CONSUMED:
case TITLEBAR_GESTURE_STATE_DISCARDED:
break;
}
}
static void
handle_button_on_shadow(struct seat *seat, uint32_t serial, uint32_t time,
uint32_t button, uint32_t state){
enum libdecor_resize_edge edge = LIBDECOR_RESIZE_EDGE_NONE;
edge = component_edge(ctx.active, seat->pointer_x, seat->pointer_y, SHADOW_MARGIN);
enum libdecor_resize_edge edge =
component_edge(ctx.active, seat->pointer_x, seat->pointer_y, SHADOW_MARGIN);
if (edge != LIBDECOR_RESIZE_EDGE_NONE &&
(ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE)){
libdecor_frame_resize(seat->wl_seat, serial, edge);
@ -3072,46 +3078,6 @@ const struct wl_touch_listener touch_listener = {
touch_cancel
};
static void
output_geometry(void *data, struct wl_output *wl_output,
int32_t x, int32_t y,
int32_t physical_width, int32_t physical_height,
int32_t subpixel, const char *make, const char *model,
int32_t transform){}
static void
output_mode(void *data, struct wl_output *wl_output,
uint32_t flags, int32_t width, int32_t height,
int32_t refresh){}
static void
output_done(void *data, struct wl_output *wl_output){
struct output *output = data;
struct seat *seat;
if (ctx.decoration_type != DECORATION_TYPE_NONE){
redraw_scale(&ctx.shadow);
}
wl_list_for_each(seat, &ctx.seat_list, link) {
if (update_local_cursor(seat)){
send_cursor(seat);
}
}
}
static void
output_scale(void *data, struct wl_output *wl_output, int32_t factor){
struct output *output = data;
output->scale = factor;
}
const struct wl_output_listener output_listener = {
output_geometry,
output_mode,
output_done,
output_scale
};
static void
remove_surface_outputs(struct border_component *cmpnt, const struct output *output){
struct surface_output *surface_output;

View File

@ -287,8 +287,6 @@ enum titlebar_gesture {
void libdecor_frame_set_visibility(bool visible);
void libdecor_frame_show_window_menu(struct wl_seat *wl_seat, uint32_t serial, int x, int y);
void libdecor_frame_popup_grab(const char *seat_name);
void libdecor_frame_popup_ungrab(const char *seat_name);
void libdecor_frame_translate_coordinate(int surface_x, int surface_y, int *frame_x, int *frame_y);
void libdecor_frame_resize(struct wl_seat *wl_seat, uint32_t serial, enum libdecor_resize_edge edge);
@ -301,8 +299,6 @@ void libdecor_frame_map(void);
bool libdecor_configuration_get_content_size(struct libdecor_configuration *configuration, int *width, int *height);
int libdecor_dispatch(int timeout);
// #include "libdecor-cairo-blur.h"
int blur_surface(cairo_surface_t *surface, int margin);
@ -331,19 +327,20 @@ static void init_wl_output( uint32_t id, uint32_t version);
static void output_removed(struct output *output);
static void draw_header_button(cairo_t *cr, cairo_surface_t *surface, enum header_element button_type);
static const char *libdecor_gtk_proxy_tag = "libdecor-gtk";
static int libdecor_plugin_gtk_dispatch(int timeout);
static void libdecor_plugin_gtk_set_handle_application_cursor(bool handle_cursor);
static void libdecor_plugin_gtk_frame_free(void);
static void libdecor_plugin_gtk_frame_commit(struct libdecor_state *state, struct libdecor_configuration *configuration);
static void libdecor_plugin_gtk_frame_popup_grab(const char *seat_name);
static void libdecor_plugin_gtk_frame_popup_ungrab(const char *seat_name);
static void libdecor_plugin_gtk_frame_get_border_size(enum libdecor_window_state window_state, int *left, int *right, int *top, int *bottom);
static bool update_local_cursor(struct seat *seat);
static void draw_decoration(void);
static void draw_header_button(cairo_t *cr, cairo_surface_t *surface, enum header_element button_type);
static void redraw_scale(struct border_component *cmpnt);
static void send_cursor(struct seat *seat);
static void buffer_free(struct buffer *buffer);
static void draw_border_component(struct border_component *border_component);
// digesting_libdecor