WINGs Phase D: port wballoon, wpopupbutton, wtext to vtable

New vtable slots: pointer_grab, pointer_ungrab, bell, balloon_draw, text_init
All implemented in X11 backend, no-ops in Wayland backend.

wballoon.c: XTranslateCoordinates -> get_screen_position, showText -> balloon_draw
wpopupbutton.c: all 7 Xlib calls replaced (grabs, coords, flush)
wtext.c: XMapWindow, XBell, XGrabPointer, XUngrabPointer, cursor, GC init all ported
This commit is contained in:
Window Maker 2026-05-23 15:26:48 +02:00
parent 264679a2d1
commit 9eecb2511c
5 changed files with 89 additions and 50 deletions

View File

@ -650,6 +650,7 @@ typedef struct W_ViewBackend {
void (*bell)(void *vctx); void (*bell)(void *vctx);
void (*balloon_draw)(void *vctx, struct W_View *view, int x, int y, void (*balloon_draw)(void *vctx, struct W_View *view, int x, int y,
int w, int h, const char *text); int w, int h, const char *text);
void (*text_init)(void *vctx, struct W_View *view, void *stipple_gc_out);
} W_ViewBackend; } W_ViewBackend;
extern const W_ViewBackend W_ViewBackendX11; extern const W_ViewBackend W_ViewBackendX11;

View File

@ -441,7 +441,12 @@ static void popUpMenu(PopUpButton * bPtr)
if (WMGetArrayItemCount(bPtr->items) < 1) if (WMGetArrayItemCount(bPtr->items) < 1)
return; return;
XTranslateCoordinates(scr->display, bPtr->view->window, scr->rootWin, 0, 0, &x, &y, &dummyW); {
WMPoint pos = scr->viewBackend->get_screen_position(
scr->viewBackendCtx, bPtr->view);
x = pos.x;
y = pos.y;
}
if (bPtr->flags.pullsDown) { if (bPtr->flags.pullsDown) {
y += bPtr->view->size.height; y += bPtr->view->size.height;
@ -450,8 +455,7 @@ static void popUpMenu(PopUpButton * bPtr)
} }
W_MoveView(bPtr->menuView, x, y); W_MoveView(bPtr->menuView, x, y);
XSetWindowBackgroundPixmap(scr->display, bPtr->menuView->window, makeMenuPixmap(bPtr)); scr->viewBackend->redisplay(scr->viewBackendCtx, bPtr->menuView);
XClearWindow(scr->display, bPtr->menuView->window);
if (W_VIEW_WIDTH(bPtr->menuView) != W_VIEW_WIDTH(bPtr->view)) if (W_VIEW_WIDTH(bPtr->menuView) != W_VIEW_WIDTH(bPtr->view))
resizeMenu(bPtr); resizeMenu(bPtr);
@ -629,9 +633,8 @@ static void handleActionEvents(WMEvent * event, void *data)
bPtr->highlightedItem = -1; bPtr->highlightedItem = -1;
bPtr->flags.insideMenu = 0; bPtr->flags.insideMenu = 0;
} }
XGrabPointer(bPtr->view->screen->display, bPtr->menuView->window, bPtr->view->screen->viewBackend->pointer_grab(
False, ButtonReleaseMask | ButtonMotionMask | EnterWindowMask bPtr->view->screen->viewBackendCtx, bPtr->menuView, False, CurrentTime);
| LeaveWindowMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
break; break;
case WME_BUTTON_RELEASE: case WME_BUTTON_RELEASE:
@ -639,7 +642,8 @@ static void handleActionEvents(WMEvent * event, void *data)
event->u.button.button == WINGsConfiguration.mouseWheelDown) { event->u.button.button == WINGsConfiguration.mouseWheelDown) {
break; break;
} }
XUngrabPointer(bPtr->view->screen->display, event->u.button.time); bPtr->view->screen->viewBackend->pointer_ungrab(
bPtr->view->screen->viewBackendCtx, event->u.button.time);
if (!bPtr->flags.pullsDown) if (!bPtr->flags.pullsDown)
popDownMenu(bPtr); popDownMenu(bPtr);
@ -660,10 +664,10 @@ static void handleActionEvents(WMEvent * event, void *data)
if (bPtr->flags.pullsDown) { if (bPtr->flags.pullsDown) {
for (i = 0; i < MENU_BLINK_COUNT; i++) { for (i = 0; i < MENU_BLINK_COUNT; i++) {
paintMenuEntry(bPtr, bPtr->highlightedItem, False); paintMenuEntry(bPtr, bPtr->highlightedItem, False);
XSync(bPtr->view->screen->display, 0); bPtr->view->screen->viewBackend->flush(bPtr->view->screen->viewBackendCtx);
wusleep(MENU_BLINK_DELAY); wusleep(MENU_BLINK_DELAY);
paintMenuEntry(bPtr, bPtr->highlightedItem, True); paintMenuEntry(bPtr, bPtr->highlightedItem, True);
XSync(bPtr->view->screen->display, 0); bPtr->view->screen->viewBackend->flush(bPtr->view->screen->viewBackendCtx);
wusleep(MENU_BLINK_DELAY); wusleep(MENU_BLINK_DELAY);
} }
} }

View File

@ -629,7 +629,6 @@ static void paintText(Text * tPtr)
WMScreen *scr = tPtr->view->screen; WMScreen *scr = tPtr->view->screen;
const W_RenderBackend *R = scr->renderBackend; const W_RenderBackend *R = scr->renderBackend;
void *rctx = scr->renderBackendCtx; void *rctx = scr->renderBackendCtx;
Display *dpy = tPtr->view->screen->display;
Window win = tPtr->view->window; Window win = tPtr->view->window;
WMColor *color; WMColor *color;
@ -762,9 +761,8 @@ static void paintText(Text * tPtr)
if (!view->flags.realized) if (!view->flags.realized)
WMRealizeWidget(tb->d.widget); WMRealizeWidget(tb->d.widget);
if (!view->flags.mapped) { if (!view->flags.mapped) {
XMapWindow(view->screen->display, view->window); W_MapView(view);
XFlush(view->screen->display); view->screen->viewBackend->flush(view->screen->viewBackendCtx);
view->flags.mapped = 1;
} }
} }
@ -876,7 +874,8 @@ static void mouseOverObject(Text * tPtr, int x, int y)
{ {
XSetWindowAttributes attribs; XSetWindowAttributes attribs;
attribs.cursor = tPtr->view->attribs.cursor; attribs.cursor = tPtr->view->attribs.cursor;
XChangeWindowAttributes(tPtr->view->screen->display, tPtr->view->window, CWCursor, &attribs); tPtr->view->screen->viewBackend->set_cursor(
tPtr->view->screen->viewBackendCtx, tPtr->view, attribs.cursor);
} }
} }
@ -2331,7 +2330,7 @@ static void handleTextKeyPress(Text * tPtr, WMEvent * event)
WMShowTextRuler(tPtr, i); WMShowTextRuler(tPtr, i);
tPtr->flags.rulerShown = i; tPtr->flags.rulerShown = i;
} else if (control_pressed && *buffer == '\a') { } else if (control_pressed && *buffer == '\a') {
XBell(tPtr->view->screen->display, 0); tPtr->view->screen->viewBackend->bell(tPtr->view->screen->viewBackendCtx);
} else { } else {
WMRelayToNextResponder(tPtr->view, event); WMRelayToNextResponder(tPtr->view, event);
} }
@ -2391,7 +2390,6 @@ static void pasteText(WMView * view, Atom selection, Atom target, Time timestamp
static void handleActionEvents(WMEvent * event, void *data) static void handleActionEvents(WMEvent * event, void *data)
{ {
Text *tPtr = (Text *) data; Text *tPtr = (Text *) data;
Display *dpy = tPtr->view->screen->display;
KeySym ksym; KeySym ksym;
switch (event->type) { switch (event->type) {
@ -2403,10 +2401,9 @@ static void handleActionEvents(WMEvent * event, void *data)
} }
if (tPtr->flags.focused) { if (tPtr->flags.focused) {
XGrabPointer(dpy, W_VIEW(tPtr)->window, False, tPtr->view->screen->viewBackend->pointer_grab(
PointerMotionMask | ButtonPressMask | ButtonReleaseMask, tPtr->view->screen->viewBackendCtx,
GrabModeAsync, GrabModeAsync, None, W_VIEW(tPtr), False, CurrentTime);
tPtr->view->screen->invisibleCursor, CurrentTime);
tPtr->flags.pointerGrabbed = True; tPtr->flags.pointerGrabbed = True;
handleTextKeyPress(tPtr, event); handleTextKeyPress(tPtr, event);
@ -2426,7 +2423,8 @@ static void handleActionEvents(WMEvent * event, void *data)
if (tPtr->flags.pointerGrabbed) { if (tPtr->flags.pointerGrabbed) {
tPtr->flags.pointerGrabbed = False; tPtr->flags.pointerGrabbed = False;
XUngrabPointer(dpy, CurrentTime); tPtr->view->screen->viewBackend->pointer_ungrab(
tPtr->view->screen->viewBackendCtx, CurrentTime);
} }
if (tPtr->flags.waitingForSelection) if (tPtr->flags.waitingForSelection)
@ -2455,7 +2453,8 @@ static void handleActionEvents(WMEvent * event, void *data)
if (tPtr->flags.pointerGrabbed) { if (tPtr->flags.pointerGrabbed) {
tPtr->flags.pointerGrabbed = False; tPtr->flags.pointerGrabbed = False;
XUngrabPointer(dpy, CurrentTime); tPtr->view->screen->viewBackend->pointer_ungrab(
tPtr->view->screen->viewBackendCtx, CurrentTime);
break; break;
} }
@ -2526,7 +2525,7 @@ static void handleActionEvents(WMEvent * event, void *data)
int n; int n;
if (!tPtr->flags.editable) { if (!tPtr->flags.editable) {
XBell(dpy, 0); tPtr->view->screen->viewBackend->bell(tPtr->view->screen->viewBackendCtx);
break; break;
} }
@ -2565,7 +2564,8 @@ static void handleActionEvents(WMEvent * event, void *data)
case WME_BUTTON_RELEASE: case WME_BUTTON_RELEASE:
if (tPtr->flags.pointerGrabbed) { if (tPtr->flags.pointerGrabbed) {
tPtr->flags.pointerGrabbed = False; tPtr->flags.pointerGrabbed = False;
XUngrabPointer(dpy, CurrentTime); tPtr->view->screen->viewBackend->pointer_ungrab(
tPtr->view->screen->viewBackendCtx, CurrentTime);
break; break;
} }
@ -2976,9 +2976,7 @@ static WMArray *getXdndDestinationTypeArray(void)
WMText *WMCreateTextForDocumentType(WMWidget * parent, WMAction * parser, WMAction * writer) WMText *WMCreateTextForDocumentType(WMWidget * parent, WMAction * parser, WMAction * writer)
{ {
Text *tPtr; Text *tPtr;
Display *dpy;
WMScreen *scr; WMScreen *scr;
XGCValues gcv;
tPtr = wmalloc(sizeof(Text)); tPtr = wmalloc(sizeof(Text));
tPtr->widgetClass = WC_Text; tPtr->widgetClass = WC_Text;
@ -2989,20 +2987,8 @@ WMText *WMCreateTextForDocumentType(WMWidget * parent, WMAction * parser, WMActi
return NULL; return NULL;
} }
dpy = tPtr->view->screen->display;
scr = tPtr->view->screen; scr = tPtr->view->screen;
if (XA_Targets == None) {
/*
* Because the X protocol guaranties that the value will never change in
* the lifespan of the server, we query the values only the first time a
* widget is created
*/
XA_Targets = XInternAtom(dpy, "TARGETS", False);
XA_Format_Text = XInternAtom(dpy, "TEXT", False);
XA_Format_Compound_Text = XInternAtom(dpy, "COMPOUND_TEXT", False);
}
tPtr->view->self = tPtr; tPtr->view->self = tPtr;
tPtr->view->attribs.cursor = scr->textCursor; tPtr->view->attribs.cursor = scr->textCursor;
tPtr->view->attribFlags |= CWOverrideRedirect | CWCursor; tPtr->view->attribFlags |= CWOverrideRedirect | CWCursor;
@ -3013,15 +2999,8 @@ WMText *WMCreateTextForDocumentType(WMWidget * parent, WMAction * parser, WMActi
tPtr->bgColor = WMWhiteColor(scr); tPtr->bgColor = WMWhiteColor(scr);
W_SetViewBackgroundColor(tPtr->view, tPtr->bgColor); W_SetViewBackgroundColor(tPtr->view, tPtr->bgColor);
gcv.graphics_exposures = False; /* Platform-specific text widget init (atoms, stipple GC) */
gcv.foreground = W_PIXEL(scr->gray); scr->viewBackend->text_init(scr->viewBackendCtx, tPtr->view, (void *)&tPtr->stippledGC);
gcv.background = W_PIXEL(scr->darkGray);
gcv.fill_style = FillStippled;
/* why not use scr->stipple here? */
gcv.stipple = XCreateBitmapFromData(dpy, W_DRAWABLE(scr), STIPPLE_BITS, STIPPLE_WIDTH, STIPPLE_HEIGHT);
tPtr->stippledGC = XCreateGC(dpy, W_DRAWABLE(scr),
GCForeground | GCBackground | GCStipple
| GCFillStyle | GCGraphicsExposures, &gcv);
tPtr->ruler = NULL; tPtr->ruler = NULL;
tPtr->vS = NULL; tPtr->vS = NULL;

View File

@ -531,6 +531,11 @@ static char *wl_clipboard_fetch(void *vctx, int *len_out)
return NULL; return NULL;
} }
static void wl_text_init(void *vctx, W_View *view, void *stipple_gc_out)
{
(void)vctx; (void)view; (void)stipple_gc_out;
}
static void wl_balloon_draw(void *vctx, W_View *view, int x, int y, static void wl_balloon_draw(void *vctx, W_View *view, int x, int y,
int w, int h, const char *text) int w, int h, const char *text)
{ {
@ -614,4 +619,5 @@ const W_ViewBackend W_ViewBackendWL = {
.pointer_ungrab = NULL, .pointer_ungrab = NULL,
.bell = NULL, .bell = NULL,
.balloon_draw = wl_balloon_draw, .balloon_draw = wl_balloon_draw,
.text_init = wl_text_init,
}; };

View File

@ -234,6 +234,54 @@ static char *x11_clipboard_fetch(void *vctx, int *len_out)
return copy; return copy;
} }
static void x11_pointer_grab(void *vctx, W_View *view, int owner_events, unsigned long time)
{
W_Screen *scr = (W_Screen *)vctx;
XGrabPointer(scr->display, view->window, owner_events,
ButtonReleaseMask | ButtonMotionMask | EnterWindowMask | LeaveWindowMask,
GrabModeAsync, GrabModeAsync, None, None, time);
}
static void x11_pointer_ungrab(void *vctx, unsigned long time)
{
W_Screen *scr = (W_Screen *)vctx;
XUngrabPointer(scr->display, time);
}
static void x11_bell(void *vctx)
{
W_Screen *scr = (W_Screen *)vctx;
XBell(scr->display, 0);
}
static Atom XA_Targets = None;
static Atom XA_Format_Text = None;
static Atom XA_Format_Compound_Text = None;
static void x11_text_init(void *vctx, W_View *view, void *stipple_gc_out)
{
W_Screen *scr = (W_Screen *)vctx;
Display *dpy = scr->display;
GC *gc_out = (GC *)stipple_gc_out;
XGCValues gcv;
if (XA_Targets == None) {
XA_Targets = XInternAtom(dpy, "TARGETS", False);
XA_Format_Text = XInternAtom(dpy, "TEXT", False);
XA_Format_Compound_Text = XInternAtom(dpy, "COMPOUND_TEXT", False);
}
gcv.graphics_exposures = False;
gcv.foreground = W_PIXEL(scr->gray);
gcv.background = W_PIXEL(scr->darkGray);
gcv.fill_style = FillStippled;
gcv.stipple = XCreateBitmapFromData(dpy, W_DRAWABLE(scr),
"\xaa\x55\xaa\x55\xaa\x55\xaa\x55", 8, 8);
*gc_out = XCreateGC(dpy, W_DRAWABLE(scr),
GCForeground | GCBackground | GCStipple
| GCFillStyle | GCGraphicsExposures, &gcv);
}
static void x11_balloon_draw(void *vctx, W_View *view, int x, int y, static void x11_balloon_draw(void *vctx, W_View *view, int x, int y,
int w, int h, const char *text) int w, int h, const char *text)
{ {
@ -504,8 +552,9 @@ const W_ViewBackend W_ViewBackendX11 = {
.window_realize = x11_window_realize, .window_realize = x11_window_realize,
.window_set_geometry = x11_window_set_geometry, .window_set_geometry = x11_window_set_geometry,
.window_withdraw = x11_window_withdraw, .window_withdraw = x11_window_withdraw,
.pointer_grab = NULL, .pointer_grab = x11_pointer_grab,
.pointer_ungrab = NULL, .pointer_ungrab = x11_pointer_ungrab,
.bell = NULL, .bell = x11_bell,
.balloon_draw = x11_balloon_draw, .balloon_draw = x11_balloon_draw,
.text_init = x11_text_init,
}; };