diff --git a/WINGs/wevent.c b/WINGs/wevent.c index 1236997..e71b811 100644 --- a/WINGs/wevent.c +++ b/WINGs/wevent.c @@ -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) { diff --git a/WINGs/wrender_wl.c b/WINGs/wrender_wl.c index bba5525..bdfab90 100644 --- a/WINGs/wrender_wl.c +++ b/WINGs/wrender_wl.c @@ -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); } diff --git a/WINGs/wtextfield.c b/WINGs/wtextfield.c index 763008d..bbca5bf 100644 --- a/WINGs/wtextfield.c +++ b/WINGs/wtextfield.c @@ -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); diff --git a/WINGs/wview_wl.c b/WINGs/wview_wl.c index c49c26c..b00e030 100644 --- a/WINGs/wview_wl.c +++ b/WINGs/wview_wl.c @@ -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) diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index 9d3f194..4f8030f 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -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,