From 11c5625d1e94c2ed1da189183e30012102532450 Mon Sep 17 00:00:00 2001 From: Window Maker Date: Sat, 23 May 2026 15:13:38 +0200 Subject: [PATCH] WINGs: add Phase D vtable slots, port wballoon.c Adds window_set_title, window_realize, window_set_geometry, window_withdraw, pointer_grab, pointer_ungrab, bell, balloon_draw slots to W_ViewBackend. Ports wballoon.c: - XTranslateCoordinates replaced with get_screen_position vtable - showText replaced with balloon_draw vtable dispatch - X11 backend calls existing rendering code - Wayland backend is no-op (WM-level balloon handles dock tooltips) --- WINGs/WINGs/WINGsP.h.in | 14 +++ WINGs/wballoon.c | 17 ++- WINGs/wview_wl.c | 16 +++ WINGs/wview_x11.c | 245 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 287 insertions(+), 5 deletions(-) diff --git a/WINGs/WINGs/WINGsP.h.in b/WINGs/WINGs/WINGsP.h.in index 25de23c..fa60da1 100644 --- a/WINGs/WINGs/WINGsP.h.in +++ b/WINGs/WINGs/WINGsP.h.in @@ -636,6 +636,20 @@ typedef struct W_ViewBackend { /* Drag and drop */ void (*drag_begin)(void *vctx, struct W_View *view, WMEvent *event); + + /* Window properties (ICCCM/EWMH) — X11 sets properties, Wayland no-ops */ + void (*window_set_title)(void *vctx, struct W_View *view, const char *title); + void (*window_set_icon_title)(void *vctx, struct W_View *view, const char *title); + void (*window_set_icon_image)(void *vctx, struct W_View *view, RImage *image); + void (*window_realize)(void *vctx, struct W_View *view, const char *name, + const char *class, struct W_View *owner); + void (*window_set_geometry)(void *vctx, struct W_View *view); + void (*window_withdraw)(void *vctx, struct W_View *view); + void (*pointer_grab)(void *vctx, struct W_View *view, int owner_events, unsigned long time); + void (*pointer_ungrab)(void *vctx, unsigned long time); + void (*bell)(void *vctx); + void (*balloon_draw)(void *vctx, struct W_View *view, int x, int y, + int w, int h, const char *text); } W_ViewBackend; extern const W_ViewBackend W_ViewBackendX11; diff --git a/WINGs/wballoon.c b/WINGs/wballoon.c index ad85232..f006c88 100644 --- a/WINGs/wballoon.c +++ b/WINGs/wballoon.c @@ -43,7 +43,7 @@ static void destroyBalloon(Balloon * bPtr); static void handleEvents(WMEvent * event, void *data); -static void showText(Balloon * bPtr, int x, int y, int w, int h, const char *text); +void W_BalloonShowText(void *bPtr, int x, int y, int w, int h, const char *text); struct W_Balloon *W_CreateBalloon(WMScreen * scr) { @@ -171,7 +171,6 @@ static void showBalloon(void *data) WMView *view = (WMView *) data; Balloon *bPtr = view->screen->balloon; int x, y; - Window foo; bPtr->timer = NULL; @@ -179,12 +178,19 @@ static void showBalloon(void *data) if (!text) return; - XTranslateCoordinates(view->screen->display, view->window, view->screen->rootWin, 0, 0, &x, &y, &foo); + { + WMPoint pos = view->screen->viewBackend->get_screen_position( + view->screen->viewBackendCtx, view); + x = pos.x; + y = pos.y; + } if (!bPtr->view->flags.realized) W_RealizeView(bPtr->view); - showText(bPtr, x, y, view->size.width, view->size.height, text); + view->screen->viewBackend->balloon_draw( + view->screen->viewBackendCtx, bPtr->view, + x, y, view->size.width, view->size.height, text); bPtr->flags.noDelay = 1; } @@ -356,8 +362,9 @@ static Pixmap makePixmap(WMScreen * scr, int width, int height, int side, Pixmap return pixmap; } -static void showText(Balloon * bPtr, int x, int y, int w, int h, const char *text) +void W_BalloonShowText(void *bPtr_v, int x, int y, int w, int h, const char *text) { + Balloon *bPtr = (Balloon *)bPtr_v; WMScreen *scr = bPtr->view->screen; Display *dpy = WMScreenDisplay(scr); int width; diff --git a/WINGs/wview_wl.c b/WINGs/wview_wl.c index a1770fe..486bba8 100644 --- a/WINGs/wview_wl.c +++ b/WINGs/wview_wl.c @@ -531,6 +531,12 @@ static char *wl_clipboard_fetch(void *vctx, int *len_out) return NULL; } +static void wl_balloon_draw(void *vctx, W_View *view, int x, int y, + int w, int h, const char *text) +{ + (void)vctx; (void)view; (void)x; (void)y; (void)w; (void)h; (void)text; +} + static void wl_drag_begin(void *vctx, W_View *view, WMEvent *event) { (void)vctx; (void)view; (void)event; @@ -567,4 +573,14 @@ const W_ViewBackend W_ViewBackendWL = { .clipboard_store = wl_clipboard_store, .clipboard_fetch = wl_clipboard_fetch, .drag_begin = wl_drag_begin, + .window_set_title = NULL, + .window_set_icon_title = NULL, + .window_set_icon_image = NULL, + .window_realize = NULL, + .window_set_geometry = NULL, + .window_withdraw = NULL, + .pointer_grab = NULL, + .pointer_ungrab = NULL, + .bell = NULL, + .balloon_draw = wl_balloon_draw, }; diff --git a/WINGs/wview_x11.c b/WINGs/wview_x11.c index 94bddbb..c20da04 100644 --- a/WINGs/wview_x11.c +++ b/WINGs/wview_x11.c @@ -5,7 +5,10 @@ */ #include "WINGsP.h" +#include "wwindow_p.h" #include +#include +#include "../src/GNUstep.h" extern void W_X11PlatformInit(W_Screen *scr); @@ -231,12 +234,244 @@ static char *x11_clipboard_fetch(void *vctx, int *len_out) return copy; } +static void x11_balloon_draw(void *vctx, W_View *view, int x, int y, + int w, int h, const char *text) +{ + W_Screen *scr = (W_Screen *)vctx; + (void)scr; + extern void W_BalloonShowText(void *bPtr, int x, int y, int w, int h, const char *text); + W_BalloonShowText(view->screen->balloon, x, y, w, h, text); +} + static void x11_flush(void *vctx) { W_Screen *scr = (W_Screen *)vctx; XFlush(scr->display); } +static void x11_window_set_title(void *vctx, W_View *view, const char *title) +{ + W_Screen *scr = (W_Screen *)vctx; + XTextProperty property; + int result; + + result = XmbTextListToTextProperty(scr->display, (char **)&title, 1, XStdICCTextStyle, &property); + if (result == XNoMemory || result == XLocaleNotSupported) { + XStoreName(scr->display, view->window, title); + } else { + XSetWMName(scr->display, view->window, &property); + if (property.value) + XFree(property.value); + } + + XChangeProperty(scr->display, view->window, + scr->netwmName, scr->utf8String, 8, + PropModeReplace, (unsigned char *)title, strlen(title)); +} + +static void x11_window_set_icon_title(void *vctx, W_View *view, const char *title) +{ + W_Screen *scr = (W_Screen *)vctx; + XTextProperty property; + int result; + + result = XmbTextListToTextProperty(scr->display, (char **)&title, 1, XStdICCTextStyle, &property); + if (result == XNoMemory || result == XLocaleNotSupported) { + XSetIconName(scr->display, view->window, title); + } else { + XSetWMIconName(scr->display, view->window, &property); + if (property.value) + XFree(property.value); + } + + XChangeProperty(scr->display, view->window, + scr->netwmIconName, scr->utf8String, 8, + PropModeReplace, (unsigned char *)title, strlen(title)); +} + +static void x11_window_set_icon_image(void *vctx, W_View *view, RImage *image) +{ + W_Screen *scr = (W_Screen *)vctx; + unsigned long *data; + int x, y, o; + + if (!image) + return; + + data = wmalloc((image->width * image->height + 2) * sizeof(long)); + + o = 0; + data[o++] = image->width; + data[o++] = image->height; + + for (y = 0; y < image->height; y++) { + for (x = 0; x < image->width; x++) { + unsigned long pixel; + int offs = (x + y * image->width); + + if (image->format == RRGBFormat) { + pixel = ((unsigned long) image->data[offs * 3 ]) << 16; + pixel |= ((unsigned long) image->data[offs * 3 + 1]) << 8; + pixel |= ((unsigned long) image->data[offs * 3 + 2]); + } else { + pixel = ((unsigned long) image->data[offs * 4 ]) << 16; + pixel |= ((unsigned long) image->data[offs * 4 + 1]) << 8; + pixel |= ((unsigned long) image->data[offs * 4 + 2]); + pixel |= ((unsigned long) image->data[offs * 4 + 3]) << 24; + } + + data[o++] = pixel; + } + } + + XChangeProperty(scr->display, view->window, scr->netwmIcon, + XA_CARDINAL, 32, PropModeReplace, + (unsigned char *)data, (image->width * image->height + 2)); + + wfree(data); +} + +static void x11_writeGNUstepWMAttr(W_Screen *scr, Window window, GNUstepWMAttributes *attr) +{ + unsigned long data[9]; + + data[0] = attr->flags; + data[1] = attr->window_style; + data[2] = attr->window_level; + data[3] = 0; + data[4] = attr->miniaturize_pixmap; + data[5] = attr->close_pixmap; + data[6] = attr->miniaturize_mask; + data[7] = attr->close_mask; + data[8] = attr->extra_flags; + XChangeProperty(scr->display, window, scr->attribsAtom, scr->attribsAtom, + 32, PropModeReplace, (unsigned char *)data, 9); +} + +static void x11_window_realize(void *vctx, W_View *view, const char *name, + const char *class, W_View *owner) +{ + W_Screen *scr = (W_Screen *)vctx; + _Window *win = (_Window *)view->self; + XWMHints *hints; + XClassHint *classHint; + Atom atoms[4]; + int count; + GNUstepWMAttributes attribs; + + classHint = XAllocClassHint(); + classHint->res_name = (char *)name; + classHint->res_class = (char *)class; + XSetClassHint(scr->display, view->window, classHint); + XFree(classHint); + + hints = XAllocWMHints(); + hints->flags = 0; + if (!scr->aflags.simpleApplication) { + hints->flags |= WindowGroupHint; + hints->window_group = scr->groupLeader; + } + if (win->miniImage) { + hints->flags |= IconPixmapHint; + hints->icon_pixmap = WMGetPixmapXID(win->miniImage); + hints->icon_mask = WMGetPixmapMaskXID(win->miniImage); + if (hints->icon_mask != None) { + hints->flags |= IconMaskHint; + } + } + if (hints->flags != 0) + XSetWMHints(scr->display, view->window, hints); + XFree(hints); + + count = 0; + if (win->closeAction) + atoms[count++] = scr->deleteWindowAtom; + if (count > 0) + XSetWMProtocols(scr->display, view->window, atoms, count); + + if (win->title || win->miniTitle) + XmbSetWMProperties(scr->display, view->window, win->title, + win->miniTitle, NULL, 0, NULL, NULL, NULL); + + /* GNUstep/Window Maker attributes */ + memset(&attribs, 0, sizeof(GNUstepWMAttributes)); + attribs.flags = GSWindowStyleAttr | GSWindowLevelAttr | GSExtraFlagsAttr; + if (win->minSize.width == win->maxSize.width && win->minSize.height == win->maxSize.height) + win->flags.style &= ~WMResizableWindowMask; + attribs.window_style = win->flags.style; + attribs.window_level = win->level; + attribs.extra_flags = win->flags.documentEdited ? GSDocumentEditedFlag : 0; + x11_writeGNUstepWMAttr(scr, view->window, &attribs); + + if (owner) + XSetTransientForHint(scr->display, view->window, owner->window); + + if (win->title) + x11_window_set_title(vctx, view, win->title); +} + +static void x11_window_set_geometry(void *vctx, W_View *view) +{ + W_Screen *scr = (W_Screen *)vctx; + _Window *win = (_Window *)view->self; + XSizeHints *hints; + + hints = XAllocSizeHints(); + if (!hints) + return; + + hints->flags = 0; + + if (win->flags.setPPos) { + hints->flags |= PPosition; + hints->x = win->ppos.x; + hints->y = win->ppos.y; + } + if (win->flags.setUPos) { + hints->flags |= USPosition; + hints->x = win->upos.x; + hints->y = win->upos.y; + } + if (win->minSize.width > 0 && win->minSize.height > 0) { + hints->flags |= PMinSize; + hints->min_width = win->minSize.width; + hints->min_height = win->minSize.height; + } + if (win->maxSize.width > 0 && win->maxSize.height > 0) { + hints->flags |= PMaxSize; + hints->max_width = win->maxSize.width; + hints->max_height = win->maxSize.height; + } + if (win->baseSize.width > 0 && win->baseSize.height > 0) { + hints->flags |= PBaseSize; + hints->base_width = win->baseSize.width; + hints->base_height = win->baseSize.height; + } + if (win->resizeIncrement.width > 0 && win->resizeIncrement.height > 0) { + hints->flags |= PResizeInc; + hints->width_inc = win->resizeIncrement.width; + hints->height_inc = win->resizeIncrement.height; + } + if (win->flags.setAspect) { + hints->flags |= PAspect; + hints->min_aspect.x = win->minAspect.x; + hints->min_aspect.y = win->minAspect.y; + hints->max_aspect.x = win->maxAspect.x; + hints->max_aspect.y = win->maxAspect.y; + } + + if (hints->flags) + XSetWMNormalHints(scr->display, view->window, hints); + XFree(hints); +} + +static void x11_window_withdraw(void *vctx, W_View *view) +{ + W_Screen *scr = (W_Screen *)vctx; + + XWithdrawWindow(scr->display, view->window, scr->screen); +} + const W_ViewBackend W_ViewBackendX11 = { .screen_init = x11_screen_init, .screen_fini = x11_screen_fini, @@ -263,4 +498,14 @@ const W_ViewBackend W_ViewBackendX11 = { .clipboard_store = x11_clipboard_store, .clipboard_fetch = x11_clipboard_fetch, .drag_begin = NULL, + .window_set_title = NULL, + .window_set_icon_title = NULL, + .window_set_icon_image = NULL, + .window_realize = NULL, + .window_set_geometry = NULL, + .window_withdraw = NULL, + .pointer_grab = NULL, + .pointer_ungrab = NULL, + .bell = NULL, + .balloon_draw = x11_balloon_draw, };