diff --git a/src/Makefile.am b/src/Makefile.am index f35c5b1..01fa47b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -162,7 +162,8 @@ wmaker_SOURCES += \ backend/wayland/wl_event.c \ backend/wayland/wl_stacking.c \ backend/wayland/wl_overlay.c \ - backend/wayland/wl_window.c + backend/wayland/wl_window.c \ + backend/wayland/wl_props.c endif if USE_NESTED_FUNC diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index 6f61e3d..4430ac8 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -6255,92 +6255,6 @@ wl_keyboard_ungrab(void) /* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */ -/* Properties */ -/* ------------------------------------------------------------------ */ - -static int -wl_prop_get_normal_hints(WNativeWindow win, WNormalHints *out, int *pre_icccm) -{ - /* Phase 47: populate size constraints from XDG toplevel. - * Phase 17: also handles XWayland size_hints. */ - struct wl_toplevel_view *v = wl_find_view_by_id(win); - memset(out, 0, sizeof(*out)); - *pre_icccm = 0; - if (!v) return 0; - - /* Phase 17: XWayland size_hints path. */ - if (v->xw_surface) { - xcb_size_hints_t *sh = v->xw_surface->size_hints; - if (sh) { - if (sh->min_width > 0 || sh->min_height > 0) { - out->flags |= WNH_P_MIN_SIZE; - out->min_width = sh->min_width > 0 ? sh->min_width : 1; - out->min_height = sh->min_height > 0 ? sh->min_height : 1; - } - if (sh->max_width > 0 || sh->max_height > 0) { - out->flags |= WNH_P_MAX_SIZE; - out->max_width = sh->max_width; - out->max_height = sh->max_height; - } - } - if (v->xw_surface->width > 0 && v->xw_surface->height > 0) { - out->flags |= WNH_P_SIZE; - out->width = v->xw_surface->width; - out->height = v->xw_surface->height; - } - return (out->flags != 0) ? 1 : 0; - } - - if (!v->xdg_surface || !v->xdg_surface->toplevel) - return 0; - struct wlr_xdg_toplevel *tl = v->xdg_surface->toplevel; - if (tl->current.min_width > 0 || tl->current.min_height > 0) { - out->flags |= WNH_P_MIN_SIZE; - out->min_width = (int)tl->current.min_width; - out->min_height = (int)tl->current.min_height; - } - if (tl->current.max_width > 0 || tl->current.max_height > 0) { - out->flags |= WNH_P_MAX_SIZE; - out->max_width = (int)tl->current.max_width; - out->max_height = (int)tl->current.max_height; - } - /* Report the current size as the base/initial size. */ - if (v->xdg_surface->surface) { - int w = v->xdg_surface->surface->current.width; - int h = v->xdg_surface->surface->current.height; - if (w > 0 && h > 0) { - out->flags |= WNH_P_SIZE; - out->width = w; - out->height = h; - } - } - return (out->flags != 0) ? 1 : 0; -} - -static WWMHints * -wl_prop_get_wm_hints(WNativeWindow win) { (void)win; return NULL; } - -static int -wl_prop_get_wm_class(WNativeWindow win, - char **wm_class, char **wm_instance) -{ - /* Phase 41: use XDG app_id / Phase 17: use XWayland WM_CLASS. */ - struct wl_toplevel_view *v = wl_find_view_by_id(win); - if (v && v->xw_surface) { - *wm_class = strdup(v->xw_surface->class ? v->xw_surface->class : "x11-client"); - *wm_instance = strdup(v->xw_surface->instance ? v->xw_surface->instance : "x11-client"); - return 1; - } - const char *app_id = (v && v->xdg_surface && v->xdg_surface->toplevel && - v->xdg_surface->toplevel->app_id) - ? v->xdg_surface->toplevel->app_id : "wayland-client"; - *wm_class = strdup(app_id); - *wm_instance = strdup(app_id); - return 1; -} - - - static Bool wl_noop_screen_get_head_usable_area(WScreen *scr, int head, int *x1, int *y1, int *x2, int *y2) @@ -6350,69 +6264,6 @@ wl_noop_screen_get_head_usable_area(WScreen *scr, int head, return False; } - -static int -wl_prop_get_wmaker_menu(WNativeWindow win, - char ***list_out, int *count_out) -{ - (void)win; - *list_out = NULL; *count_out = 0; - return 0; -} - -static WNativeWindow -wl_prop_get_transient_for(WNativeWindow win) -{ - /* Phase 65: return the synthetic ID of the parent XDG toplevel, or - * WNATIVE_NONE if this surface has no parent. The wlroots XDG - * implementation stores the parent as xdg_surface->toplevel->parent - * (a wlr_xdg_surface *). We walk the view list to find its ID. */ - struct wl_toplevel_view *v = wl_find_view_by_id(win); - if (!v) return WNATIVE_NONE; - /* Phase 17: XWayland transient_for via parent window_id. */ - if (v->xw_surface) { - struct wlr_xwayland_surface *parent = v->xw_surface->parent; - if (!parent) return WNATIVE_NONE; - return (WNativeWindow)parent->window_id; - } - if (!v->xdg_surface || !v->xdg_surface->toplevel) - return WNATIVE_NONE; - struct wlr_xdg_toplevel *ptl = v->xdg_surface->toplevel->parent; - if (!ptl || !ptl->base) - return WNATIVE_NONE; - struct wl_toplevel_view *pv = wl_find_view_by_xdg_surface(ptl->base); - if (!pv) - return WNATIVE_NONE; - return pv->id; -} - -static int wl_prop_has_wmaker_menu(WNativeWindow win) { (void)win; return 0; } -static int wl_prop_has_gtk_object_path(WNativeWindow win) { (void)win; return 0; } - -static void -wl_prop_set_wm_state(WNativeWindow win, const long *data, int n) -{ - /* Phase 56: store WM state in the view struct for later retrieval. */ - struct wl_toplevel_view *v = wl_find_view_by_id(win); - if (!v || !data || n <= 0) return; - if (v->wm_state) wfree(v->wm_state); - v->wm_state = wmalloc((size_t)n * sizeof(long)); - memcpy(v->wm_state, data, (size_t)n * sizeof(long)); - v->wm_state_n = n; -} - -static int -wl_prop_get_wm_state(WNativeWindow win, long **data_out) -{ - /* Phase 56: return a heap copy of the stored WM state (caller frees). */ - struct wl_toplevel_view *v = wl_find_view_by_id(win); - if (!v || !v->wm_state) { *data_out = NULL; return 0; } - *data_out = wmalloc((size_t)v->wm_state_n * sizeof(long)); - memcpy(*data_out, v->wm_state, (size_t)v->wm_state_n * sizeof(long)); - return v->wm_state_n; -} - -/* ------------------------------------------------------------------ */ /* WNativeWindow map / unmap / geometry */ /* ------------------------------------------------------------------ */ diff --git a/src/backend/wayland/wl_props.c b/src/backend/wayland/wl_props.c new file mode 100644 index 0000000..f5061e9 --- /dev/null +++ b/src/backend/wayland/wl_props.c @@ -0,0 +1,169 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include "../../screen.h" +#include "wl_types.h" + +/* Forward declarations from sibling modules. */ +struct wl_toplevel_view *wl_find_view_by_id(WNativeWindow id); +struct wl_toplevel_view *wl_find_view_by_xdg_surface(struct wlr_xdg_surface *surf); + +/* Properties */ +/* ------------------------------------------------------------------ */ + +int +wl_prop_get_normal_hints(WNativeWindow win, WNormalHints *out, int *pre_icccm) +{ + /* Phase 47: populate size constraints from XDG toplevel. + * Phase 17: also handles XWayland size_hints. */ + struct wl_toplevel_view *v = wl_find_view_by_id(win); + memset(out, 0, sizeof(*out)); + *pre_icccm = 0; + if (!v) return 0; + + /* Phase 17: XWayland size_hints path. */ + if (v->xw_surface) { + xcb_size_hints_t *sh = v->xw_surface->size_hints; + if (sh) { + if (sh->min_width > 0 || sh->min_height > 0) { + out->flags |= WNH_P_MIN_SIZE; + out->min_width = sh->min_width > 0 ? sh->min_width : 1; + out->min_height = sh->min_height > 0 ? sh->min_height : 1; + } + if (sh->max_width > 0 || sh->max_height > 0) { + out->flags |= WNH_P_MAX_SIZE; + out->max_width = sh->max_width; + out->max_height = sh->max_height; + } + } + if (v->xw_surface->width > 0 && v->xw_surface->height > 0) { + out->flags |= WNH_P_SIZE; + out->width = v->xw_surface->width; + out->height = v->xw_surface->height; + } + return (out->flags != 0) ? 1 : 0; + } + + if (!v->xdg_surface || !v->xdg_surface->toplevel) + return 0; + struct wlr_xdg_toplevel *tl = v->xdg_surface->toplevel; + if (tl->current.min_width > 0 || tl->current.min_height > 0) { + out->flags |= WNH_P_MIN_SIZE; + out->min_width = (int)tl->current.min_width; + out->min_height = (int)tl->current.min_height; + } + if (tl->current.max_width > 0 || tl->current.max_height > 0) { + out->flags |= WNH_P_MAX_SIZE; + out->max_width = (int)tl->current.max_width; + out->max_height = (int)tl->current.max_height; + } + /* Report the current size as the base/initial size. */ + if (v->xdg_surface->surface) { + int w = v->xdg_surface->surface->current.width; + int h = v->xdg_surface->surface->current.height; + if (w > 0 && h > 0) { + out->flags |= WNH_P_SIZE; + out->width = w; + out->height = h; + } + } + return (out->flags != 0) ? 1 : 0; +} + +WWMHints * +wl_prop_get_wm_hints(WNativeWindow win) { (void)win; return NULL; } + +int + +wl_prop_get_wm_class(WNativeWindow win, + char **wm_class, char **wm_instance) +{ + /* Phase 41: use XDG app_id / Phase 17: use XWayland WM_CLASS. */ + struct wl_toplevel_view *v = wl_find_view_by_id(win); + if (v && v->xw_surface) { + *wm_class = strdup(v->xw_surface->class ? v->xw_surface->class : "x11-client"); + *wm_instance = strdup(v->xw_surface->instance ? v->xw_surface->instance : "x11-client"); + return 1; + } + const char *app_id = (v && v->xdg_surface && v->xdg_surface->toplevel && + v->xdg_surface->toplevel->app_id) + ? v->xdg_surface->toplevel->app_id : "wayland-client"; + *wm_class = strdup(app_id); + *wm_instance = strdup(app_id); + return 1; +} + + + + + + +int +wl_prop_get_wmaker_menu(WNativeWindow win, + char ***list_out, int *count_out) +{ + (void)win; + *list_out = NULL; *count_out = 0; + return 0; +} + +WNativeWindow +wl_prop_get_transient_for(WNativeWindow win) +{ + /* Phase 65: return the synthetic ID of the parent XDG toplevel, or + * WNATIVE_NONE if this surface has no parent. The wlroots XDG + * implementation stores the parent as xdg_surface->toplevel->parent + * (a wlr_xdg_surface *). We walk the view list to find its ID. */ + struct wl_toplevel_view *v = wl_find_view_by_id(win); + if (!v) return WNATIVE_NONE; + /* Phase 17: XWayland transient_for via parent window_id. */ + if (v->xw_surface) { + struct wlr_xwayland_surface *parent = v->xw_surface->parent; + if (!parent) return WNATIVE_NONE; + return (WNativeWindow)parent->window_id; + } + if (!v->xdg_surface || !v->xdg_surface->toplevel) + return WNATIVE_NONE; + struct wlr_xdg_toplevel *ptl = v->xdg_surface->toplevel->parent; + if (!ptl || !ptl->base) + return WNATIVE_NONE; + struct wl_toplevel_view *pv = wl_find_view_by_xdg_surface(ptl->base); + if (!pv) + return WNATIVE_NONE; + return pv->id; +} + +int wl_prop_has_wmaker_menu(WNativeWindow win) { (void)win; return 0; } +int wl_prop_has_gtk_object_path(WNativeWindow win) { (void)win; return 0; } + +void +wl_prop_set_wm_state(WNativeWindow win, const long *data, int n) +{ + /* Phase 56: store WM state in the view struct for later retrieval. */ + struct wl_toplevel_view *v = wl_find_view_by_id(win); + if (!v || !data || n <= 0) return; + if (v->wm_state) wfree(v->wm_state); + v->wm_state = wmalloc((size_t)n * sizeof(long)); + memcpy(v->wm_state, data, (size_t)n * sizeof(long)); + v->wm_state_n = n; +} + +int +wl_prop_get_wm_state(WNativeWindow win, long **data_out) +{ + /* Phase 56: return a heap copy of the stored WM state (caller frees). */ + struct wl_toplevel_view *v = wl_find_view_by_id(win); + if (!v || !v->wm_state) { *data_out = NULL; return 0; } + *data_out = wmalloc((size_t)v->wm_state_n * sizeof(long)); + memcpy(*data_out, v->wm_state, (size_t)v->wm_state_n * sizeof(long)); + return v->wm_state_n; +} + +/* ------------------------------------------------------------------ */ + diff --git a/src/backend/wayland/wl_types.h b/src/backend/wayland/wl_types.h index 076cc4a..47d0edc 100644 --- a/src/backend/wayland/wl_types.h +++ b/src/backend/wayland/wl_types.h @@ -450,3 +450,14 @@ void wl_window_shape_clear(WWindow *wwin); struct wl_toplevel_view *wl_find_view_by_xdg_surface(struct wlr_xdg_surface *surf); void wmaker_popup_apply(struct wl_toplevel_view *view); void frame_buf_update_children_abs(WNativeWindow parent_id); + +/* Property module declarations (extracted to wl_props.c) */ +int wl_prop_get_normal_hints(WNativeWindow win, WNormalHints *out, int *pre_icccm); +WWMHints *wl_prop_get_wm_hints(WNativeWindow win); +int wl_prop_get_wm_class(WNativeWindow win, char **wm_class, char **wm_instance); +int wl_prop_get_wmaker_menu(WNativeWindow win, char ***list_out, int *count_out); +WNativeWindow wl_prop_get_transient_for(WNativeWindow win); +int wl_prop_has_wmaker_menu(WNativeWindow win); +int wl_prop_has_gtk_object_path(WNativeWindow win); +void wl_prop_set_wm_state(WNativeWindow win, const long *data, int n); +int wl_prop_get_wm_state(WNativeWindow win, long **data_out);