diff --git a/digesting_libdecor.c b/digesting_libdecor.c index fd133f1..c0bef08 100755 --- a/digesting_libdecor.c +++ b/digesting_libdecor.c @@ -62,21 +62,6 @@ exit 0 #include "digesting_libdecor.h" -//@global vtables -const struct wl_registry_listener wl_registry_listener; -const struct xdg_surface_listener xdg_surface_listener; -const struct xdg_toplevel_listener xdg_toplevel_listener; -const struct zxdg_toplevel_decoration_v1_listener xdg_toplevel_decoration_listener; -const struct xdg_wm_base_listener xdg_wm_base_listener; -const struct wl_buffer_listener buffer_listener; -const struct wl_callback_listener shm_callback_listener; - -const struct wl_shm_listener shm_listener; -const struct wl_seat_listener seat_listener; -const struct wl_pointer_listener pointer_listener; -const struct wl_touch_listener touch_listener; -const struct wl_output_listener output_listener; - // X(N:name,R:return,P:params) #define GL_FUNCS_XLIST(X)\ X(glDrawBuffer, void, (GLenum buf)) \ @@ -106,6 +91,437 @@ shm_format(void *user_data, struct wl_shm *wl_shm, uint32_t format){ const struct wl_shm_listener shm_listener = { shm_format }; +static void +cursor_surface_enter(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output){ + struct seat *seat = data; + if (own_proxy(wl_output)) { + if (update_local_cursor(seat)){ + send_cursor(seat); + } + } +} + +static void +cursor_surface_leave(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output){ + struct seat *seat = data; + + if (own_proxy(wl_output)){ + if (update_local_cursor(seat)){ + send_cursor(seat); + } + } +} + +static struct wl_surface_listener cursor_surface_listener = { + cursor_surface_enter, + cursor_surface_leave, +}; + +static void +pointer_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, + struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y){ + if (surface){ + struct seat *seat = data; + + bool is_own_surface = own_proxy(surface); + if (is_own_surface || ctx.handle_cursor){ + if (seat->cursor_surface == 0){ + seat->cursor_surface = wl_compositor_create_surface(ctx.wl_compositor); + wl_surface_add_listener(seat->cursor_surface, &cursor_surface_listener, seat); + } + seat->pointer_x = wl_fixed_to_int(surface_x); + seat->pointer_y = wl_fixed_to_int(surface_y); + seat->serial = serial; + seat->pointer_focus = surface; + } + + if (is_own_surface){ + ctx.active = border_component_from_wl_surface(surface); + if (ctx.active){ + draw_decoration(); + wl_surface_commit(ctx.wl_surface); + } + update_local_cursor(seat); + send_cursor(seat); + } + } +} + +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 = 0; + + if (surface != 0 && own_proxy(surface)){ + ctx.titlebar_gesture.state = TITLEBAR_GESTURE_STATE_INIT; + ctx.titlebar_gesture.first_pressed_button = 0; + + ctx.active = 0; + ctx.hdr_focus.widget = 0; + ctx.hdr_focus.type = HEADER_NONE; + draw_decoration(); + wl_surface_commit(ctx.wl_surface); + update_local_cursor(seat); + } +} + +static void +pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, + wl_fixed_t surface_x, wl_fixed_t surface_y){ + struct seat *seat = data; + struct header_element_data new_focus; + + 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; + } + } +} + +static void +pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial, + uint32_t time, uint32_t button, uint32_t state){ + struct seat *seat = data; + if (seat->pointer_focus && own_proxy(seat->pointer_focus)){ + switch (ctx.active->type) { + case SHADOW: { + 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); + } + }break; + + case HEADER: { + switch (ctx.titlebar_gesture.state){ + case TITLEBAR_GESTURE_STATE_INIT: { + if (state == WL_POINTER_BUTTON_STATE_PRESSED){ + if (button == BTN_RIGHT){ + const int title_height = gtk_widget_get_allocated_height(ctx.header); + xdg_toplevel_show_window_menu(ctx.xdg_toplevel, seat->wl_seat, serial, seat->pointer_x, -title_height); + ctx.titlebar_gesture.state = TITLEBAR_GESTURE_STATE_CONSUMED; + } + else{ + if (button == BTN_LEFT && + ctx.titlebar_gesture.first_pressed_button == BTN_LEFT && + time - ctx.titlebar_gesture.first_pressed_time < (uint32_t)ctx.double_click_time_ms){ + if ((ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE)){ + toggle_maximized(); + } + ctx.titlebar_gesture.state = TITLEBAR_GESTURE_STATE_CONSUMED; + } + else{ + ctx.titlebar_gesture.first_pressed_button = button; + ctx.titlebar_gesture.first_pressed_time = time; + ctx.titlebar_gesture.pressed_x = seat->pointer_x; + ctx.titlebar_gesture.pressed_y = seat->pointer_y; + ctx.titlebar_gesture.pressed_serial = serial; + ctx.titlebar_gesture.state = TITLEBAR_GESTURE_STATE_BUTTON_PRESSED; + } + } + + ctx.titlebar_gesture.button_pressed_count = 1; + + switch (ctx.hdr_focus.type){ + case HEADER_MIN: + case HEADER_MAX: + case HEADER_CLOSE: { + ctx.hdr_focus.state |= GTK_STATE_FLAG_ACTIVE; + draw_title_bar(); + wl_surface_commit(ctx.wl_surface); + }break; + + default: break; + } + } + }break; + + case TITLEBAR_GESTURE_STATE_BUTTON_PRESSED: { + if (state == WL_POINTER_BUTTON_STATE_PRESSED) { + ctx.titlebar_gesture.state = TITLEBAR_GESTURE_STATE_DISCARDED; + ctx.titlebar_gesture.button_pressed_count += 1; + } + else{ + ctx.titlebar_gesture.button_pressed_count -= 1; + + if (ctx.titlebar_gesture.button_pressed_count == 0) { + ctx.titlebar_gesture.state = TITLEBAR_GESTURE_STATE_INIT; + if (ctx.titlebar_gesture.first_pressed_button == button && + button == BTN_LEFT) { + switch (ctx.hdr_focus.type) { + case HEADER_MIN: { + if (ctx.frame_capabilities & LIBDECOR_ACTION_MINIMIZE){ + xdg_toplevel_set_minimized(ctx.xdg_toplevel); + } + }break; + + case HEADER_MAX: { + if ((ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE)){ + toggle_maximized(); + } + }break; + + case HEADER_CLOSE: { + if (ctx.frame_capabilities & LIBDECOR_ACTION_CLOSE){ + ctx.close_signal = 1; + seat->pointer_focus = 0; + } + }break; + + default: break; + } + + ctx.hdr_focus.state &= ~GTK_STATE_FLAG_ACTIVE; + if (GTK_IS_WIDGET(ctx.header)){ + draw_title_bar(); + wl_surface_commit(ctx.wl_surface); + } + } + } + else{ + ctx.hdr_focus.state &= ~GTK_STATE_FLAG_ACTIVE; + if (GTK_IS_WIDGET(ctx.header)) { + draw_title_bar(); + wl_surface_commit(ctx.wl_surface); + } + } + + } + }break; + + case TITLEBAR_GESTURE_STATE_CONSUMED: + case TITLEBAR_GESTURE_STATE_DISCARDED: { + if (state == WL_POINTER_BUTTON_STATE_PRESSED){ + ctx.titlebar_gesture.button_pressed_count++; + } + else{ + ctx.titlebar_gesture.button_pressed_count--; + if (ctx.titlebar_gesture.button_pressed_count == 0) { + ctx.titlebar_gesture.state = TITLEBAR_GESTURE_STATE_INIT; + ctx.titlebar_gesture.first_pressed_button = 0; + } + } + }break; + } + }break; + + default: break; + } + } +} + +static void +pointer_axis(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis, wl_fixed_t value){} + +const struct wl_pointer_listener pointer_listener = { + pointer_enter, + pointer_leave, + pointer_motion, + pointer_button, + pointer_axis +}; + +static void +touch_down(void *data, struct wl_touch *wl_touch, uint32_t serial, + uint32_t time, struct wl_surface *surface, int32_t id, + wl_fixed_t x, wl_fixed_t y){ + struct seat *seat = data; + + if (surface != 0 && own_proxy(surface)){ + + seat->touch_focus = surface; + ctx.touch_active = border_component_from_wl_surface(surface); + + if (ctx.touch_active){ + update_touch_focus(seat, x, y); + + /* update decorations */ + draw_decoration(); + wl_surface_commit(ctx.wl_surface); + + enum libdecor_resize_edge edge = LIBDECOR_RESIZE_EDGE_NONE; + switch (ctx.touch_active->type) { + case SHADOW: { + edge = component_edge(ctx.touch_active, wl_fixed_to_int(x), wl_fixed_to_int(y), SHADOW_MARGIN); + }break; + + case HEADER: { + switch (ctx.hdr_focus.type){ + case HEADER_MIN: + case HEADER_MAX: + case HEADER_CLOSE: { + ctx.hdr_focus.state |= GTK_STATE_FLAG_ACTIVE; + draw_title_bar(); + wl_surface_commit(ctx.wl_surface); + }break; + + default: { + if (time - seat->touch_down_time_stamp < (uint32_t)ctx.double_click_time_ms) { + if ((ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE)){ + toggle_maximized(); + } + } + else{ + if (ctx.frame_capabilities & LIBDECOR_ACTION_MOVE){ + seat->touch_down_time_stamp = time; + libdecor_frame_move(seat->wl_seat, serial); + } + } + }break; + } + }break; + + default: break; + } + + if (edge != LIBDECOR_RESIZE_EDGE_NONE && + (ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE)) { + libdecor_frame_resize(seat->wl_seat, serial, edge); + } + } + } +} + +static void +touch_up(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, int32_t id){ + struct seat *seat = data; + if (seat->touch_focus && own_proxy(seat->touch_focus)){ + if (ctx.touch_active != 0){ + if (ctx.touch_active->type == HEADER){ + switch (ctx.hdr_focus.type) { + case HEADER_MIN: { + if (ctx.frame_capabilities & LIBDECOR_ACTION_MINIMIZE){ + xdg_toplevel_set_minimized(ctx.xdg_toplevel); + } + }break; + + case HEADER_MAX: { + if ((ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE)){ + toggle_maximized(); + } + }break; + + case HEADER_CLOSE: { + if (ctx.frame_capabilities & LIBDECOR_ACTION_CLOSE){ + ctx.close_signal = 1; + seat->touch_focus = 0; + } + }break; + + default: break; + } + + /* unset active/clicked state once released */ + ctx.hdr_focus.state &= ~GTK_STATE_FLAG_ACTIVE; + if (GTK_IS_WIDGET(ctx.header)) { + draw_title_bar(); + wl_surface_commit(ctx.wl_surface); + } + } + + seat->touch_focus = 0; + ctx.touch_active = 0; + ctx.hdr_focus.widget = 0; + ctx.hdr_focus.type = HEADER_NONE; + draw_decoration(); + wl_surface_commit(ctx.wl_surface); + } + } +} + +static void +touch_motion(void *data, struct wl_touch *wl_touch, uint32_t time, + int32_t id, wl_fixed_t x, wl_fixed_t y){ + struct seat *seat = data; + if (seat->touch_focus && own_proxy(seat->touch_focus)){ + update_touch_focus(seat, x, y); + } +} + +static void +touch_frame(void *data, struct wl_touch *wl_touch){} + +static void +touch_cancel(void *data, struct wl_touch *wl_touch){} + +const struct wl_touch_listener touch_listener = { + touch_down, + touch_up, + touch_motion, + touch_frame, + touch_cancel +}; + +static void +seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities){ + struct seat *seat = data; + + if ((capabilities & WL_SEAT_CAPABILITY_POINTER) && !seat->wl_pointer){ + seat->wl_pointer = wl_seat_get_pointer(wl_seat); + wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, seat); + } + else if (!(capabilities & WL_SEAT_CAPABILITY_POINTER) && seat->wl_pointer){ + wl_pointer_release(seat->wl_pointer); + seat->wl_pointer = NULL; + } + + if ((capabilities & WL_SEAT_CAPABILITY_TOUCH) && !seat->wl_touch){ + seat->wl_touch = wl_seat_get_touch(wl_seat); + wl_touch_add_listener(seat->wl_touch, &touch_listener, seat); + } + else if (!(capabilities & WL_SEAT_CAPABILITY_TOUCH) && seat->wl_touch) { + wl_touch_release(seat->wl_touch); + seat->wl_touch = NULL; + } +} + +static void +seat_name(void *data, struct wl_seat *wl_seat, const char *name){ + struct seat *seat = (struct seat*)data; + seat->name = strdup(name); +} + +const struct wl_seat_listener seat_listener = { + seat_capabilities, + seat_name +}; + static void output_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y, @@ -147,9 +563,9 @@ const struct wl_output_listener output_listener = { }; static void -wlevent__wl_registry_global(void *data, struct wl_registry *wl_registry, - uint32_t name, const char *interface, - uint32_t version){ +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)); @@ -192,7 +608,6 @@ wlevent__wl_registry_global(void *data, struct wl_registry *wl_registry, seat = calloc(1, sizeof *seat); seat->cursor_scale = 1; - wl_list_init(&seat->cursor_outputs); wl_list_insert(&ctx.seat_list, &seat->link); seat->wl_seat = wl_registry_bind(ctx.wl_registry, name, &wl_seat_interface, 3); wl_seat_add_listener(seat->wl_seat, &seat_listener, seat); @@ -213,54 +628,176 @@ wlevent__wl_registry_global(void *data, struct wl_registry *wl_registry, } static void -wlevent__wl_registry_global_remove(void *data, struct wl_registry *registry, - uint32_t name){ +wl_registry_global_remove(void *data, struct wl_registry *registry, + uint32_t name){ struct output *output; wl_list_for_each(output, &ctx.output_list, link){ if (output->id == name){ - output_removed(output); + struct seat *seat; + + if (ctx.decoration_type != DECORATION_TYPE_NONE){ + struct surface_output *surface_output; + wl_list_for_each(surface_output, &ctx.shadow.output_list, link) { + if (surface_output->output == output) { + wl_list_remove(&surface_output->link); + free(surface_output); + break; + } + } + } + + wl_list_remove(&output->link); + wl_output_destroy(output->wl_output); + free(output); + break; } } } const struct wl_registry_listener wl_registry_listener = { - wlevent__wl_registry_global, - wlevent__wl_registry_global_remove, + wl_registry_global, + wl_registry_global_remove, }; static void -seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities){ - struct seat *seat = data; +xdg_surface_configure(void *user_data, struct xdg_surface *xdg_surface, uint32_t serial){ + struct libdecor_configuration *configuration; - if ((capabilities & WL_SEAT_CAPABILITY_POINTER) && !seat->wl_pointer){ - seat->wl_pointer = wl_seat_get_pointer(wl_seat); - wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, seat); - } - else if (!(capabilities & WL_SEAT_CAPABILITY_POINTER) && seat->wl_pointer){ - wl_pointer_release(seat->wl_pointer); - seat->wl_pointer = NULL; + configuration = ctx.pending_configuration; + ctx.pending_configuration = 0; + + if (configuration == 0){ + configuration = calloc(1, sizeof *configuration); } - if ((capabilities & WL_SEAT_CAPABILITY_TOUCH) && !seat->wl_touch){ - seat->wl_touch = wl_seat_get_touch(wl_seat); - wl_touch_add_listener(seat->wl_touch, &touch_listener, seat); + configuration->serial = serial; + + { + int w = ctx.w; + int h = ctx.h; + if (libdecor_configuration_get_content_size(configuration, &w, &h)){ + ctx.w = w; + ctx.h = h; + } + if (!ctx.configured){ + ctx.configured = 1; + libdecor_frame_commit(w, h, configuration); + } + else{ + ctx.has_cached_config = 1; + ctx.cached_config = *configuration; + } } - else if (!(capabilities & WL_SEAT_CAPABILITY_TOUCH) && seat->wl_touch) { - wl_touch_release(seat->wl_touch); - seat->wl_touch = NULL; + + free(configuration); +} + +const struct xdg_surface_listener xdg_surface_listener = { + xdg_surface_configure, +}; + +static void +xdg_toplevel_configure(void *user_data, struct xdg_toplevel *xdg_toplevel, + int32_t width, int32_t height, struct wl_array *states){ + enum libdecor_window_state window_state = LIBDECOR_WINDOW_STATE_NONE; + uint32_t *p; + + wl_array_for_each(p, states) { + enum xdg_toplevel_state state = *p; + switch (state) { + case XDG_TOPLEVEL_STATE_FULLSCREEN: window_state |= LIBDECOR_WINDOW_STATE_FULLSCREEN; break; + case XDG_TOPLEVEL_STATE_MAXIMIZED: window_state |= LIBDECOR_WINDOW_STATE_MAXIMIZED; break; + case XDG_TOPLEVEL_STATE_ACTIVATED: window_state |= LIBDECOR_WINDOW_STATE_ACTIVE; break; + case XDG_TOPLEVEL_STATE_TILED_LEFT: window_state |= LIBDECOR_WINDOW_STATE_TILED_LEFT; break; + case XDG_TOPLEVEL_STATE_TILED_RIGHT: window_state |= LIBDECOR_WINDOW_STATE_TILED_RIGHT; break; + case XDG_TOPLEVEL_STATE_TILED_TOP: window_state |= LIBDECOR_WINDOW_STATE_TILED_TOP; break; + case XDG_TOPLEVEL_STATE_TILED_BOTTOM: window_state |= LIBDECOR_WINDOW_STATE_TILED_BOTTOM; break; + case XDG_TOPLEVEL_STATE_RESIZING: window_state |= LIBDECOR_WINDOW_STATE_RESIZING; break; +#ifdef XDG_TOPLEVEL_STATE_SUSPENDED_SINCE_VERSION + case XDG_TOPLEVEL_STATE_SUSPENDED: window_state |= LIBDECOR_WINDOW_STATE_SUSPENDED; break; +#endif +#ifdef XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT_SINCE_VERSION + case XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT: window_state |= LIBDECOR_WINDOW_STATE_CONSTRAINED_LEFT; break; + case XDG_TOPLEVEL_STATE_CONSTRAINED_RIGHT: window_state |= LIBDECOR_WINDOW_STATE_CONSTRAINED_RIGHT; break; + case XDG_TOPLEVEL_STATE_CONSTRAINED_TOP: window_state |= LIBDECOR_WINDOW_STATE_CONSTRAINED_TOP; break; + case XDG_TOPLEVEL_STATE_CONSTRAINED_BOTTOM: window_state |= LIBDECOR_WINDOW_STATE_CONSTRAINED_BOTTOM; break; +#endif + default: break; + } } + + ctx.pending_configuration = calloc(1, sizeof *ctx.pending_configuration); + ctx.pending_configuration->has_size = true; + ctx.pending_configuration->window_width = width; + ctx.pending_configuration->window_height = height; + ctx.pending_configuration->has_window_state = true; + ctx.pending_configuration->window_state = window_state; } static void -seat_name(void *data, struct wl_seat *wl_seat, const char *name){ - struct seat *seat = (struct seat*)data; - seat->name = strdup(name); +xdg_toplevel_close(void *user_data, struct xdg_toplevel *xdg_toplevel){ + ctx.close_signal = 1; } -const struct wl_seat_listener seat_listener = { - seat_capabilities, - seat_name +#ifdef XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION +static void +xdg_toplevel_configure_bounds(void *user_data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height){ + int left = 0, top = 0, right = 0, bottom = 0; + + if (ctx.visible != 0 && + ctx.decoration_mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE){ + libdecor_plugin_gtk_frame_get_border_size(0, &left, &right, &top, &bottom); + } + + width -= left + right; + height -= top + bottom; + // +} +#endif + +#ifdef XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION +static void +xdg_toplevel_wm_capabilities(void *user_data, + struct xdg_toplevel *xdg_toplevel, + struct wl_array *capabilities){ + enum xdg_toplevel_wm_capabilities *wm_cap; + + ctx.wm_capabilities = 0; + + wl_array_for_each(wm_cap, capabilities) { + switch (*wm_cap) { + case XDG_TOPLEVEL_WM_CAPABILITIES_WINDOW_MENU: { + ctx.wm_capabilities |= LIBDECOR_WM_CAPABILITIES_WINDOW_MENU; + }break; + + case XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE: { + ctx.wm_capabilities |= LIBDECOR_WM_CAPABILITIES_MAXIMIZE; + }break; + + case XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN: { + ctx.wm_capabilities |= LIBDECOR_WM_CAPABILITIES_FULLSCREEN; + }break; + + case XDG_TOPLEVEL_WM_CAPABILITIES_MINIMIZE: { + ctx.wm_capabilities |= LIBDECOR_WM_CAPABILITIES_MINIMIZE; + }break; + + default: break; + } + } +} +#endif + +const struct xdg_toplevel_listener xdg_toplevel_listener = { + xdg_toplevel_configure, + xdg_toplevel_close, +#ifdef XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION + xdg_toplevel_configure_bounds, +#endif +#ifdef XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION + xdg_toplevel_wm_capabilities, +#endif }; static void @@ -712,16 +1249,6 @@ constrain_content_size(int *width, int *height){ *height = MIN(*height, lim.max_height); } -static struct libdecor_configuration * -libdecor_configuration_new(void) -{ - struct libdecor_configuration *configuration; - - configuration = calloc(1, sizeof *configuration); - - return configuration; -} - static bool frame_get_window_size_for(struct libdecor_state *state, int *window_width, int *window_height){ *window_width = state->content_width; @@ -796,157 +1323,6 @@ libdecor_configuration_get_content_size(struct libdecor_configuration *configura return true; } -static void -xdg_surface_configure(void *user_data, struct xdg_surface *xdg_surface, uint32_t serial){ - struct libdecor_configuration *configuration; - - configuration = ctx.pending_configuration; - ctx.pending_configuration = 0; - - if (configuration == 0){ - configuration = libdecor_configuration_new(); - } - - configuration->serial = serial; - - { - int w = ctx.w; - int h = ctx.h; - if (libdecor_configuration_get_content_size(configuration, &w, &h)){ - ctx.w = w; - ctx.h = h; - } - if (!ctx.configured){ - ctx.configured = 1; - libdecor_frame_commit(w, h, configuration); - } - else{ - ctx.has_cached_config = 1; - ctx.cached_config = *configuration; - } - } - - free(configuration); -} - -const struct xdg_surface_listener xdg_surface_listener = { - xdg_surface_configure, -}; - -static enum libdecor_window_state -parse_states(struct wl_array *states){ - enum libdecor_window_state pending_state = LIBDECOR_WINDOW_STATE_NONE; - uint32_t *p; - - wl_array_for_each(p, states) { - enum xdg_toplevel_state state = *p; - - switch (state) { - case XDG_TOPLEVEL_STATE_FULLSCREEN: pending_state |= LIBDECOR_WINDOW_STATE_FULLSCREEN; break; - case XDG_TOPLEVEL_STATE_MAXIMIZED: pending_state |= LIBDECOR_WINDOW_STATE_MAXIMIZED; break; - case XDG_TOPLEVEL_STATE_ACTIVATED: pending_state |= LIBDECOR_WINDOW_STATE_ACTIVE; break; - case XDG_TOPLEVEL_STATE_TILED_LEFT: pending_state |= LIBDECOR_WINDOW_STATE_TILED_LEFT; break; - case XDG_TOPLEVEL_STATE_TILED_RIGHT: pending_state |= LIBDECOR_WINDOW_STATE_TILED_RIGHT; break; - case XDG_TOPLEVEL_STATE_TILED_TOP: pending_state |= LIBDECOR_WINDOW_STATE_TILED_TOP; break; - case XDG_TOPLEVEL_STATE_TILED_BOTTOM: pending_state |= LIBDECOR_WINDOW_STATE_TILED_BOTTOM; break; - case XDG_TOPLEVEL_STATE_RESIZING: pending_state |= LIBDECOR_WINDOW_STATE_RESIZING; break; -#ifdef XDG_TOPLEVEL_STATE_SUSPENDED_SINCE_VERSION - case XDG_TOPLEVEL_STATE_SUSPENDED: pending_state |= LIBDECOR_WINDOW_STATE_SUSPENDED; break; -#endif -#ifdef XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT_SINCE_VERSION - case XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT: pending_state |= LIBDECOR_WINDOW_STATE_CONSTRAINED_LEFT; break; - case XDG_TOPLEVEL_STATE_CONSTRAINED_RIGHT: pending_state |= LIBDECOR_WINDOW_STATE_CONSTRAINED_RIGHT; break; - case XDG_TOPLEVEL_STATE_CONSTRAINED_TOP: pending_state |= LIBDECOR_WINDOW_STATE_CONSTRAINED_TOP; break; - case XDG_TOPLEVEL_STATE_CONSTRAINED_BOTTOM: pending_state |= LIBDECOR_WINDOW_STATE_CONSTRAINED_BOTTOM; break; -#endif - - default: break; - } - } - - return pending_state; -} - -static void -xdg_toplevel_configure(void *user_data, struct xdg_toplevel *xdg_toplevel, - int32_t width, int32_t height, struct wl_array *states){ - enum libdecor_window_state window_state; - - window_state = parse_states(states); - - ctx.pending_configuration = libdecor_configuration_new(); - ctx.pending_configuration->has_size = true; - ctx.pending_configuration->window_width = width; - ctx.pending_configuration->window_height = height; - ctx.pending_configuration->has_window_state = true; - ctx.pending_configuration->window_state = window_state; -} - -static void -xdg_toplevel_close(void *user_data, struct xdg_toplevel *xdg_toplevel){ - ctx.close_signal = 1; -} - -#ifdef XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION -static void -xdg_toplevel_configure_bounds(void *user_data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height){ - int left = 0, top = 0, right = 0, bottom = 0; - - if (ctx.visible != 0 && - ctx.decoration_mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE){ - libdecor_plugin_gtk_frame_get_border_size(0, &left, &right, &top, &bottom); - } - - width -= left + right; - height -= top + bottom; - // -} -#endif - -#ifdef XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION -static void -xdg_toplevel_wm_capabilities(void *user_data, - struct xdg_toplevel *xdg_toplevel, - struct wl_array *capabilities){ - enum xdg_toplevel_wm_capabilities *wm_cap; - - ctx.wm_capabilities = 0; - - wl_array_for_each(wm_cap, capabilities) { - switch (*wm_cap) { - case XDG_TOPLEVEL_WM_CAPABILITIES_WINDOW_MENU: { - ctx.wm_capabilities |= LIBDECOR_WM_CAPABILITIES_WINDOW_MENU; - }break; - - case XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE: { - ctx.wm_capabilities |= LIBDECOR_WM_CAPABILITIES_MAXIMIZE; - }break; - - case XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN: { - ctx.wm_capabilities |= LIBDECOR_WM_CAPABILITIES_FULLSCREEN; - }break; - - case XDG_TOPLEVEL_WM_CAPABILITIES_MINIMIZE: { - ctx.wm_capabilities |= LIBDECOR_WM_CAPABILITIES_MINIMIZE; - }break; - - default: break; - } - } -} -#endif - -const struct xdg_toplevel_listener xdg_toplevel_listener = { - xdg_toplevel_configure, - xdg_toplevel_close, -#ifdef XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION - xdg_toplevel_configure_bounds, -#endif -#ifdef XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION - xdg_toplevel_wm_capabilities, -#endif -}; - void libdecor_frame_set_visibility(bool visible){ ctx.visible = visible; @@ -1162,7 +1538,6 @@ cleanup(void){ { struct seat *seat, *seat_tmp; wl_list_for_each_safe(seat, seat_tmp, &ctx.seat_list, link) { - struct cursor_output *cursor_output, *tmp; if (seat->wl_pointer){ wl_pointer_destroy(seat->wl_pointer); @@ -1178,11 +1553,6 @@ cleanup(void){ wl_cursor_theme_destroy(seat->cursor_theme); } - wl_list_for_each_safe(cursor_output, tmp, &seat->cursor_outputs, link) { - wl_list_remove(&cursor_output->link); - free(cursor_output); - } - free(seat->name); free(seat); } @@ -2471,58 +2841,6 @@ libdecor_plugin_gtk_frame_get_border_size(enum libdecor_window_state window_stat } } -static void -cursor_surface_enter(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output){ - struct seat *seat = data; - if (own_proxy(wl_output)) { - struct cursor_output *cursor_output; - cursor_output = calloc(1, sizeof *cursor_output); - cursor_output->output = wl_output_get_user_data(wl_output); - wl_list_insert(&seat->cursor_outputs, &cursor_output->link); - - if (update_local_cursor(seat)){ - send_cursor(seat); - } - } -} - -static void -cursor_surface_leave(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output){ - struct seat *seat = data; - - if (own_proxy(wl_output)){ - struct cursor_output *cursor_output, *tmp; - wl_list_for_each_safe(cursor_output, tmp, &seat->cursor_outputs, link){ - if (cursor_output->output->wl_output == wl_output){ - wl_list_remove(&cursor_output->link); - free(cursor_output); - } - } - - if (update_local_cursor(seat)){ - send_cursor(seat); - } - } -} - -static struct wl_surface_listener cursor_surface_listener = { - cursor_surface_enter, - cursor_surface_leave, -}; - -static void -ensure_cursor_surface(struct seat *seat){ - struct wl_compositor *wl_compositor = ctx.wl_compositor; - - if (seat->cursor_surface){ - return; - } - - seat->cursor_surface = wl_compositor_create_surface(wl_compositor); - wl_surface_add_listener(seat->cursor_surface, - &cursor_surface_listener, seat); -} - enum libdecor_resize_edge component_edge(const struct border_component *cmpnt, const int pointer_x, const int pointer_y, @@ -2575,11 +2893,6 @@ update_local_cursor(struct seat *seat){ bool theme_updated = false; { int scale = 1; - struct cursor_output *cursor_output; - wl_list_for_each(cursor_output, &seat->cursor_outputs, link){ - scale = MAX(scale, cursor_output->output->scale); - } - if (seat->cursor_theme == 0 || seat->cursor_scale != scale){ struct wl_cursor_theme *theme; @@ -2648,269 +2961,6 @@ send_cursor(struct seat *seat){ } } -static void -pointer_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, - struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y){ - if (surface){ - struct seat *seat = data; - - bool is_own_surface = own_proxy(surface); - if (is_own_surface || ctx.handle_cursor){ - ensure_cursor_surface(seat); - seat->pointer_x = wl_fixed_to_int(surface_x); - seat->pointer_y = wl_fixed_to_int(surface_y); - seat->serial = serial; - seat->pointer_focus = surface; - } - - if (is_own_surface){ - ctx.active = border_component_from_wl_surface(surface); - if (ctx.active){ - draw_decoration(); - wl_surface_commit(ctx.wl_surface); - } - update_local_cursor(seat); - send_cursor(seat); - } - } -} - -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 = 0; - - if (surface != 0 && own_proxy(surface)){ - ctx.titlebar_gesture.state = TITLEBAR_GESTURE_STATE_INIT; - ctx.titlebar_gesture.first_pressed_button = 0; - - ctx.active = 0; - ctx.hdr_focus.widget = 0; - ctx.hdr_focus.type = HEADER_NONE; - draw_decoration(); - wl_surface_commit(ctx.wl_surface); - update_local_cursor(seat); - } -} - -static void -pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, - wl_fixed_t surface_x, wl_fixed_t surface_y){ - struct seat *seat = data; - struct header_element_data new_focus; - - 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; - } - } -} - -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 = - 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); - } -} - -static void -handle_titlebar_gesture(struct seat *seat, uint32_t serial, enum titlebar_gesture gesture){ - switch (gesture){ - case TITLEBAR_GESTURE_DOUBLE_CLICK: { - if ((ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE)){ - toggle_maximized(); - } - }break; - - case TITLEBAR_GESTURE_MIDDLE_CLICK: break; - - case TITLEBAR_GESTURE_RIGHT_CLICK: { - const int title_height = gtk_widget_get_allocated_height(ctx.header); - xdg_toplevel_show_window_menu(ctx.xdg_toplevel, seat->wl_seat, serial, seat->pointer_x, -title_height); - }break; - } -} - -static void -handle_button_on_header(struct seat *seat, uint32_t serial, uint32_t time, uint32_t button, uint32_t state){ - switch (ctx.titlebar_gesture.state){ - case TITLEBAR_GESTURE_STATE_INIT: { - if (state == WL_POINTER_BUTTON_STATE_PRESSED){ - if (button == BTN_RIGHT){ - handle_titlebar_gesture(seat, serial, TITLEBAR_GESTURE_RIGHT_CLICK); - ctx.titlebar_gesture.state = TITLEBAR_GESTURE_STATE_CONSUMED; - } - else{ - if (button == BTN_LEFT && - ctx.titlebar_gesture.first_pressed_button == BTN_LEFT && - time - ctx.titlebar_gesture.first_pressed_time < (uint32_t)ctx.double_click_time_ms){ - handle_titlebar_gesture(seat, serial, TITLEBAR_GESTURE_DOUBLE_CLICK); - ctx.titlebar_gesture.state = TITLEBAR_GESTURE_STATE_CONSUMED; - } - else{ - ctx.titlebar_gesture.first_pressed_button = button; - ctx.titlebar_gesture.first_pressed_time = time; - ctx.titlebar_gesture.pressed_x = seat->pointer_x; - ctx.titlebar_gesture.pressed_y = seat->pointer_y; - ctx.titlebar_gesture.pressed_serial = serial; - ctx.titlebar_gesture.state = TITLEBAR_GESTURE_STATE_BUTTON_PRESSED; - } - } - - ctx.titlebar_gesture.button_pressed_count = 1; - - switch (ctx.hdr_focus.type){ - case HEADER_MIN: - case HEADER_MAX: - case HEADER_CLOSE: { - ctx.hdr_focus.state |= GTK_STATE_FLAG_ACTIVE; - draw_title_bar(); - wl_surface_commit(ctx.wl_surface); - }break; - - default: break; - } - } - }break; - - case TITLEBAR_GESTURE_STATE_BUTTON_PRESSED: { - if (state == WL_POINTER_BUTTON_STATE_PRESSED) { - ctx.titlebar_gesture.state = TITLEBAR_GESTURE_STATE_DISCARDED; - ctx.titlebar_gesture.button_pressed_count += 1; - } - else{ - ctx.titlebar_gesture.button_pressed_count -= 1; - - if (ctx.titlebar_gesture.button_pressed_count == 0) { - ctx.titlebar_gesture.state = TITLEBAR_GESTURE_STATE_INIT; - if (ctx.titlebar_gesture.first_pressed_button == button && - button == BTN_LEFT) { - switch (ctx.hdr_focus.type) { - case HEADER_MIN: { - if (ctx.frame_capabilities & LIBDECOR_ACTION_MINIMIZE){ - xdg_toplevel_set_minimized(ctx.xdg_toplevel); - } - }break; - - case HEADER_MAX: { - if ((ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE)){ - toggle_maximized(); - } - }break; - - case HEADER_CLOSE: { - if (ctx.frame_capabilities & LIBDECOR_ACTION_CLOSE){ - xdg_toplevel_close(0, ctx.xdg_toplevel); - seat->pointer_focus = 0; - } - }break; - - default: break; - } - - ctx.hdr_focus.state &= ~GTK_STATE_FLAG_ACTIVE; - if (GTK_IS_WIDGET(ctx.header)){ - draw_title_bar(); - wl_surface_commit(ctx.wl_surface); - } - } - } - else{ - ctx.hdr_focus.state &= ~GTK_STATE_FLAG_ACTIVE; - if (GTK_IS_WIDGET(ctx.header)) { - draw_title_bar(); - wl_surface_commit(ctx.wl_surface); - } - } - - } - }break; - - case TITLEBAR_GESTURE_STATE_CONSUMED: - case TITLEBAR_GESTURE_STATE_DISCARDED: { - if (state == WL_POINTER_BUTTON_STATE_PRESSED){ - ctx.titlebar_gesture.button_pressed_count++; - } - else{ - ctx.titlebar_gesture.button_pressed_count--; - if (ctx.titlebar_gesture.button_pressed_count == 0) { - ctx.titlebar_gesture.state = TITLEBAR_GESTURE_STATE_INIT; - ctx.titlebar_gesture.first_pressed_button = 0; - } - } - }break; - } -} - -static void -pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial, - uint32_t time, uint32_t button, uint32_t state){ - struct seat *seat = data; - if (seat->pointer_focus && own_proxy(seat->pointer_focus)){ - switch (ctx.active->type) { - case SHADOW: { - handle_button_on_shadow(seat, serial, time, button, state); - }break; - - case HEADER: { - handle_button_on_header(seat, serial, time, button, state); - }break; - - default: break; - } - } -} - -static void -pointer_axis(void *data, struct wl_pointer *wl_pointer, - uint32_t time, uint32_t axis, wl_fixed_t value){} - -const struct wl_pointer_listener pointer_listener = { - pointer_enter, - pointer_leave, - pointer_motion, - pointer_button, - pointer_axis -}; - static void update_touch_focus(struct seat *seat, wl_fixed_t x, wl_fixed_t y){ if (GTK_IS_WIDGET(ctx.header) && ctx.touch_active->type == HEADER){ @@ -2927,171 +2977,6 @@ update_touch_focus(struct seat *seat, wl_fixed_t x, wl_fixed_t y){ } } -static void -touch_down(void *data, struct wl_touch *wl_touch, uint32_t serial, - uint32_t time, struct wl_surface *surface, int32_t id, - wl_fixed_t x, wl_fixed_t y){ - struct seat *seat = data; - - if (surface != 0 && own_proxy(surface)){ - - seat->touch_focus = surface; - ctx.touch_active = border_component_from_wl_surface(surface); - - if (ctx.touch_active){ - update_touch_focus(seat, x, y); - - /* update decorations */ - draw_decoration(); - wl_surface_commit(ctx.wl_surface); - - enum libdecor_resize_edge edge = LIBDECOR_RESIZE_EDGE_NONE; - switch (ctx.touch_active->type) { - case SHADOW: { - edge = component_edge(ctx.touch_active, wl_fixed_to_int(x), wl_fixed_to_int(y), SHADOW_MARGIN); - }break; - - case HEADER: { - switch (ctx.hdr_focus.type){ - case HEADER_MIN: - case HEADER_MAX: - case HEADER_CLOSE: { - ctx.hdr_focus.state |= GTK_STATE_FLAG_ACTIVE; - draw_title_bar(); - wl_surface_commit(ctx.wl_surface); - }break; - - default: { - if (time - seat->touch_down_time_stamp < (uint32_t)ctx.double_click_time_ms) { - if ((ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE)){ - toggle_maximized(); - } - } - else{ - if (ctx.frame_capabilities & LIBDECOR_ACTION_MOVE){ - seat->touch_down_time_stamp = time; - libdecor_frame_move(seat->wl_seat, serial); - } - } - }break; - } - }break; - - default: break; - } - - if (edge != LIBDECOR_RESIZE_EDGE_NONE && - (ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE)) { - libdecor_frame_resize(seat->wl_seat, serial, edge); - } - } - } -} - -static void -touch_up(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, int32_t id){ - struct seat *seat = data; - if (seat->touch_focus && own_proxy(seat->touch_focus)){ - if (ctx.touch_active != 0){ - if (ctx.touch_active->type == HEADER){ - switch (ctx.hdr_focus.type) { - case HEADER_MIN: { - if (ctx.frame_capabilities & LIBDECOR_ACTION_MINIMIZE){ - xdg_toplevel_set_minimized(ctx.xdg_toplevel); - } - }break; - - case HEADER_MAX: { - if ((ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE)){ - toggle_maximized(); - } - }break; - - case HEADER_CLOSE: { - if (ctx.frame_capabilities & LIBDECOR_ACTION_CLOSE){ - xdg_toplevel_close(0, ctx.xdg_toplevel); - seat->touch_focus = 0; - } - }break; - - default: break; - } - - /* unset active/clicked state once released */ - ctx.hdr_focus.state &= ~GTK_STATE_FLAG_ACTIVE; - if (GTK_IS_WIDGET(ctx.header)) { - draw_title_bar(); - wl_surface_commit(ctx.wl_surface); - } - } - - seat->touch_focus = 0; - ctx.touch_active = 0; - ctx.hdr_focus.widget = 0; - ctx.hdr_focus.type = HEADER_NONE; - draw_decoration(); - wl_surface_commit(ctx.wl_surface); - } - } -} - -static void -touch_motion(void *data, struct wl_touch *wl_touch, uint32_t time, - int32_t id, wl_fixed_t x, wl_fixed_t y){ - struct seat *seat = data; - if (seat->touch_focus && own_proxy(seat->touch_focus)){ - update_touch_focus(seat, x, y); - } -} - -static void -touch_frame(void *data, struct wl_touch *wl_touch){} - -static void -touch_cancel(void *data, struct wl_touch *wl_touch){} - -const struct wl_touch_listener touch_listener = { - touch_down, - touch_up, - touch_motion, - touch_frame, - touch_cancel -}; - -static void -remove_surface_outputs(struct border_component *cmpnt, const struct output *output){ - struct surface_output *surface_output; - wl_list_for_each(surface_output, &cmpnt->output_list, link) { - if (surface_output->output == output) { - wl_list_remove(&surface_output->link); - free(surface_output); - break; - } - } -} - -static void -output_removed(struct output *output){ - struct seat *seat; - - if (ctx.decoration_type != DECORATION_TYPE_NONE){ - remove_surface_outputs(&ctx.shadow, output); - } - wl_list_for_each(seat, &ctx.seat_list, link) { - struct cursor_output *cursor_output; - wl_list_for_each(cursor_output, &seat->cursor_outputs, link) { - if (cursor_output->output == output) { - wl_list_remove(&cursor_output->link); - free(cursor_output); - } - } - } - - wl_list_remove(&output->link); - wl_output_destroy(output->wl_output); - free(output); -} - //#include "desktop-settings.c" static bool diff --git a/digesting_libdecor.h b/digesting_libdecor.h index ce349d9..5a7d1ad 100644 --- a/digesting_libdecor.h +++ b/digesting_libdecor.h @@ -223,7 +223,6 @@ struct seat { struct wl_surface *cursor_surface; struct wl_cursor *current_cursor; int cursor_scale; - struct wl_list cursor_outputs; struct wl_cursor_theme *cursor_theme; /* cursors for resize edges and corners */ @@ -271,11 +270,6 @@ struct surface_output { struct wl_list link; }; -struct cursor_output { - struct output *output; - struct wl_list link; -}; - enum titlebar_gesture { TITLEBAR_GESTURE_DOUBLE_CLICK, TITLEBAR_GESTURE_MIDDLE_CLICK, @@ -320,12 +314,7 @@ static void init_shell_surface(void); static void do_map(void); -//#include "plugins/gtk/libdecor-gtk.c" - - -static void init_wl_output( uint32_t id, uint32_t version); - -static void output_removed(struct output *output); +// #include "plugins/gtk/libdecor-gtk.c" static const char *libdecor_gtk_proxy_tag = "libdecor-gtk"; @@ -342,6 +331,14 @@ static void send_cursor(struct seat *seat); static void buffer_free(struct buffer *buffer); static void draw_border_component(struct border_component *border_component); +static bool own_proxy(void *proxy); +static struct border_component * border_component_from_wl_surface(const struct wl_surface *surface); +static struct header_element_data get_header_focus(const GtkHeaderBar *header_bar, const int x, const int y); +static void draw_title_bar(void); +enum libdecor_resize_edge component_edge(const struct border_component *cmpnt, const int pointer_x, const int pointer_y, const int margin); +static void toggle_maximized(void); +static void update_touch_focus(struct seat *seat, wl_fixed_t x, wl_fixed_t y); + // digesting_libdecor typedef struct Ctx{