Implement WINGs dialog rendering infrastructure
- wl_client_reparent: create child frame_buf for WINGs views, connect backing pixman image so widgets paint into the scene graph - View lookup table: map synthetic IDs to W_View* for event dispatch - render_wl_pixmap_copy: detect view IDs and copy into backing image - W_ViewCommitBacking callback: commit frame_buf after WINGs paint - WMHandleEvent: use view table in Wayland mode (was always NULL) - wtextfield.c paintCursor: use render backend draw_line instead of XDrawLine (crash fix for Run dialog)
This commit is contained in:
parent
531dcf8235
commit
1d0b82eed5
|
|
@ -212,7 +212,8 @@ int WMHandleEvent(WMEvent * event)
|
|||
XEvent *xev = (XEvent *)event->_x11_raw;
|
||||
view = W_GetViewForXWindow(xev->xany.display, (Window)window);
|
||||
} else {
|
||||
view = NULL;
|
||||
extern W_View *W_GetViewForWindow(Window id);
|
||||
view = W_GetViewForWindow((Window)window);
|
||||
}
|
||||
|
||||
if (!view) {
|
||||
|
|
|
|||
|
|
@ -45,7 +45,16 @@ render_wl_pixmap_copy(void *rctx, WMDrawable src, WMDrawable dst,
|
|||
{
|
||||
(void)rctx;
|
||||
pixman_image_t *s = (pixman_image_t *)src;
|
||||
pixman_image_t *d = (pixman_image_t *)dst;
|
||||
pixman_image_t *d;
|
||||
|
||||
/* If dst is a WINGs view ID, look up its backing image */
|
||||
if ((unsigned long)dst >= 0x20000000 && (unsigned long)dst < 0x30000000) {
|
||||
extern void *W_GetViewBacking(unsigned long id);
|
||||
d = (pixman_image_t *)W_GetViewBacking((unsigned long)dst);
|
||||
if (!d) return; /* no backing store yet */
|
||||
} else {
|
||||
d = (pixman_image_t *)dst;
|
||||
}
|
||||
pixman_image_composite32(PIXMAN_OP_SRC, s, NULL, d,
|
||||
sx, sy, 0, 0, dx, dy, w, h);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -716,8 +716,13 @@ static void paintCursor(TextField * tPtr)
|
|||
printf("%d %d\n",cx,tPtr->cursorPosition);
|
||||
*/
|
||||
|
||||
XDrawLine(screen->display, tPtr->view->window, screen->xorGC,
|
||||
cx, tPtr->offsetWidth, cx, tPtr->view->size.height - tPtr->offsetWidth - 1);
|
||||
{
|
||||
const W_RenderBackend *R = screen->renderBackend;
|
||||
void *rctx = screen->renderBackendCtx;
|
||||
R->draw_line(rctx, (WMDrawable)tPtr->view->window, screen->black,
|
||||
cx, tPtr->offsetWidth, cx,
|
||||
tPtr->view->size.height - tPtr->offsetWidth - 1);
|
||||
}
|
||||
|
||||
W_SetPreeditPositon(tPtr->view, cx, 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,83 @@
|
|||
#define WL_VIEW_ID_BASE 0x20000000
|
||||
static unsigned int wl_view_next_id = WL_VIEW_ID_BASE;
|
||||
|
||||
/* Callback set by WM backend to commit frame_buf after paint */
|
||||
void (*W_ViewCommitBackingFn)(unsigned long id) = NULL;
|
||||
|
||||
/* Simple view lookup table (ID → W_View*) */
|
||||
#define VIEW_TABLE_SIZE 256
|
||||
static struct { Window id; W_View *view; void *backing; } view_table[VIEW_TABLE_SIZE];
|
||||
|
||||
static void view_table_put(Window id, W_View *view)
|
||||
{
|
||||
unsigned idx = ((unsigned)id) % VIEW_TABLE_SIZE;
|
||||
for (int i = 0; i < VIEW_TABLE_SIZE; i++) {
|
||||
unsigned slot = (idx + i) % VIEW_TABLE_SIZE;
|
||||
if (view_table[slot].id == 0 || view_table[slot].id == id) {
|
||||
view_table[slot].id = id;
|
||||
view_table[slot].view = view;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
W_View *W_GetViewForWindow(Window id)
|
||||
{
|
||||
unsigned idx = ((unsigned)id) % VIEW_TABLE_SIZE;
|
||||
for (int i = 0; i < VIEW_TABLE_SIZE; i++) {
|
||||
unsigned slot = (idx + i) % VIEW_TABLE_SIZE;
|
||||
if (view_table[slot].id == id)
|
||||
return view_table[slot].view;
|
||||
if (view_table[slot].id == 0)
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get/set backing pixman image for a view ID */
|
||||
void *W_GetViewBacking(Window id)
|
||||
{
|
||||
unsigned idx = ((unsigned)id) % VIEW_TABLE_SIZE;
|
||||
for (int i = 0; i < VIEW_TABLE_SIZE; i++) {
|
||||
unsigned slot = (idx + i) % VIEW_TABLE_SIZE;
|
||||
if (view_table[slot].id == id)
|
||||
return view_table[slot].backing;
|
||||
if (view_table[slot].id == 0)
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void W_SetViewBacking(Window id, void *img)
|
||||
{
|
||||
unsigned idx = ((unsigned)id) % VIEW_TABLE_SIZE;
|
||||
for (int i = 0; i < VIEW_TABLE_SIZE; i++) {
|
||||
unsigned slot = (idx + i) % VIEW_TABLE_SIZE;
|
||||
if (view_table[slot].id == id) {
|
||||
view_table[slot].backing = img;
|
||||
return;
|
||||
}
|
||||
if (view_table[slot].id == 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void view_table_remove(Window id)
|
||||
{
|
||||
unsigned idx = ((unsigned)id) % VIEW_TABLE_SIZE;
|
||||
for (int i = 0; i < VIEW_TABLE_SIZE; i++) {
|
||||
unsigned slot = (idx + i) % VIEW_TABLE_SIZE;
|
||||
if (view_table[slot].id == id) {
|
||||
view_table[slot].id = 0;
|
||||
view_table[slot].view = NULL;
|
||||
view_table[slot].backing = NULL;
|
||||
return;
|
||||
}
|
||||
if (view_table[slot].id == 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void *wl_screen_init(W_Screen *scr)
|
||||
{
|
||||
(void)scr;
|
||||
|
|
@ -27,6 +104,7 @@ static void wl_create_root(void *vctx, W_View *view)
|
|||
(void)vctx;
|
||||
|
||||
view->window = (Window)wl_view_next_id++;
|
||||
view_table_put(view->window, view);
|
||||
/* Default screen size — the WM backend will update this */
|
||||
view->size.width = 1920;
|
||||
view->size.height = 1080;
|
||||
|
|
@ -38,6 +116,7 @@ static void wl_realize(void *vctx, W_View *view)
|
|||
|
||||
/* Assign a synthetic ID so W_DispatchMessage doesn't skip this view */
|
||||
view->window = (Window)wl_view_next_id++;
|
||||
view_table_put(view->window, view);
|
||||
}
|
||||
|
||||
static void wl_noop(void *vctx, W_View *view)
|
||||
|
|
@ -117,6 +196,11 @@ static void wl_redisplay(void *vctx, W_View *view)
|
|||
ev._x11_raw = NULL;
|
||||
|
||||
WMHandleEvent(&ev);
|
||||
|
||||
/* Notify WM backend to commit the view's backing buffer */
|
||||
extern void (*W_ViewCommitBackingFn)(unsigned long id);
|
||||
if (W_ViewCommitBackingFn)
|
||||
W_ViewCommitBackingFn((unsigned long)view->window);
|
||||
}
|
||||
|
||||
static WMPoint wl_get_screen_position(void *vctx, W_View *view)
|
||||
|
|
|
|||
|
|
@ -2071,6 +2071,12 @@ wl_display_open(const char *name)
|
|||
* when the output fires (for nested Wayland, new_output fires during
|
||||
* wlr_backend_start via the host compositor roundtrip). */
|
||||
wl_state.scene = wlr_scene_create();
|
||||
/* Register commit callback for WINGs views (defined later in file) */
|
||||
{
|
||||
extern void (*W_ViewCommitBackingFn)(unsigned long id);
|
||||
extern void wl_view_commit_backing_impl(unsigned long id);
|
||||
W_ViewCommitBackingFn = wl_view_commit_backing_impl;
|
||||
}
|
||||
if (wl_state.scene)
|
||||
wwarning("wl_backend: scene graph created");
|
||||
else
|
||||
|
|
@ -5707,7 +5713,77 @@ wl_client_adopt_attributes(WNativeWindow win, unsigned long event_mask)
|
|||
|
||||
static void
|
||||
wl_client_reparent(WNativeWindow client, WNativeWindow new_parent, int x, int y)
|
||||
{ (void)client; (void)new_parent; (void)x; (void)y; }
|
||||
{
|
||||
/* For WINGs internal windows: create a child frame_buf so the dialog
|
||||
* content is visible in the scene graph. */
|
||||
if (client >= 0x20000000 && new_parent >= 0x10000000) {
|
||||
/* client is a WINGs view ID, new_parent is a frame_buf */
|
||||
struct wl_frame_buf *parent_fb = frame_buf_find(new_parent);
|
||||
if (!parent_fb) return;
|
||||
|
||||
/* Check if we already have a frame_buf for this client */
|
||||
struct wl_frame_buf *existing = frame_buf_find(client);
|
||||
if (existing) {
|
||||
/* Just update parent and position */
|
||||
existing->parent_id = new_parent;
|
||||
existing->rel_x = x;
|
||||
existing->rel_y = y;
|
||||
existing->x = parent_fb->x + x;
|
||||
existing->y = parent_fb->y + y;
|
||||
if (existing->scene_buf)
|
||||
wlr_scene_node_set_position(&existing->scene_buf->node,
|
||||
existing->x, existing->y);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create a new frame_buf for this WINGs view.
|
||||
* We don't know the size yet — use parent's content area. */
|
||||
int w = parent_fb->width;
|
||||
int h = parent_fb->height - y;
|
||||
if (w <= 0) w = 1;
|
||||
if (h <= 0) h = 1;
|
||||
|
||||
struct wl_frame_buf *fb = wmalloc(sizeof(*fb));
|
||||
memset(fb, 0, sizeof(*fb));
|
||||
|
||||
fb->image = pixman_image_create_bits(PIXMAN_a8r8g8b8, w, h, NULL, 0);
|
||||
if (!fb->image) { wfree(fb); return; }
|
||||
|
||||
wlr_buffer_init(&fb->base, &frame_buf_impl, w, h);
|
||||
|
||||
fb->id = client; /* use the WINGs view ID directly */
|
||||
fb->parent_id = new_parent;
|
||||
fb->rel_x = x;
|
||||
fb->rel_y = y;
|
||||
fb->x = parent_fb->x + x;
|
||||
fb->y = parent_fb->y + y;
|
||||
fb->width = w;
|
||||
fb->height = h;
|
||||
|
||||
if (wl_state.scene) {
|
||||
fb->scene_buf = wlr_scene_buffer_create(&wl_state.scene->tree,
|
||||
&fb->base);
|
||||
if (fb->scene_buf) {
|
||||
wlr_scene_node_set_position(&fb->scene_buf->node, fb->x, fb->y);
|
||||
wlr_scene_node_set_enabled(&fb->scene_buf->node, false);
|
||||
}
|
||||
}
|
||||
|
||||
wl_list_insert(&wl_state.frame_list, &fb->link);
|
||||
|
||||
/* Connect the WINGs view's backing store to this frame_buf's image */
|
||||
extern void W_SetViewBacking(unsigned long id, void *img);
|
||||
W_SetViewBacking((unsigned long)client, fb->image);
|
||||
}
|
||||
}
|
||||
|
||||
/* Called by WINGs after a view repaints — commit its frame_buf to scene graph */
|
||||
void wl_view_commit_backing_impl(unsigned long id)
|
||||
{
|
||||
struct wl_frame_buf *fb = frame_buf_find((WNativeWindow)id);
|
||||
if (fb && fb->scene_buf)
|
||||
wlr_scene_buffer_set_buffer(fb->scene_buf, &fb->base);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_client_synth_configure(WNativeWindow client_win,
|
||||
|
|
|
|||
Loading…
Reference in New Issue