From e0584cc5eac06b93be1c18a06e19ad99d52d461f Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Fri, 6 Mar 2026 14:53:27 -0800 Subject: [PATCH] [wayland_gtk_egl] full feature set up and running, some steps towards multi-seat support (not tested) --- wayland_gtk_egl.c | 471 ++++++++++++++++++++++++++-------------------- wayland_gtk_egl.h | 16 +- 2 files changed, 285 insertions(+), 202 deletions(-) diff --git a/wayland_gtk_egl.c b/wayland_gtk_egl.c index f420168..4d32e9c 100755 --- a/wayland_gtk_egl.c +++ b/wayland_gtk_egl.c @@ -85,25 +85,22 @@ static const struct xdg_wm_base_listener xdg_wm_base_listener = { static void pointer_enter(void *udata, struct wl_pointer *wl_pointer, CSD_U32 serial, struct wl_surface *surface, wl_fixed_t fx, wl_fixed_t fy){ + CSD_Seat *seat = &ctx.seat; CSD_Window *window = &ctx.window; CSD_GTK_Window *gtk_window = &ctx.gtk_window; CSD_S32 surface_off[2] = {0}; - if (surface == window->main_wl_surface){ - // surface_off = {0,0} + if (csd_gtk_calc_surface_off(gtk_window, surface, surface_off)){ + // handled by gtk frame } - else if (surface == gtk_window->titlebar.wl_surface){ - memcpy(surface_off, gtk_window->titlebar.p, sizeof(surface_off)); - } - else if (surface == gtk_window->shadow.wl_surface){ - memcpy(surface_off, gtk_window->shadow.p, sizeof(surface_off)); + else if (surface == window->main_wl_surface){ + // app's surface_off = {0,0} } - CSD_Seat *seat = &ctx.seat; seat->hover_surface = surface; + seat->serial = serial; seat->hover_p[0] = surface_off[0] + wl_fixed_to_int(fx); seat->hover_p[1] = surface_off[1] + wl_fixed_to_int(fy); - seat->serial = serial; } static void @@ -117,20 +114,16 @@ pointer_leave(void *udata, struct wl_pointer *wl_pointer, static void pointer_motion(void *udata, struct wl_pointer *wl_pointer, CSD_U32 time, wl_fixed_t fx, wl_fixed_t fy){ + CSD_Seat *seat = &ctx.seat; CSD_Window *window = &ctx.window; CSD_GTK_Window *gtk_window = &ctx.gtk_window; - CSD_Seat *seat = &ctx.seat; - CSD_S32 surface_off[2] = {0}; - if (seat->hover_surface == window->main_wl_surface){ - // surface_off = {0,0} + if (csd_gtk_calc_surface_off(gtk_window, seat->hover_surface, surface_off)){ + // handled by gtk frame } - else if (seat->hover_surface == gtk_window->titlebar.wl_surface){ - memcpy(surface_off, gtk_window->titlebar.p, sizeof(surface_off)); - } - else if (seat->hover_surface == gtk_window->shadow.wl_surface){ - memcpy(surface_off, gtk_window->shadow.p, sizeof(surface_off)); + else if (seat->hover_surface == window->main_wl_surface){ + // app's surface_off = {0,0} } seat->hover_p[0] = surface_off[0] + wl_fixed_to_int(fx); @@ -154,7 +147,7 @@ pointer_button(void *udata, struct wl_pointer *wl_pointer, static void pointer_axis(void *udata, struct wl_pointer *wl_pointer, CSD_U32 time, CSD_U32 axis, wl_fixed_t fv){ - int v = wl_fixed_to_int(fv); + CSD_S32 v = wl_fixed_to_int(fv); } static const struct wl_pointer_listener pointer_listener = { @@ -217,7 +210,8 @@ registry_global(void *udata, struct wl_registry *wl_registry, else if (strcmp(interface, "wl_seat") == 0){ CSD_Seat *seat = &ctx.seat; if (seat->wl_seat == 0){ - seat->wl_seat = wl_registry_bind(ctx.wl_registry, name, &wl_seat_interface, 3); + seat->wl_seat = wl_registry_bind(ctx.wl_registry, name, + &wl_seat_interface, 3); wl_seat_add_listener(seat->wl_seat, &seat_listener, 0); seat->cursor_surface = wl_compositor_create_surface(ctx.wl_compositor); } @@ -246,7 +240,8 @@ static const struct xdg_surface_listener xdg_surface_listener = { static void xdg_toplevel_configure(void *udata, struct xdg_toplevel *xdg_toplevel, - int32_t width, int32_t height, struct wl_array *states){ + int32_t width, int32_t height, + struct wl_array *states){ CSD_Window *window = &ctx.window; if (width != 0 && height != 0){ window->config_staged.dim[0] = width; @@ -353,42 +348,18 @@ int main(){ /* create a window */ { /* window main surface */ - CSD_Window *window = &ctx.window; - window->main_wl_surface = wl_compositor_create_surface(ctx.wl_compositor); - window->main_xdg_surface = xdg_wm_base_get_xdg_surface(ctx.xdg_wm_base, window->main_wl_surface); - xdg_surface_add_listener(window->main_xdg_surface, &xdg_surface_listener, 0); - window->main_xdg_toplevel = xdg_surface_get_toplevel(window->main_xdg_surface); - xdg_toplevel_add_listener(window->main_xdg_toplevel, &xdg_toplevel_listener, 0); - - window->control_flags = ~0; - - window->dim[0] = 640; - window->dim[1] = 480; - window->config_staged.decoration_mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE; - if (ctx.zxdg_decoration_manager != 0){ - window->main_zxdg_toplevel_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(ctx.zxdg_decoration_manager, window->main_xdg_toplevel); - zxdg_toplevel_decoration_v1_add_listener(window->main_zxdg_toplevel_decoration, &zxdg_toplevel_decoration_listener, 0); - } - - for (int k = 0; k < 2; k += 1){ - window->mmbox[k][0] = 0; - window->mmbox[k][1] = (1 << 30); - } - - xdg_toplevel_set_app_id(window->main_xdg_toplevel, "demo"); - xdg_toplevel_set_title(window->main_xdg_toplevel, "Example Window"); - wl_surface_commit(window->main_wl_surface); - - /* window subsurface */ - ctx.gtk_window.shadow = csd_subsurface_new(); - ctx.gtk_window.titlebar = csd_subsurface_new(); + csd_window_init(&ctx.window); /* window gtk */ - csd_gtk_window_init(); - - /* window egl */ + csd_gtk_window_init(&ctx.gtk_window); + } + + /* window egl */ + { + CSD_Window *window = &ctx.window; ctx.main_wl_egl_window = wl_egl_window_create(window->main_wl_surface, - window->dim[0], window->dim[1]); + window->dim[0], + window->dim[1]); EGLConfig configs[64]; EGLint config_cap = sizeof(configs)/sizeof(*configs); @@ -406,7 +377,8 @@ int main(){ EGL_STENCIL_SIZE, 8, EGL_NONE, }; - eglChooseConfig(ctx.egl_display, attributes, configs, config_cap, &config_count); + eglChooseConfig(ctx.egl_display, attributes, + configs, config_cap, &config_count); } { @@ -415,7 +387,9 @@ int main(){ EGL_NONE, }; for (EGLint i = 0; i < config_count; i += 1){ - ctx.main_egl_surface = eglCreateWindowSurface(ctx.egl_display, configs[i], ctx.main_wl_egl_window, attributes); + ctx.main_egl_surface = + eglCreateWindowSurface(ctx.egl_display, configs[i], + ctx.main_wl_egl_window, attributes); if (ctx.main_egl_surface != EGL_NO_SURFACE){ break; } @@ -468,75 +442,29 @@ int main(){ } } - { - CSD_Window *window = &ctx.window; - - /* apply config */ - if (window->config.serial != window->config_staged.serial){ - window->config = window->config_staged; - xdg_surface_ack_configure(window->main_xdg_surface, window->config.serial); - } - - int csd = (window->config.decoration_mode == - ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE); - - /* window sizing */ - memset(&window->csd_frame, 0, sizeof window->csd_frame); - memset(window->csd_dim, 0, sizeof window->csd_dim); - if (csd){ - window->csd_frame = csd_gtk_calculate_frame(); - } - for (int i = 0; i < 2; i += 1){ - window->csd_dim[i] = window->csd_frame.border[i][0] + window->csd_frame.border[i][1]; - } - for (int i = 0; i < 2; i += 1){ - int32_t d = window->config.dim[i] - window->csd_dim[i]; - if (!window->handled_first_size){ - d = window->dim[i]; - window->config.dim[i] = d + window->csd_dim[i]; - } - d = CSD_ClampBot(d, window->mmbox[i][0]); - d = CSD_ClampTop(d, window->mmbox[i][1]); - d = CSD_ClampBot(d, window->csd_frame.minbox[i]); - window->dim[i] = d; - } - window->handled_first_size = 1; - - /* window size commit */ - if (!(window->control_flags & CSD_WindowControlFlag_Resize)){ - xdg_toplevel_set_min_size(window->main_xdg_toplevel, - window->dim[0], window->dim[1]); - xdg_toplevel_set_max_size(window->main_xdg_toplevel, - window->dim[0], window->dim[1]); - } - else{ - for (int i = 0; i < 2; i += 1){ - int32_t mw = window->csd_dim[0] + CSD_ClampBot(window->mmbox[0][i], - window->csd_frame.minbox[i]); - int32_t mh = window->mmbox[1][i] + window->csd_dim[1]; - if (i == 0){ - xdg_toplevel_set_min_size(window->main_xdg_toplevel, mw, mh); - } - else{ - xdg_toplevel_set_max_size(window->main_xdg_toplevel, mw, mh); - } - } - } - xdg_surface_set_window_geometry(window->main_xdg_surface, - -window->csd_frame.border[0][0], - -window->csd_frame.border[1][0], - window->dim[0] + window->csd_dim[0], - window->dim[1] + window->csd_dim[1]); - wl_egl_window_resize(ctx.main_wl_egl_window, - window->dim[0], window->dim[1], 0, 0); + /* setup seats list for frame */ + CSD_Seat *seats[] = {&ctx.seat}; + CSD_U32 seat_count = 1; + + for (CSD_U32 si = 0; si < seat_count; si += 1){ + seats[si]->cursor_shape = CSD_CursorShape_Hidden; } + /* apply new window config */ + csd_window_apply_new_config(&ctx.window); + + /* calculate csd frame */ + CSD_Frame csd_frame = csd_gtk_calc_frame(&ctx.window, &ctx.gtk_window); + + /* window size update */ + csd_window_size_update(&ctx.window, &csd_frame); + + /* egl size update */ + wl_egl_window_resize(ctx.main_wl_egl_window, + ctx.window.dim[0], ctx.window.dim[1], 0, 0); + /* frame update and render */ - { - CSD_Seat *seat = &ctx.seat; - seat->cursor_shape = CSD_CursorShape_Pointer; - csd_gtk_update_and_render(); - } + csd_gtk_update_and_render(&ctx.window, &ctx.gtk_window, seats, seat_count); /* app update & render */ { @@ -544,6 +472,19 @@ int main(){ if (ctx.close_signal){ exit_loop = 1; } + else if (ctx.minimize_signal){ + ctx.minimize_signal = 0; + xdg_toplevel_set_minimized(window->main_xdg_toplevel); + } + else if (ctx.maximize_signal){ + ctx.maximize_signal = 0; + if (window->config.flags & CSD_WindowFlag_IsMax){ + xdg_toplevel_unset_maximized(window->main_xdg_toplevel); + } + else{ + xdg_toplevel_set_maximized(window->main_xdg_toplevel); + } + } glDrawBuffer(GL_BACK); glViewport(0, 0, window->dim[0], window->dim[1]); @@ -560,7 +501,6 @@ int main(){ /* commit new cursor */ { CSD_Seat *seat = &ctx.seat; - CSD_Window *window = &ctx.window; struct wl_cursor *cursor = ctx.wl_cursors[seat->cursor_shape]; if (cursor != 0){ struct wl_cursor_image *cursor_image = cursor->images[0]; @@ -583,6 +523,103 @@ int main(){ /* csd helpers */ +static void +csd_window_init(CSD_Window *window){ + window->main_wl_surface = wl_compositor_create_surface(ctx.wl_compositor); + window->main_xdg_surface = xdg_wm_base_get_xdg_surface(ctx.xdg_wm_base, window->main_wl_surface); + xdg_surface_add_listener(window->main_xdg_surface, &xdg_surface_listener, 0); + window->main_xdg_toplevel = xdg_surface_get_toplevel(window->main_xdg_surface); + xdg_toplevel_add_listener(window->main_xdg_toplevel, &xdg_toplevel_listener, 0); + + window->control_flags = ~0; + + window->dim[0] = 640; + window->dim[1] = 480; + window->config_staged.decoration_mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE; + if (ctx.zxdg_decoration_manager != 0){ + window->main_zxdg_toplevel_decoration = + zxdg_decoration_manager_v1_get_toplevel_decoration(ctx.zxdg_decoration_manager, + window->main_xdg_toplevel); + zxdg_toplevel_decoration_v1_add_listener(window->main_zxdg_toplevel_decoration, + &zxdg_toplevel_decoration_listener, 0); + } + + for (int k = 0; k < 2; k += 1){ + window->mmbox[k][0] = 1; + window->mmbox[k][1] = (1 << 30); + } + + xdg_toplevel_set_app_id(window->main_xdg_toplevel, "demo"); + xdg_toplevel_set_title(window->main_xdg_toplevel, "Example Window"); + wl_surface_commit(window->main_wl_surface); +} + +static void +csd_window_apply_new_config(CSD_Window *window){ + if (window->config.serial != window->config_staged.serial){ + window->config = window->config_staged; + xdg_surface_ack_configure(window->main_xdg_surface, window->config.serial); + } +} + +static void +csd_window_size_update(CSD_Window *window, CSD_Frame *csd_frame){ + /* window sizing */ + memset(&window->csd_frame, 0, sizeof window->csd_frame); + memset(window->csd_dim, 0, sizeof window->csd_dim); + if (window->config.decoration_mode == + ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE){ + window->csd_frame = *csd_frame; + for (CSD_U32 i = 0; i < 2; i += 1){ + window->csd_dim[i] = (csd_frame->border[i][0] + + csd_frame->border[i][1]); + } + } + for (CSD_U32 i = 0; i < 2; i += 1){ + int32_t d = window->config.dim[i] - window->csd_dim[i]; + if (!window->handled_first_size){ + d = window->dim[i]; + window->config.dim[i] = d + window->csd_dim[i]; + } + d = CSD_ClampBot(d, window->mmbox[i][0]); + d = CSD_ClampTop(d, window->mmbox[i][1]); + d = CSD_ClampBot(d, window->csd_frame.minbox[i]); + window->dim[i] = d; + } + window->handled_first_size = 1; + + /* window size commit */ + if (!(window->control_flags & CSD_WindowControlFlag_Resize)){ + xdg_toplevel_set_min_size(window->main_xdg_toplevel, + window->dim[0], window->dim[1]); + xdg_toplevel_set_max_size(window->main_xdg_toplevel, + window->dim[0], window->dim[1]); + } + else{ + for (CSD_S32 i = 0; i < 2; i += 1){ + CSD_S32 m[2]; + for (CSD_S32 k = 0; k < 2; k += 1){ + m[k] = window->mmbox[k][i]; + if (i == 0){ + m[k] = CSD_ClampBot(m[k], window->csd_frame.minbox[k]); + } + m[k] += window->csd_dim[k]; + } + if (i == 0){ + xdg_toplevel_set_min_size(window->main_xdg_toplevel, m[0], m[1]); + } + else{ + xdg_toplevel_set_max_size(window->main_xdg_toplevel, m[0], m[1]); + } + } + } + xdg_surface_set_window_geometry(window->main_xdg_surface, + -window->csd_frame.border[0][0], + -window->csd_frame.border[1][0], + window->dim[0] + window->csd_dim[0], + window->dim[1] + window->csd_dim[1]); +} + static CSD_SubSurface csd_subsurface_new(void){ CSD_Window *window = &ctx.window; @@ -957,8 +994,9 @@ csd_gtk_init(void){ } static void -csd_gtk_window_init(void){ - CSD_GTK_Window *gtk_window = &ctx.gtk_window; +csd_gtk_window_init(CSD_GTK_Window *gtk_window){ + gtk_window->shadow = csd_subsurface_new(); + gtk_window->titlebar = csd_subsurface_new(); gtk_window->header = gtk_header_bar_new(); gtk_window->window = gtk_offscreen_window_new(); @@ -981,11 +1019,9 @@ csd_gtk_window_init(void){ } static CSD_Frame -csd_gtk_calculate_frame(void){ - CSD_Window *window = &ctx.window; - CSD_GTK_Window *gtk_window = &ctx.gtk_window; +csd_gtk_calc_frame(CSD_Window *window, CSD_GTK_Window *gtk_window){ CSD_Frame frame = {0}; - bool show_title = (!(window->config.flags & CSD_WindowFlag_IsFullscreen)); + CSD_B32 show_title = (!(window->config.flags & CSD_WindowFlag_IsFullscreen)); if (show_title){ gtk_widget_get_preferred_height(gtk_window->header, 0, &frame.border[1][0]); gtk_header_bar_set_title(GTK_HEADER_BAR(gtk_window->header), ""); @@ -995,6 +1031,21 @@ csd_gtk_calculate_frame(void){ return(frame); } +static CSD_B32 +csd_gtk_calc_surface_off(CSD_GTK_Window *gtk_window, struct wl_surface *surface, + CSD_S32 *off){ + CSD_B32 result = 0; + if (surface == gtk_window->titlebar.wl_surface){ + memcpy(off, gtk_window->titlebar.p, sizeof(gtk_window->titlebar.p)); + result = 1; + } + else if (surface == gtk_window->shadow.wl_surface){ + memcpy(off, gtk_window->shadow.p, sizeof(gtk_window->shadow.p)); + result = 1; + } + return(result); +} + typedef struct CSD_GTK_FindWidgetVars{ char *name; GtkWidget *widget; @@ -1027,30 +1078,57 @@ csd_gtk__widget_from_name(GtkWidget *root, char *name){ #define SHADOW_MARGIN 24 static void -csd_gtk_update_and_render(void){ - CSD_Seat *seat = &ctx.seat; - CSD_Window *window = &ctx.window; - CSD_GTK_Window *gtk_window = &ctx.gtk_window; +csd_gtk_update_and_render(CSD_Window *window, CSD_GTK_Window *gtk_window, + CSD_Seat **seats, CSD_U32 seat_count){ - /* determine cursor location information */ + /* setup buttons */ + enum{ + HEADER_BUTTON_NULL, + HEADER_BUTTON_MIN, HEADER_BUTTON_MAX, HEADER_BUTTON_CLOSE, + HEADER_BUTTON_COUNT + }; + static char* header_button_name[] = { + 0, ".minimize", ".maximize", ".close" + }; + CSD_B32 header_button_active[] = { + /*NULL*/ 0, + /*MIN*/ (window->control_flags & CSD_WindowControlFlag_Min), + /*MAX*/ ((window->control_flags & CSD_WindowControlFlag_Max) && + (window->control_flags & CSD_WindowControlFlag_Resize)), + /*CLOSE*/ (window->control_flags & CSD_WindowControlFlag_Close) + }; + + /* per-cursor locals */ enum{ LOCATION_NULL, LOCATION_SHADOW, LOCATION_TITLEBAR, }; - CSD_U32 cursor_loc = LOCATION_NULL; - CSD_S32 cursor_shadow_loc = 0; - { - { - CSD_S32 l = (seat->hover_p[0] < 0); - CSD_S32 r = (!l && seat->hover_p[0] >= window->dim[0]); - CSD_S32 t = (seat->hover_p[1] < -window->csd_frame.border[1][0]); - CSD_S32 b = (!t && seat->hover_p[1] >= window->dim[1]); - cursor_shadow_loc = 3*(b - t) + (r - l); - } - if (cursor_shadow_loc != 0){ - cursor_loc = LOCATION_SHADOW; - } - else if (seat->hover_p[1] < 0){ - cursor_loc = LOCATION_TITLEBAR; + struct CursorVars{ + CSD_U32 loc; + CSD_S32 shadow_loc; + CSD_U32 header_button_hover; + } CursorVars; + struct CursorVars *cursors = alloca(sizeof(struct CursorVars)*seat_count); + memset(cursors, 0, sizeof(struct CursorVars)*seat_count); + + /* determine cursor location information */ + for (CSD_U32 si = 0; si < seat_count; si += 1){ + CSD_Seat *seat = seats[si]; + + if (seat->hover_surface == window->main_wl_surface || + seat->hover_surface == gtk_window->titlebar.wl_surface || + seat->hover_surface == gtk_window->shadow.wl_surface){ + CSD_B32 l = (seat->hover_p[0] < 0); + CSD_B32 r = (!l && seat->hover_p[0] >= window->dim[0]); + CSD_B32 t = (seat->hover_p[1] < -window->csd_frame.border[1][0]); + CSD_B32 b = (!t && seat->hover_p[1] >= window->dim[1]); + + cursors[si].shadow_loc = 3*(b - t) + (r - l); + if (cursors[si].shadow_loc != 0){ + cursors[si].loc = LOCATION_SHADOW; + } + else if (seat->hover_p[1] < 0){ + cursors[si].loc = LOCATION_TITLEBAR; + } } } @@ -1098,25 +1176,6 @@ csd_gtk_update_and_render(void){ csd_subsurface_commit(subsurface); } - - /* setup buttons */ - enum{ - HEADER_BUTTON_NULL, - HEADER_BUTTON_MIN, HEADER_BUTTON_MAX, HEADER_BUTTON_CLOSE, - HEADER_BUTTON_COUNT - }; - static char* header_button_name[] = { - 0, ".minimize", ".maximize", ".close" - }; - CSD_B32 header_button_active[] = { - /*NULL*/ 0, - /*MIN*/ (window->control_flags & CSD_WindowControlFlag_Min), - /*MAX*/ ((window->control_flags & CSD_WindowControlFlag_Max) && - (window->control_flags & CSD_WindowControlFlag_Resize)), - /*CLOSE*/ (window->control_flags & CSD_WindowControlFlag_Close) - }; - CSD_U32 header_button_hover = 0; - /* draw frame */ { CSD_SubSurface *subsurface = >k_window->titlebar; @@ -1216,17 +1275,21 @@ csd_gtk_update_and_render(void){ GtkAllocation rect; gtk_widget_get_clip(widget, &rect); + CSD_S32 x0 = rect.x; + CSD_S32 y0 = rect.y - title_dim[1]; + CSD_S32 x1 = rect.x + rect.width; + CSD_S32 y1 = rect.y + rect.height - title_dim[1]; + /* check pointer hover */ CSD_B32 is_hovered = 0; - { - CSD_S32 x0 = rect.x; - CSD_S32 y0 = rect.y - title_dim[1]; - CSD_S32 x1 = rect.x + rect.width; - CSD_S32 y1 = rect.y + rect.height - title_dim[1]; - if (x0 <= seat->hover_p[0] && seat->hover_p[0] < x1 && - y0 <= seat->hover_p[1] && seat->hover_p[1] < y1){ - header_button_hover = i; - is_hovered = 1; + for (CSD_U32 si = 0; si < seat_count; si += 1){ + if (cursors[si].loc == LOCATION_TITLEBAR){ + CSD_Seat *seat = seats[si]; + if (x0 <= seat->hover_p[0] && seat->hover_p[0] < x1 && + y0 <= seat->hover_p[1] && seat->hover_p[1] < y1){ + cursors[si].header_button_hover = i; + is_hovered = 1; + } } } @@ -1324,26 +1387,30 @@ csd_gtk_update_and_render(void){ /* handle left-button press */ if (ctx.event_button == BTN_LEFT && ctx.event_button_state == 1){ - switch (cursor_loc){ + CSD_U32 si = 0; + switch (cursors[si].loc){ default: case LOCATION_NULL: break; case LOCATION_SHADOW: { +#define X(N) XDG_TOPLEVEL_RESIZE_EDGE_##N static const enum xdg_toplevel_resize_edge xedge_box[] = { - XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT, XDG_TOPLEVEL_RESIZE_EDGE_TOP, XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT, - XDG_TOPLEVEL_RESIZE_EDGE_LEFT, XDG_TOPLEVEL_RESIZE_EDGE_NONE, XDG_TOPLEVEL_RESIZE_EDGE_RIGHT, - XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT, XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM, XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT, + X(TOP_LEFT), X(TOP), X(TOP_RIGHT), + X(LEFT), X(NONE), X(RIGHT), + X(BOTTOM_LEFT), X(BOTTOM), X(BOTTOM_RIGHT), }; - xdg_toplevel_resize(window->main_xdg_toplevel, seat->wl_seat, - seat->serial, xedge_box[4 + cursor_shadow_loc]); +#undef X + xdg_toplevel_resize(window->main_xdg_toplevel, seats[si]->wl_seat, + seats[si]->serial, xedge_box[4 + cursors[si].shadow_loc]); ctx.has_event = 0; }break; case LOCATION_TITLEBAR: { - if (header_button_hover == 0){ - xdg_toplevel_move(window->main_xdg_toplevel, seat->wl_seat, seat->serial); + if (cursors[si].header_button_hover == 0){ + xdg_toplevel_move(window->main_xdg_toplevel, + seats[si]->wl_seat, seats[si]->serial); } else{ - gtk_window->active_header_button = header_button_hover; + gtk_window->active_header_button = cursors[si].header_button_hover; } ctx.has_event = 0; }break; @@ -1353,25 +1420,31 @@ csd_gtk_update_and_render(void){ /* handle left-button release */ if (ctx.event_button == BTN_LEFT && ctx.event_button_state == 0){ + CSD_U32 si = 0; if (gtk_window->active_header_button != 0 && - gtk_window->active_header_button == header_button_hover){ - // activate button effect here + gtk_window->active_header_button == cursors[si].header_button_hover){ + switch (gtk_window->active_header_button){ + case HEADER_BUTTON_MIN: { ctx.minimize_signal = 1; } break; + case HEADER_BUTTON_MAX: { ctx.maximize_signal = 1; } break; + case HEADER_BUTTON_CLOSE: { ctx.close_signal = 1; } break; + } + gtk_window->active_header_button = 0; } - gtk_window->active_header_button = 0; } } /* set cursor shape */ - if (window->control_flags & CSD_WindowControlFlag_Resize){ - static const CSD_CursorShape cursor_box[] = { - CSD_CursorShape_Resize_TopLeft, CSD_CursorShape_Resize_Top, CSD_CursorShape_Resize_TopRight, - CSD_CursorShape_Resize_Left, CSD_CursorShape_Pointer, CSD_CursorShape_Resize_Right, - CSD_CursorShape_Resize_BottomLeft, CSD_CursorShape_Resize_Bottom, CSD_CursorShape_Resize_BottomRight, - }; - seat->cursor_shape = cursor_box[4 + cursor_shadow_loc]; - } - else{ - seat->cursor_shape = CSD_CursorShape_Pointer; + for (CSD_U32 si = 0; si < seat_count; si += 1){ + if (window->control_flags & CSD_WindowControlFlag_Resize){ +#define X(N) CSD_CursorShape_##N + static const CSD_CursorShape cursor_box[] = { + X(Resize_TopLeft), X(Resize_Top), X(Resize_TopRight), + X(Resize_Left), X(Pointer), X(Resize_Right), + X(Resize_BottomLeft), X(Resize_Bottom), X(Resize_BottomRight), + }; +#undef X + seats[si]->cursor_shape = cursor_box[4 + cursors[si].shadow_loc]; + } } } diff --git a/wayland_gtk_egl.h b/wayland_gtk_egl.h index b51f774..c8f6f97 100644 --- a/wayland_gtk_egl.h +++ b/wayland_gtk_egl.h @@ -133,6 +133,10 @@ typedef struct CSD_Seat{ /* csd helpers */ +static void csd_window_init(CSD_Window *window); +static void csd_window_apply_new_config(CSD_Window *window); +static void csd_window_size_update(CSD_Window *window, CSD_Frame *csd_frame); + static CSD_SubSurface csd_subsurface_new(void); static void csd_subsurface_buffer_clear(CSD_SubSurface *subsurface); static void csd_subsurface_buffer_alloc(CSD_SubSurface *subsurface, CSD_S32 dim[2]); @@ -180,10 +184,14 @@ typedef struct CSD_GTK_Window{ /* csd gtk implementation */ static void csd_gtk_init(void); -static void csd_gtk_window_init(void); -static CSD_Frame csd_gtk_calculate_frame(void); +static void csd_gtk_window_init(CSD_GTK_Window *gtk_window); +static CSD_Frame csd_gtk_calc_frame(CSD_Window *window, CSD_GTK_Window *gtk_window); +static CSD_B32 csd_gtk_calc_surface_off(CSD_GTK_Window *gtk_window, + struct wl_surface *surface, + CSD_S32 *off); -static void csd_gtk_update_and_render(void); +static void csd_gtk_update_and_render(CSD_Window *window, CSD_GTK_Window *gtk_window, + CSD_Seat **seats, CSD_U32 seat_count); /* csd gtk cairo shadow rendering */ @@ -198,6 +206,8 @@ static void csd_gtk_render_shadow(cairo_t *cr, cairo_surface_t *surface, typedef struct Ctx{ /* the rest */ CSD_B32 close_signal; + CSD_B32 minimize_signal; + CSD_B32 maximize_signal; CSD_B32 has_event; CSD_U32 event_button;