decompose wl_backend.c: extract wl_window.c (window map/unmap/move/resize/border/clear)
This commit is contained in:
parent
b9450d16ad
commit
273589092d
|
|
@ -161,7 +161,8 @@ wmaker_SOURCES += \
|
|||
backend/wayland/wl_context.c \
|
||||
backend/wayland/wl_event.c \
|
||||
backend/wayland/wl_stacking.c \
|
||||
backend/wayland/wl_overlay.c
|
||||
backend/wayland/wl_overlay.c \
|
||||
backend/wayland/wl_window.c
|
||||
endif
|
||||
|
||||
if USE_NESTED_FUNC
|
||||
|
|
|
|||
|
|
@ -326,7 +326,7 @@ static int wl_client_get_pid(WNativeWindow win);
|
|||
static void wl_update_pointer_focus(uint32_t time_msec);
|
||||
static void wl_pointer_warp_to(int x, int y);
|
||||
/* wmaker-popup-v1 helper — defined in protocol section below. */
|
||||
static void wmaker_popup_apply(struct wl_toplevel_view *view);
|
||||
void wmaker_popup_apply(struct wl_toplevel_view *view);
|
||||
/* Phase 14: pointer event handler forward declarations. */
|
||||
static void handle_pointer_motion(struct wl_listener *listener, void *data);
|
||||
/* Phase 24: click-to-focus helper — defined in Phase 13 pointer section. */
|
||||
|
|
@ -396,7 +396,7 @@ wl_find_view_by_id(WNativeWindow id)
|
|||
}
|
||||
|
||||
/* Phase 65: look up the view for a given wlr_xdg_surface pointer. */
|
||||
static struct wl_toplevel_view *
|
||||
struct wl_toplevel_view *
|
||||
wl_find_view_by_xdg_surface(struct wlr_xdg_surface *surf)
|
||||
{
|
||||
struct wl_toplevel_view *v;
|
||||
|
|
@ -1081,7 +1081,7 @@ wmaker_popup_resource_destroy(struct wl_resource *resource)
|
|||
view->popup = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
wmaker_popup_apply(struct wl_toplevel_view *view)
|
||||
{
|
||||
if (!view || !view->popup) return;
|
||||
|
|
@ -4062,7 +4062,7 @@ static void fb_attach_tree_listener(struct wl_frame_buf *fb)
|
|||
* to keep absolute-position tracking in sync after the parent moves.
|
||||
* Hit-testing (frame_buf_at, frame_buf_button_at) and click coordinate
|
||||
* translation depend on these fields being current. */
|
||||
static void
|
||||
void
|
||||
frame_buf_update_children_abs(WNativeWindow parent_id)
|
||||
{
|
||||
struct wl_frame_buf *parent = frame_buf_find(parent_id);
|
||||
|
|
@ -6339,41 +6339,7 @@ wl_prop_get_wm_class(WNativeWindow win,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static Bool
|
||||
wl_window_fetch_name(WNativeWindow win, char **name_out)
|
||||
{
|
||||
/* Phase 41: XDG title / Phase 17: XWayland title. */
|
||||
struct wl_toplevel_view *v = wl_find_view_by_id(win);
|
||||
const char *title = NULL;
|
||||
if (v && v->xw_surface)
|
||||
title = v->xw_surface->title;
|
||||
else if (v && v->xdg_surface && v->xdg_surface->toplevel)
|
||||
title = v->xdg_surface->toplevel->title;
|
||||
if (title) {
|
||||
*name_out = strdup(title);
|
||||
return True;
|
||||
}
|
||||
*name_out = NULL;
|
||||
return False;
|
||||
}
|
||||
|
||||
static Bool
|
||||
wl_window_get_icon_name(WNativeWindow win, char **name_out)
|
||||
{
|
||||
/* Phase 60: return title for icon labels; Phase 17: XWayland path. */
|
||||
struct wl_toplevel_view *v = wl_find_view_by_id(win);
|
||||
const char *title = NULL;
|
||||
if (v && v->xw_surface)
|
||||
title = v->xw_surface->title;
|
||||
else if (v && v->xdg_surface && v->xdg_surface->toplevel)
|
||||
title = v->xdg_surface->toplevel->title;
|
||||
if (title) {
|
||||
*name_out = strdup(title);
|
||||
return True;
|
||||
}
|
||||
*name_out = NULL;
|
||||
return False;
|
||||
}
|
||||
|
||||
static Bool
|
||||
wl_noop_screen_get_head_usable_area(WScreen *scr, int head,
|
||||
|
|
@ -6384,15 +6350,6 @@ wl_noop_screen_get_head_usable_area(WScreen *scr, int head,
|
|||
return False;
|
||||
}
|
||||
|
||||
static void *
|
||||
wl_window_get_icon_image(WNativeWindow win)
|
||||
{
|
||||
/* For XWayland clients, parse _NET_WM_ICON via the Xwayland display.
|
||||
* For native Wayland clients there is no equivalent (the upcoming
|
||||
* xdg-toplevel-icon protocol is not yet wired). */
|
||||
if (!wl_state.x_display) return NULL;
|
||||
return get_window_image_from_x11(wl_state.x_display, (WNativeWindow)win);
|
||||
}
|
||||
|
||||
static int
|
||||
wl_prop_get_wmaker_menu(WNativeWindow win,
|
||||
|
|
@ -6459,333 +6416,14 @@ wl_prop_get_wm_state(WNativeWindow win, long **data_out)
|
|||
/* WNativeWindow map / unmap / geometry */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static void
|
||||
wl_window_map(WNativeWindow win)
|
||||
{
|
||||
struct wl_toplevel_view *v = wl_find_view_by_id(win);
|
||||
if (v && v->scene_node) {
|
||||
wlr_scene_node_set_enabled(&v->scene_node->node, true);
|
||||
return;
|
||||
}
|
||||
if (v)
|
||||
return;
|
||||
/* Frame buffer: enable its scene node and children. */
|
||||
struct wl_frame_buf *fb = frame_buf_find(win);
|
||||
if (fb && fb->scene_buf) {
|
||||
/* If this is a child, only enable if parent is enabled */
|
||||
if (fb->parent_id) {
|
||||
struct wl_frame_buf *parent = frame_buf_find(fb->parent_id);
|
||||
if (parent && parent->scene_buf &&
|
||||
!parent->scene_buf->node.enabled)
|
||||
return; /* parent not visible yet */
|
||||
}
|
||||
wlr_scene_node_set_enabled(&fb->scene_buf->node, true);
|
||||
/* Raise the tree (raises entire window assembly together) */
|
||||
if (fb->tree) {
|
||||
wlr_scene_node_set_enabled(&fb->tree->node, true);
|
||||
wlr_scene_node_raise_to_top(&fb->tree->node);
|
||||
} else if (!fb->parent_id)
|
||||
wlr_scene_node_raise_to_top(&fb->scene_buf->node);
|
||||
/* Also enable children (and grandchildren) */
|
||||
struct wl_frame_buf *child;
|
||||
wl_list_for_each(child, &wl_state.frame_list, link) {
|
||||
if (child->parent_id == win && child->scene_buf) {
|
||||
wlr_scene_node_set_enabled(&child->scene_buf->node, true);
|
||||
struct wl_frame_buf *gc;
|
||||
wl_list_for_each(gc, &wl_state.frame_list, link) {
|
||||
if (gc->parent_id == child->id && gc->scene_buf)
|
||||
wlr_scene_node_set_enabled(&gc->scene_buf->node, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wl_window_map_raised(WNativeWindow win)
|
||||
{
|
||||
struct wl_toplevel_view *v = wl_find_view_by_id(win);
|
||||
if (v && v->scene_node) {
|
||||
wlr_scene_node_set_enabled(&v->scene_node->node, true);
|
||||
if (v->frame_id) {
|
||||
struct wl_frame_buf *fb = frame_buf_find(v->frame_id);
|
||||
if (fb && fb->tree) {
|
||||
wlr_scene_node_raise_to_top(&fb->tree->node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
wlr_scene_node_raise_to_top(&v->scene_node->node);
|
||||
return;
|
||||
}
|
||||
struct wl_frame_buf *fb = frame_buf_find(win);
|
||||
if (fb && fb->scene_buf) {
|
||||
wlr_scene_node_set_enabled(&fb->scene_buf->node, true);
|
||||
if (fb->tree) {
|
||||
/* Top-level frame: enable tree (decoration children become visible). */
|
||||
wlr_scene_node_set_enabled(&fb->tree->node, true);
|
||||
wlr_scene_node_raise_to_top(&fb->tree->node);
|
||||
} else {
|
||||
wlr_scene_node_raise_to_top(&fb->scene_buf->node);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
static void wl_window_map_subwindows(WNativeWindow parent)
|
||||
{
|
||||
(void)parent;
|
||||
/* Child windows are sub-regions of the frame buffer — no-op. */
|
||||
}
|
||||
|
||||
static void
|
||||
wl_window_unmap(WNativeWindow win)
|
||||
{
|
||||
struct wl_toplevel_view *v = wl_find_view_by_id(win);
|
||||
if (v && v->scene_node) {
|
||||
wlr_scene_node_set_enabled(&v->scene_node->node, false);
|
||||
return;
|
||||
}
|
||||
struct wl_frame_buf *fb = frame_buf_find(win);
|
||||
if (!fb) return;
|
||||
/* For top-level frames, disable the whole tree. This hides the frame
|
||||
* buffer, all child scene_bufs (titlebar, resizebar, buttons), and the
|
||||
* client surface reparented into fb->tree — atomically and irrevocably
|
||||
* until the frame is explicitly mapped again. Disabling individual
|
||||
* child nodes is insufficient because a subsequent wl_frame_paint can
|
||||
* re-enable them while the window is still iconified. */
|
||||
if (fb->tree) {
|
||||
wlr_scene_node_set_enabled(&fb->tree->node, false);
|
||||
return;
|
||||
}
|
||||
/* Child frame_buf: disable its scene_buf node only. */
|
||||
if (fb->scene_buf)
|
||||
wlr_scene_node_set_enabled(&fb->scene_buf->node, false);
|
||||
}
|
||||
static void wl_window_move(WNativeWindow win, int x, int y)
|
||||
{
|
||||
struct wl_toplevel_view *v = wl_find_view_by_id(win);
|
||||
if (v) {
|
||||
if (v->frame_id) {
|
||||
/* Client is a child of a frame — coords are relative to frame */
|
||||
v->frame_rel_x = x;
|
||||
v->frame_rel_y = y;
|
||||
struct wl_frame_buf *fb = frame_buf_find(v->frame_id);
|
||||
if (fb) {
|
||||
v->x = fb->x + x;
|
||||
v->y = fb->y + y;
|
||||
}
|
||||
} else {
|
||||
v->x = x; v->y = y;
|
||||
}
|
||||
if (v->scene_node) {
|
||||
/* Scene node is a child of the frame tree — use relative coords */
|
||||
if (v->frame_id)
|
||||
wlr_scene_node_set_position(&v->scene_node->node, x, y);
|
||||
else
|
||||
wlr_scene_node_set_position(&v->scene_node->node, v->x, v->y);
|
||||
}
|
||||
if (v->xw_surface)
|
||||
wlr_xwayland_surface_configure(v->xw_surface,
|
||||
(int16_t)v->x, (int16_t)v->y,
|
||||
v->xw_surface->width, v->xw_surface->height);
|
||||
/* Re-apply any popups whose parent is this toplevel so they
|
||||
* track the parent's position. */
|
||||
struct wl_toplevel_view *p;
|
||||
wl_list_for_each(p, &wl_state.toplevel_list, link) {
|
||||
if (p->popup && p->popup_parent
|
||||
&& wl_find_view_by_xdg_surface(p->popup_parent->base) == v) {
|
||||
wmaker_popup_apply(p);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
struct wl_frame_buf *fb = frame_buf_find(win);
|
||||
if (fb) {
|
||||
fb->rel_x = x; fb->rel_y = y;
|
||||
if (fb->parent_id) {
|
||||
struct wl_frame_buf *parent = frame_buf_find(fb->parent_id);
|
||||
if (parent) {
|
||||
fb->x = parent->x + x;
|
||||
fb->y = parent->y + y;
|
||||
} else {
|
||||
fb->x = x; fb->y = y;
|
||||
}
|
||||
/* Child frame_buf: reposition scene_buf at relative offset */
|
||||
if (fb->scene_buf)
|
||||
wlr_scene_node_set_position(&fb->scene_buf->node, x, y);
|
||||
} else {
|
||||
fb->x = x; fb->y = y;
|
||||
/* Top-level frame: move the tree (children follow automatically) */
|
||||
if (fb->tree)
|
||||
wlr_scene_node_set_position(&fb->tree->node, x, y);
|
||||
}
|
||||
/* Update absolute position tracking for hit-testing — recursively
|
||||
* for all descendants so grandchildren (e.g. WINGs panel inside
|
||||
* a fake_leader inside a WMaker frame) stay in sync. */
|
||||
frame_buf_update_children_abs(win);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void wl_window_resize(WNativeWindow win, int w, int h)
|
||||
{
|
||||
struct wl_toplevel_view *v = wl_find_view_by_id(win);
|
||||
if (v) {
|
||||
if (w <= 0 || h <= 0) return;
|
||||
if (v->xw_surface) {
|
||||
wlr_xwayland_surface_configure(v->xw_surface,
|
||||
(int16_t)v->x, (int16_t)v->y, (uint16_t)w, (uint16_t)h);
|
||||
return;
|
||||
}
|
||||
if (!v->xdg_surface || !v->xdg_surface->toplevel) return;
|
||||
wlr_xdg_toplevel_set_size(v->xdg_surface->toplevel, (uint32_t)w, (uint32_t)h);
|
||||
wlr_xdg_surface_schedule_configure(v->xdg_surface);
|
||||
return;
|
||||
}
|
||||
struct wl_frame_buf *fb = frame_buf_find(win);
|
||||
if (fb && w > 0 && h > 0 && (w != fb->width || h != fb->height)) {
|
||||
pixman_image_unref(fb->image);
|
||||
fb->image = pixman_image_create_bits(PIXMAN_a8r8g8b8, w, h, NULL, 0);
|
||||
fb->width = w;
|
||||
fb->height = h;
|
||||
fb->base.width = w;
|
||||
fb->base.height = h;
|
||||
/* Update scene graph's cached buffer size for hit-testing. */
|
||||
if (fb->scene_buf)
|
||||
wlr_scene_buffer_set_dest_size(fb->scene_buf, w, h);
|
||||
}
|
||||
}
|
||||
static void wl_window_set_border(WNativeWindow win, unsigned long pixel)
|
||||
{
|
||||
(void)win; (void)pixel; /* borders are drawn into the frame buffer */
|
||||
}
|
||||
static void wl_window_set_border_width(WNativeWindow win, int width)
|
||||
{
|
||||
(void)win; (void)width; /* no-op for native frames */
|
||||
}
|
||||
static void wl_window_set_save_under(WNativeWindow win, int save_under) { (void)win; (void)save_under; }
|
||||
static void wl_noop_window_set_background(WNativeWindow win, unsigned long pixel) { (void)win; (void)pixel; }
|
||||
extern void *W_GetViewBacking(unsigned long id);
|
||||
|
||||
static void wl_window_set_background_pixmap(WNativeWindow win, unsigned long pixmap)
|
||||
{
|
||||
if (pixmap == 0) return;
|
||||
struct wl_frame_buf *fb = frame_buf_find(win);
|
||||
pixman_image_t *dst_img = NULL;
|
||||
|
||||
if (fb && fb->image) {
|
||||
dst_img = fb->image;
|
||||
fb->bg_pixmap = (pixman_image_t *)(uintptr_t)pixmap;
|
||||
} else {
|
||||
dst_img = (pixman_image_t *)W_GetViewBacking(win);
|
||||
}
|
||||
if (!dst_img) return;
|
||||
|
||||
pixman_image_t *src = (pixman_image_t *)(uintptr_t)pixmap;
|
||||
int src_w = pixman_image_get_width(src);
|
||||
int src_h = pixman_image_get_height(src);
|
||||
|
||||
/* Blit source pixmap into frame_buf's image */
|
||||
pixman_image_composite32(PIXMAN_OP_SRC,
|
||||
src, /* src */
|
||||
NULL, /* mask */
|
||||
dst_img, /* dest */
|
||||
0, 0, /* src x,y */
|
||||
0, 0, /* mask x,y */
|
||||
0, 0, /* dest x,y */
|
||||
src_w < pixman_image_get_width(dst_img) ? src_w : pixman_image_get_width(dst_img),
|
||||
src_h < pixman_image_get_height(dst_img) ? src_h : pixman_image_get_height(dst_img));
|
||||
if (fb)
|
||||
wlr_scene_buffer_set_buffer_with_damage(fb->scene_buf, &fb->base, NULL);
|
||||
}
|
||||
|
||||
static void wl_pixmap_free(unsigned long pixmap)
|
||||
{
|
||||
if (pixmap == 0) return;
|
||||
pixman_image_t *img = (pixman_image_t *)(uintptr_t)pixmap;
|
||||
pixman_image_unref(img);
|
||||
}
|
||||
static void wl_window_clear(WNativeWindow win)
|
||||
{
|
||||
struct wl_frame_buf *fb = frame_buf_find(win);
|
||||
pixman_image_t *img = NULL;
|
||||
|
||||
if (fb && fb->image) {
|
||||
img = fb->image;
|
||||
} else {
|
||||
img = (pixman_image_t *)W_GetViewBacking(win);
|
||||
}
|
||||
if (!img) return;
|
||||
|
||||
int width = pixman_image_get_width(img);
|
||||
int height = pixman_image_get_height(img);
|
||||
|
||||
/* If a background pixmap is set, repaint from it (like XClearWindow) */
|
||||
if (fb && fb->bg_pixmap) {
|
||||
pixman_image_composite32(PIXMAN_OP_SRC,
|
||||
fb->bg_pixmap, NULL, img,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
width, height);
|
||||
} else {
|
||||
/* No background pixmap — fill with transparent black */
|
||||
int stride = pixman_image_get_stride(img);
|
||||
uint32_t *data = (uint32_t *)pixman_image_get_data(img);
|
||||
memset(data, 0, stride * height);
|
||||
}
|
||||
|
||||
/* Notify the scene buffer of the update */
|
||||
if (fb)
|
||||
wlr_scene_buffer_set_buffer_with_damage(fb->scene_buf, &fb->base, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
wl_window_get_rect(WNativeWindow win,
|
||||
int *win_x, int *win_y, int *win_w, int *win_h)
|
||||
{
|
||||
/* Phase 55: return real geometry for synthetic toplevel IDs. */
|
||||
if (win == WNATIVE_NONE) {
|
||||
if (win_x) { *win_x = 0; } if (win_y) { *win_y = 0; }
|
||||
if (win_w) { *win_w = 1; } if (win_h) { *win_h = 1; }
|
||||
return 0; /* invalid/none */
|
||||
}
|
||||
struct wl_toplevel_view *v = wl_find_view_by_id(win);
|
||||
/* Phase 17: XWayland geometry. */
|
||||
if (v && v->xw_surface) {
|
||||
if (win_x) { *win_x = v->x; }
|
||||
if (win_y) { *win_y = v->y; }
|
||||
if (win_w) { *win_w = v->xw_surface->width > 0 ? v->xw_surface->width : 1; }
|
||||
if (win_h) { *win_h = v->xw_surface->height > 0 ? v->xw_surface->height : 1; }
|
||||
return 1;
|
||||
}
|
||||
if (v && v->xdg_surface && v->xdg_surface->surface) {
|
||||
int w = v->xdg_surface->surface->current.width;
|
||||
int h = v->xdg_surface->surface->current.height;
|
||||
if (win_x) { *win_x = v->x; }
|
||||
if (win_y) { *win_y = v->y; }
|
||||
if (win_w) { *win_w = w > 0 ? w : 1; }
|
||||
if (win_h) { *win_h = h > 0 ? h : 1; }
|
||||
return 1;
|
||||
}
|
||||
/* Frame buffer geometry. */
|
||||
struct wl_frame_buf *fb = frame_buf_find(win);
|
||||
if (fb) {
|
||||
if (win_x) { *win_x = fb->x; }
|
||||
if (win_y) { *win_y = fb->y; }
|
||||
if (win_w) { *win_w = fb->width; }
|
||||
if (win_h) { *win_h = fb->height; }
|
||||
return 1;
|
||||
}
|
||||
/* Synthetic child IDs (titlebar, buttons) — return minimal geometry. */
|
||||
if (win_x) { *win_x = 0; } if (win_y) { *win_y = 0; }
|
||||
if (win_w) { *win_w = 1; } if (win_h) { *win_h = 1; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wl_window_add_events(WNativeWindow win, unsigned long extra_mask) { (void)win; (void)extra_mask; }
|
||||
static void wl_window_select_events(WNativeWindow win, unsigned long mask) { (void)win; (void)mask; }
|
||||
|
||||
static void wl_window_shape_clear(WWindow *wwin) { (void)wwin; }
|
||||
void wl_window_shape_set(WWindow *wwin) { (void)wwin; }
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Client */
|
||||
|
|
|
|||
|
|
@ -423,3 +423,30 @@ int wl_overlay_text_width(WScreen *scr, const char *str, int n);
|
|||
|
||||
void wl_window_shape_set(WWindow *wwin);
|
||||
|
||||
|
||||
/* Window module declarations (extracted to wl_window.c) */
|
||||
Bool wl_window_fetch_name(WNativeWindow win, char **name_out);
|
||||
Bool wl_window_get_icon_name(WNativeWindow win, char **name_out);
|
||||
void *wl_window_get_icon_image(WNativeWindow win);
|
||||
void wl_window_map(WNativeWindow win);
|
||||
void wl_window_map_raised(WNativeWindow win);
|
||||
void wl_window_map_subwindows(WNativeWindow parent);
|
||||
void wl_window_unmap(WNativeWindow win);
|
||||
void wl_window_move(WNativeWindow win, int x, int y);
|
||||
void wl_window_resize(WNativeWindow win, int w, int h);
|
||||
void wl_window_set_border(WNativeWindow win, unsigned long pixel);
|
||||
void wl_window_set_border_width(WNativeWindow win, int width);
|
||||
void wl_window_set_save_under(WNativeWindow win, int save_under);
|
||||
void wl_noop_window_set_background(WNativeWindow win, unsigned long pixel);
|
||||
void wl_window_set_background_pixmap(WNativeWindow win, unsigned long pixmap);
|
||||
void wl_pixmap_free(unsigned long pixmap);
|
||||
void wl_window_clear(WNativeWindow win);
|
||||
int wl_window_get_rect(WNativeWindow win, int *win_x, int *win_y, int *win_w, int *win_h);
|
||||
void wl_window_add_events(WNativeWindow win, unsigned long extra_mask);
|
||||
void wl_window_select_events(WNativeWindow win, unsigned long mask);
|
||||
void wl_window_shape_clear(WWindow *wwin);
|
||||
|
||||
/* Functions shared among wl_*.c modules */
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,391 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pixman.h>
|
||||
#include <wayland-server-core.h>
|
||||
#include <wlr/types/wlr_scene.h>
|
||||
#include <wlr/types/wlr_xdg_shell.h>
|
||||
#include <wlr/xwayland.h>
|
||||
#include "../../screen.h"
|
||||
#include "wl_types.h"
|
||||
|
||||
/* Forward declarations from sibling modules. */
|
||||
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);
|
||||
struct wl_frame_buf *frame_buf_find(WNativeWindow id);
|
||||
struct wl_toplevel_view *wl_find_view_by_id(WNativeWindow id);
|
||||
pixman_image_t *get_window_image_from_x11(Display *x_display, WNativeWindow win);
|
||||
|
||||
|
||||
Bool
|
||||
wl_window_fetch_name(WNativeWindow win, char **name_out)
|
||||
{
|
||||
/* Phase 41: XDG title / Phase 17: XWayland title. */
|
||||
struct wl_toplevel_view *v = wl_find_view_by_id(win);
|
||||
const char *title = NULL;
|
||||
if (v && v->xw_surface)
|
||||
title = v->xw_surface->title;
|
||||
else if (v && v->xdg_surface && v->xdg_surface->toplevel)
|
||||
title = v->xdg_surface->toplevel->title;
|
||||
if (title) {
|
||||
*name_out = strdup(title);
|
||||
return True;
|
||||
}
|
||||
*name_out = NULL;
|
||||
return False;
|
||||
}
|
||||
Bool
|
||||
wl_window_get_icon_name(WNativeWindow win, char **name_out)
|
||||
{
|
||||
/* Phase 60: return title for icon labels; Phase 17: XWayland path. */
|
||||
struct wl_toplevel_view *v = wl_find_view_by_id(win);
|
||||
const char *title = NULL;
|
||||
if (v && v->xw_surface)
|
||||
title = v->xw_surface->title;
|
||||
else if (v && v->xdg_surface && v->xdg_surface->toplevel)
|
||||
title = v->xdg_surface->toplevel->title;
|
||||
if (title) {
|
||||
*name_out = strdup(title);
|
||||
return True;
|
||||
}
|
||||
*name_out = NULL;
|
||||
return False;
|
||||
}
|
||||
void *
|
||||
wl_window_get_icon_image(WNativeWindow win)
|
||||
{
|
||||
/* For XWayland clients, parse _NET_WM_ICON via the Xwayland display.
|
||||
* For native Wayland clients there is no equivalent (the upcoming
|
||||
* xdg-toplevel-icon protocol is not yet wired). */
|
||||
if (!wl_state.x_display) return NULL;
|
||||
return get_window_image_from_x11(wl_state.x_display, (WNativeWindow)win);
|
||||
}
|
||||
void
|
||||
wl_window_map(WNativeWindow win)
|
||||
{
|
||||
struct wl_toplevel_view *v = wl_find_view_by_id(win);
|
||||
if (v && v->scene_node) {
|
||||
wlr_scene_node_set_enabled(&v->scene_node->node, true);
|
||||
return;
|
||||
}
|
||||
if (v)
|
||||
return;
|
||||
/* Frame buffer: enable its scene node and children. */
|
||||
struct wl_frame_buf *fb = frame_buf_find(win);
|
||||
if (fb && fb->scene_buf) {
|
||||
/* If this is a child, only enable if parent is enabled */
|
||||
if (fb->parent_id) {
|
||||
struct wl_frame_buf *parent = frame_buf_find(fb->parent_id);
|
||||
if (parent && parent->scene_buf &&
|
||||
!parent->scene_buf->node.enabled)
|
||||
return; /* parent not visible yet */
|
||||
}
|
||||
wlr_scene_node_set_enabled(&fb->scene_buf->node, true);
|
||||
/* Raise the tree (raises entire window assembly together) */
|
||||
if (fb->tree) {
|
||||
wlr_scene_node_set_enabled(&fb->tree->node, true);
|
||||
wlr_scene_node_raise_to_top(&fb->tree->node);
|
||||
} else if (!fb->parent_id)
|
||||
wlr_scene_node_raise_to_top(&fb->scene_buf->node);
|
||||
/* Also enable children (and grandchildren) */
|
||||
struct wl_frame_buf *child;
|
||||
wl_list_for_each(child, &wl_state.frame_list, link) {
|
||||
if (child->parent_id == win && child->scene_buf) {
|
||||
wlr_scene_node_set_enabled(&child->scene_buf->node, true);
|
||||
struct wl_frame_buf *gc;
|
||||
wl_list_for_each(gc, &wl_state.frame_list, link) {
|
||||
if (gc->parent_id == child->id && gc->scene_buf)
|
||||
wlr_scene_node_set_enabled(&gc->scene_buf->node, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
void
|
||||
wl_window_map_raised(WNativeWindow win)
|
||||
{
|
||||
struct wl_toplevel_view *v = wl_find_view_by_id(win);
|
||||
if (v && v->scene_node) {
|
||||
wlr_scene_node_set_enabled(&v->scene_node->node, true);
|
||||
if (v->frame_id) {
|
||||
struct wl_frame_buf *fb = frame_buf_find(v->frame_id);
|
||||
if (fb && fb->tree) {
|
||||
wlr_scene_node_raise_to_top(&fb->tree->node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
wlr_scene_node_raise_to_top(&v->scene_node->node);
|
||||
return;
|
||||
}
|
||||
struct wl_frame_buf *fb = frame_buf_find(win);
|
||||
if (fb && fb->scene_buf) {
|
||||
wlr_scene_node_set_enabled(&fb->scene_buf->node, true);
|
||||
if (fb->tree) {
|
||||
/* Top-level frame: enable tree (decoration children become visible). */
|
||||
wlr_scene_node_set_enabled(&fb->tree->node, true);
|
||||
wlr_scene_node_raise_to_top(&fb->tree->node);
|
||||
} else {
|
||||
wlr_scene_node_raise_to_top(&fb->scene_buf->node);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void wl_window_map_subwindows(WNativeWindow parent)
|
||||
{
|
||||
(void)parent;
|
||||
/* Child windows are sub-regions of the frame buffer — no-op. */
|
||||
}
|
||||
void
|
||||
wl_window_unmap(WNativeWindow win)
|
||||
{
|
||||
struct wl_toplevel_view *v = wl_find_view_by_id(win);
|
||||
if (v && v->scene_node) {
|
||||
wlr_scene_node_set_enabled(&v->scene_node->node, false);
|
||||
return;
|
||||
}
|
||||
struct wl_frame_buf *fb = frame_buf_find(win);
|
||||
if (!fb) return;
|
||||
/* For top-level frames, disable the whole tree. This hides the frame
|
||||
* buffer, all child scene_bufs (titlebar, resizebar, buttons), and the
|
||||
* client surface reparented into fb->tree — atomically and irrevocably
|
||||
* until the frame is explicitly mapped again. Disabling individual
|
||||
* child nodes is insufficient because a subsequent wl_frame_paint can
|
||||
* re-enable them while the window is still iconified. */
|
||||
if (fb->tree) {
|
||||
wlr_scene_node_set_enabled(&fb->tree->node, false);
|
||||
return;
|
||||
}
|
||||
/* Child frame_buf: disable its scene_buf node only. */
|
||||
if (fb->scene_buf)
|
||||
wlr_scene_node_set_enabled(&fb->scene_buf->node, false);
|
||||
}
|
||||
|
||||
void wl_window_move(WNativeWindow win, int x, int y)
|
||||
{
|
||||
struct wl_toplevel_view *v = wl_find_view_by_id(win);
|
||||
if (v) {
|
||||
if (v->frame_id) {
|
||||
/* Client is a child of a frame — coords are relative to frame */
|
||||
v->frame_rel_x = x;
|
||||
v->frame_rel_y = y;
|
||||
struct wl_frame_buf *fb = frame_buf_find(v->frame_id);
|
||||
if (fb) {
|
||||
v->x = fb->x + x;
|
||||
v->y = fb->y + y;
|
||||
}
|
||||
} else {
|
||||
v->x = x; v->y = y;
|
||||
}
|
||||
if (v->scene_node) {
|
||||
/* Scene node is a child of the frame tree — use relative coords */
|
||||
if (v->frame_id)
|
||||
wlr_scene_node_set_position(&v->scene_node->node, x, y);
|
||||
else
|
||||
wlr_scene_node_set_position(&v->scene_node->node, v->x, v->y);
|
||||
}
|
||||
if (v->xw_surface)
|
||||
wlr_xwayland_surface_configure(v->xw_surface,
|
||||
(int16_t)v->x, (int16_t)v->y,
|
||||
v->xw_surface->width, v->xw_surface->height);
|
||||
/* Re-apply any popups whose parent is this toplevel so they
|
||||
* track the parent's position. */
|
||||
struct wl_toplevel_view *p;
|
||||
wl_list_for_each(p, &wl_state.toplevel_list, link) {
|
||||
if (p->popup && p->popup_parent
|
||||
&& wl_find_view_by_xdg_surface(p->popup_parent->base) == v) {
|
||||
wmaker_popup_apply(p);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
struct wl_frame_buf *fb = frame_buf_find(win);
|
||||
if (fb) {
|
||||
fb->rel_x = x; fb->rel_y = y;
|
||||
if (fb->parent_id) {
|
||||
struct wl_frame_buf *parent = frame_buf_find(fb->parent_id);
|
||||
if (parent) {
|
||||
fb->x = parent->x + x;
|
||||
fb->y = parent->y + y;
|
||||
} else {
|
||||
fb->x = x; fb->y = y;
|
||||
}
|
||||
/* Child frame_buf: reposition scene_buf at relative offset */
|
||||
if (fb->scene_buf)
|
||||
wlr_scene_node_set_position(&fb->scene_buf->node, x, y);
|
||||
} else {
|
||||
fb->x = x; fb->y = y;
|
||||
/* Top-level frame: move the tree (children follow automatically) */
|
||||
if (fb->tree)
|
||||
wlr_scene_node_set_position(&fb->tree->node, x, y);
|
||||
}
|
||||
/* Update absolute position tracking for hit-testing — recursively
|
||||
* for all descendants so grandchildren (e.g. WINGs panel inside
|
||||
* a fake_leader inside a WMaker frame) stay in sync. */
|
||||
frame_buf_update_children_abs(win);
|
||||
return;
|
||||
}
|
||||
}
|
||||
void wl_window_resize(WNativeWindow win, int w, int h)
|
||||
{
|
||||
struct wl_toplevel_view *v = wl_find_view_by_id(win);
|
||||
if (v) {
|
||||
if (w <= 0 || h <= 0) return;
|
||||
if (v->xw_surface) {
|
||||
wlr_xwayland_surface_configure(v->xw_surface,
|
||||
(int16_t)v->x, (int16_t)v->y, (uint16_t)w, (uint16_t)h);
|
||||
return;
|
||||
}
|
||||
if (!v->xdg_surface || !v->xdg_surface->toplevel) return;
|
||||
wlr_xdg_toplevel_set_size(v->xdg_surface->toplevel, (uint32_t)w, (uint32_t)h);
|
||||
wlr_xdg_surface_schedule_configure(v->xdg_surface);
|
||||
return;
|
||||
}
|
||||
struct wl_frame_buf *fb = frame_buf_find(win);
|
||||
if (fb && w > 0 && h > 0 && (w != fb->width || h != fb->height)) {
|
||||
pixman_image_unref(fb->image);
|
||||
fb->image = pixman_image_create_bits(PIXMAN_a8r8g8b8, w, h, NULL, 0);
|
||||
fb->width = w;
|
||||
fb->height = h;
|
||||
fb->base.width = w;
|
||||
fb->base.height = h;
|
||||
/* Update scene graph's cached buffer size for hit-testing. */
|
||||
if (fb->scene_buf)
|
||||
wlr_scene_buffer_set_dest_size(fb->scene_buf, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
void wl_window_set_border(WNativeWindow win, unsigned long pixel)
|
||||
{
|
||||
(void)win; (void)pixel; /* borders are drawn into the frame buffer */
|
||||
}
|
||||
|
||||
void wl_window_set_border_width(WNativeWindow win, int width)
|
||||
{
|
||||
(void)win; (void)width; /* no-op for native frames */
|
||||
}
|
||||
|
||||
void wl_window_set_save_under(WNativeWindow win, int save_under) { (void)win; (void)save_under; }
|
||||
void wl_noop_window_set_background(WNativeWindow win, unsigned long pixel) { (void)win; (void)pixel; }
|
||||
|
||||
extern void *W_GetViewBacking(unsigned long id);
|
||||
void wl_window_set_background_pixmap(WNativeWindow win, unsigned long pixmap)
|
||||
{
|
||||
if (pixmap == 0) return;
|
||||
struct wl_frame_buf *fb = frame_buf_find(win);
|
||||
pixman_image_t *dst_img = NULL;
|
||||
|
||||
if (fb && fb->image) {
|
||||
dst_img = fb->image;
|
||||
fb->bg_pixmap = (pixman_image_t *)(uintptr_t)pixmap;
|
||||
} else {
|
||||
dst_img = (pixman_image_t *)W_GetViewBacking(win);
|
||||
}
|
||||
if (!dst_img) return;
|
||||
|
||||
pixman_image_t *src = (pixman_image_t *)(uintptr_t)pixmap;
|
||||
int src_w = pixman_image_get_width(src);
|
||||
int src_h = pixman_image_get_height(src);
|
||||
|
||||
/* Blit source pixmap into frame_buf's image */
|
||||
pixman_image_composite32(PIXMAN_OP_SRC,
|
||||
src, /* src */
|
||||
NULL, /* mask */
|
||||
dst_img, /* dest */
|
||||
0, 0, /* src x,y */
|
||||
0, 0, /* mask x,y */
|
||||
0, 0, /* dest x,y */
|
||||
src_w < pixman_image_get_width(dst_img) ? src_w : pixman_image_get_width(dst_img),
|
||||
src_h < pixman_image_get_height(dst_img) ? src_h : pixman_image_get_height(dst_img));
|
||||
if (fb)
|
||||
wlr_scene_buffer_set_buffer_with_damage(fb->scene_buf, &fb->base, NULL);
|
||||
}
|
||||
void wl_pixmap_free(unsigned long pixmap)
|
||||
{
|
||||
if (pixmap == 0) return;
|
||||
pixman_image_t *img = (pixman_image_t *)(uintptr_t)pixmap;
|
||||
pixman_image_unref(img);
|
||||
}
|
||||
|
||||
void wl_window_clear(WNativeWindow win)
|
||||
{
|
||||
struct wl_frame_buf *fb = frame_buf_find(win);
|
||||
pixman_image_t *img = NULL;
|
||||
|
||||
if (fb && fb->image) {
|
||||
img = fb->image;
|
||||
} else {
|
||||
img = (pixman_image_t *)W_GetViewBacking(win);
|
||||
}
|
||||
if (!img) return;
|
||||
|
||||
int width = pixman_image_get_width(img);
|
||||
int height = pixman_image_get_height(img);
|
||||
|
||||
/* If a background pixmap is set, repaint from it (like XClearWindow) */
|
||||
if (fb && fb->bg_pixmap) {
|
||||
pixman_image_composite32(PIXMAN_OP_SRC,
|
||||
fb->bg_pixmap, NULL, img,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
width, height);
|
||||
} else {
|
||||
/* No background pixmap — fill with transparent black */
|
||||
int stride = pixman_image_get_stride(img);
|
||||
uint32_t *data = (uint32_t *)pixman_image_get_data(img);
|
||||
memset(data, 0, stride * height);
|
||||
}
|
||||
|
||||
/* Notify the scene buffer of the update */
|
||||
if (fb)
|
||||
wlr_scene_buffer_set_buffer_with_damage(fb->scene_buf, &fb->base, NULL);
|
||||
}
|
||||
int
|
||||
wl_window_get_rect(WNativeWindow win,
|
||||
int *win_x, int *win_y, int *win_w, int *win_h)
|
||||
{
|
||||
/* Phase 55: return real geometry for synthetic toplevel IDs. */
|
||||
if (win == WNATIVE_NONE) {
|
||||
if (win_x) { *win_x = 0; } if (win_y) { *win_y = 0; }
|
||||
if (win_w) { *win_w = 1; } if (win_h) { *win_h = 1; }
|
||||
return 0; /* invalid/none */
|
||||
}
|
||||
struct wl_toplevel_view *v = wl_find_view_by_id(win);
|
||||
/* Phase 17: XWayland geometry. */
|
||||
if (v && v->xw_surface) {
|
||||
if (win_x) { *win_x = v->x; }
|
||||
if (win_y) { *win_y = v->y; }
|
||||
if (win_w) { *win_w = v->xw_surface->width > 0 ? v->xw_surface->width : 1; }
|
||||
if (win_h) { *win_h = v->xw_surface->height > 0 ? v->xw_surface->height : 1; }
|
||||
return 1;
|
||||
}
|
||||
if (v && v->xdg_surface && v->xdg_surface->surface) {
|
||||
int w = v->xdg_surface->surface->current.width;
|
||||
int h = v->xdg_surface->surface->current.height;
|
||||
if (win_x) { *win_x = v->x; }
|
||||
if (win_y) { *win_y = v->y; }
|
||||
if (win_w) { *win_w = w > 0 ? w : 1; }
|
||||
if (win_h) { *win_h = h > 0 ? h : 1; }
|
||||
return 1;
|
||||
}
|
||||
/* Frame buffer geometry. */
|
||||
struct wl_frame_buf *fb = frame_buf_find(win);
|
||||
if (fb) {
|
||||
if (win_x) { *win_x = fb->x; }
|
||||
if (win_y) { *win_y = fb->y; }
|
||||
if (win_w) { *win_w = fb->width; }
|
||||
if (win_h) { *win_h = fb->height; }
|
||||
return 1;
|
||||
}
|
||||
/* Synthetic child IDs (titlebar, buttons) — return minimal geometry. */
|
||||
if (win_x) { *win_x = 0; } if (win_y) { *win_y = 0; }
|
||||
if (win_w) { *win_w = 1; } if (win_h) { *win_h = 1; }
|
||||
return 0;
|
||||
}
|
||||
void wl_window_add_events(WNativeWindow win, unsigned long extra_mask) { (void)win; (void)extra_mask; }
|
||||
void wl_window_select_events(WNativeWindow win, unsigned long mask) { (void)win; (void)mask; }
|
||||
void wl_window_shape_clear(WWindow *wwin) { (void)wwin; }
|
||||
void wl_window_shape_set(WWindow *wwin) { (void)wwin; }
|
||||
Loading…
Reference in New Issue