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)
This commit is contained in:
Window Maker 2026-05-23 15:13:38 +02:00
parent eeda48d24e
commit 11c5625d1e
4 changed files with 287 additions and 5 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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,
};

View File

@ -5,7 +5,10 @@
*/
#include "WINGsP.h"
#include "wwindow_p.h"
#include <X11/Xresource.h>
#include <X11/Xatom.h>
#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,
};