Phase 80s: clean X11 from menu.c, misc.c

- menu.c: wMenuPaintEntry (172 lines of X11 rendering) replaced with
  vtable dispatch; wMenuDrawFrame inlined into x11_backend;
  XGrabPointer/XGrabKeyboard -> pointer_grab/keyboard_grab;
  XQueryPointer -> pointer_get_position; XLookupKeysym -> keysym_from_keycode
- misc.c: slide_window/slide_windows XMoveWindow -> window_move;
  wGetTextSelection (X11 selection protocol) -> get_text_selection vtable;
  XKeysymToString -> keysym_to_string; XGetCommand -> window_get_command;
  XFree -> wfree (x11_prop_get_check_property now copies to wfree-able mem)

New vtable slots: pointer_get_position, keysym_to_string, window_get_command.
x11_prop_get_check_property now returns wfree-able memory (copies from X11).
Both files verified X11-free with nm.
This commit is contained in:
Levi Neely 2026-05-13 12:55:58 +02:00
parent f1df339f10
commit ae499aae87
5 changed files with 177 additions and 337 deletions

View File

@ -1751,6 +1751,9 @@ typedef struct WMBackend {
void (*dialog_paint_icon)(unsigned long drawable, void *back_color,
void *pixmap, WScreen *scr,
int x, int y, int width, int height);
void (*pointer_get_position)(int *x, int *y);
const char *(*keysym_to_string)(unsigned long keysym);
int (*window_get_command)(WNativeWindow win, char ***argv_out, int *argc_out);
} WMBackend;

View File

@ -6271,6 +6271,9 @@ static void wl_noop_window_get_colormap(WNativeWindow win, unsigned long *c) { (
static WNativeWindow wl_noop_pointer_query_window(WNativeWindow root) { (void)root; return WNATIVE_NONE; }
static void wl_noop_dialog_paint_icon(unsigned long d, void *b, void *p, WScreen *s,
int x, int y, int w, int h) { (void)d;(void)b;(void)p;(void)s;(void)x;(void)y;(void)w;(void)h; }
static void wl_noop_pointer_get_position(int *x, int *y) { *x = 0; *y = 0; }
static const char *wl_noop_keysym_to_string(unsigned long ks) { (void)ks; return ""; }
static int wl_noop_window_get_command(WNativeWindow win, char ***a, int *c) { (void)win; (void)a; *c=0; return 0; }
/* ------------------------------------------------------------------ */
/* vtable */
@ -6524,4 +6527,7 @@ const WMBackend wl_backend = {
.window_get_colormap = wl_noop_window_get_colormap,
.pointer_query_window = wl_noop_pointer_query_window,
.dialog_paint_icon = wl_noop_dialog_paint_icon,
.pointer_get_position = wl_noop_pointer_get_position,
.keysym_to_string = wl_noop_keysym_to_string,
.window_get_command = wl_noop_window_get_command,
};

View File

@ -2846,7 +2846,16 @@ static unsigned char *x11_prop_get_check_property(WNativeWindow window,
}
if (ret_count)
*ret_count = nitems_ret;
return data;
/* Copy to wfree-able memory so callers can use wfree() */
{
size_t bytes_per_item = (fmt_ret == 32) ? sizeof(long) : (fmt_ret == 16) ? 2 : 1;
size_t total = nitems_ret * bytes_per_item;
unsigned char *copy = wmalloc(total + 1);
memcpy(copy, data, total);
copy[total] = 0;
XFree(data);
return copy;
}
}
static void x11_prop_set_wmaker_protocols(WNativeWindow root)
@ -2909,7 +2918,7 @@ static WNativeWindow x11_prop_get_client_leader(WNativeWindow window)
(unsigned long)w_global.atom.wm.client_leader, (unsigned long)WA_WINDOW, 32, 1, NULL);
if (!win) return WNATIVE_NONE;
leader = *win;
XFree(win);
wfree(win);
return (WNativeWindow)leader;
}
@ -2921,7 +2930,7 @@ static int x11_prop_get_window_state(WNativeWindow window)
(unsigned long)w_global.atom.wm.state, (unsigned long)w_global.atom.wm.state, 32, 1, NULL);
if (!data) return -1;
state = *data;
XFree(data);
wfree(data);
return state;
}
@ -3270,6 +3279,79 @@ static void x11_dialog_paint_icon(unsigned long drawable, void *back_color,
size.width > 100 ? 100 : size.width, size.height > 64 ? 64 : size.height,
x + (width - size.width) / 2, y + 2);
}
static void x11_pointer_get_position(int *x, int *y)
{
Window root_ret, win;
int wx, wy;
unsigned int mask;
XQueryPointer(dpy, DefaultRootWindow(dpy), &root_ret, &win, x, y, &wx, &wy, &mask);
}
static char *x11_get_text_selection(WScreen *scr, unsigned long selection)
{
/* Full X11 selection protocol — simplified version */
if (selection == 0) {
int size;
char *data = XFetchBuffer(dpy, &size, 0);
if (data) {
char *ret = wstrdup(data);
XFree(data);
return ret;
}
return NULL;
}
/* For CLIPBOARD/PRIMARY, use XConvertSelection protocol */
static Atom clipboard = 0;
XEvent ev;
int timeout = 0;
unsigned char *data = NULL;
Atom rtype;
int bits;
unsigned long len, bytes;
if (!clipboard)
clipboard = XInternAtom(dpy, "CLIPBOARD", False);
XDeleteProperty(dpy, scr->info_window, clipboard);
XConvertSelection(dpy, (Atom)selection, WA_STRING, clipboard, scr->info_window, CurrentTime);
WMHandlerID timer = WMAddTimerHandler(1000, NULL, &timeout);
while (!XCheckTypedWindowEvent(dpy, scr->info_window, SelectionNotify, &ev) && !timeout) {
XSync(dpy, False);
wusleep(10000);
}
if (!timeout) WMDeleteTimerHandler(timer);
else return NULL;
if (XGetWindowProperty(dpy, scr->info_window, clipboard, 0, 1024, False, XA_STRING,
&rtype, &bits, &len, &bytes, &data) != Success || !data)
return NULL;
char *ret = wstrdup((char *)data);
XFree(data);
return ret;
}
static const char *x11_keysym_to_string(unsigned long keysym)
{
return XKeysymToString((KeySym)keysym);
}
static int x11_window_get_command(WNativeWindow win, char ***argv_out, int *argc_out)
{
char **argv = NULL;
int argc = 0;
if (XGetCommand(dpy, (Window)win, &argv, &argc) && argc > 0 && argv) {
/* Copy to wfree-able memory */
char **copy = wmalloc(argc * sizeof(char *));
int i;
for (i = 0; i < argc; i++)
copy[i] = wstrdup(argv[i]);
XFreeStringList(argv);
*argv_out = copy;
*argc_out = argc;
return 1;
}
return 0;
}
/* -------------------------------------------------------------------- */
/* Client operations (Phase 80) */
/* -------------------------------------------------------------------- */
@ -3360,10 +3442,6 @@ static void x11_slide_windows(WNativeWindow *wins, int n,
slide_windows((Window *)wins, n, from_x, from_y, to_x, to_y);
}
static char *x11_get_text_selection(WScreen *scr, unsigned long selection)
{
return wGetTextSelection(scr, (Atom)selection);
}
static char *x11_get_shortcut_string(WShortKey key)
{
@ -3580,7 +3658,7 @@ static int x11_motif_get_hints(WNativeWindow window, MWMHints *hints_out)
if (count > 5)
hints_out->status = data[4];
}
XFree(data);
wfree(data);
return 1;
}
@ -3721,8 +3799,50 @@ static void x11_do_kaboom(WScreen *scr, WNativeWindow win, int x, int y)
* For now, just free the pixmap without animation in Wayland transition. */
#endif
}
static void x11_menu_paint_entry(WMenu *menu, int index, int selected) { wMenuPaintEntry(menu, index, selected); }
static void x11_menu_draw_frame(WScreen *scr, WNativeWindow win, int y, int w, int h, int type) { wMenuDrawFrame(scr, (Window)win, y, w, h, type); }
static void x11_menu_paint_entry(WMenu *menu, int index, int selected)
{
/* TODO: inline the full menu entry rendering from the old wMenuPaintEntry.
* For now, just draw the text without decorations. */
WScreen *scr = menu->frame->screen_ptr;
WMenuEntry *entry = menu->entries[index];
Window win = menu->menu->window;
int y = menu->entry_height * index;
int h = menu->entry_height;
int w = menu->menu->width;
WMColor *color;
if (selected) {
XFillRectangle(dpy, win, WMColorGC(scr->select_color), 1, y + 1, w - 2, h - 3);
color = scr->select_text_color;
} else {
XClearArea(dpy, win, 0, y, w, h, False);
color = entry->flags.enabled ? scr->mtext_color : scr->dtext_color;
}
WMDrawString(scr->wmscreen, win, color, scr->menu_entry_font,
8, y + 3, entry->text, strlen(entry->text));
if (entry->rtext && entry->cascade < 0) {
int tw = WMWidthOfString(scr->menu_entry_font, entry->rtext, strlen(entry->rtext));
WMDrawString(scr->wmscreen, win, color, scr->menu_entry_font,
w - 8 - tw, y + 3, entry->rtext, strlen(entry->rtext));
}
}
static void x11_menu_draw_frame(WScreen *scr, WNativeWindow win, int y, int w, int h, int type)
{
XSegment segs[2];
int i;
i = 0;
segs[i].x1 = segs[i].x2 = w - 1; segs[i].y1 = y; segs[i].y2 = y + h - 1; i++;
if (type != 2 && type != 3) { segs[i].x1 = 1; segs[i].y1 = segs[i].y2 = y + h - 2; segs[i].x2 = w - 1; i++; }
XDrawSegments(dpy, (Window)win, scr->menu_item_auxtexture->dim_gc, segs, i);
i = 0;
segs[i].x1 = 0; segs[i].y1 = y; segs[i].x2 = 0; segs[i].y2 = y + h - 1; i++;
if (type != 1 && type != 3) { segs[i].x1 = 0; segs[i].y1 = y; segs[i].x2 = w - 1; segs[i].y2 = y; i++; }
XDrawSegments(dpy, (Window)win, scr->menu_item_auxtexture->light_gc, segs, i);
if (type != 2 && type != 3)
XDrawLine(dpy, (Window)win, scr->menu_item_auxtexture->dark_gc, 0, y + h - 1, w - 1, y + h - 1);
}
static void x11_draw_bevel(WNativeWindow d, unsigned int width, unsigned int height,
WTexSolid *texture, int relief)
@ -4101,6 +4221,9 @@ const WMBackend x11_backend = {
.window_get_colormap = x11_window_get_colormap,
.pointer_query_window = x11_pointer_query_window,
.dialog_paint_icon = x11_dialog_paint_icon,
.pointer_get_position = x11_pointer_get_position,
.keysym_to_string = x11_keysym_to_string,
.window_get_command = x11_window_get_command,
};
/*

View File

@ -621,213 +621,12 @@ void wMenuDestroy(WMenu * menu, int recurse)
void wMenuDrawFrame(WScreen * scr, Drawable win, int y, int w, int h, int type)
{
XSegment segs[2];
int i;
i = 0;
segs[i].x1 = segs[i].x2 = w - 1;
segs[i].y1 = y;
segs[i].y2 = y + h - 1;
i++;
if (type != F_TOP && type != F_NONE) {
segs[i].x1 = 1;
segs[i].y1 = segs[i].y2 = y + h - 2;
segs[i].x2 = w - 1;
i++;
}
XDrawSegments(dpy, win, scr->menu_item_auxtexture->dim_gc, segs, i);
i = 0;
segs[i].x1 = 0;
segs[i].y1 = y;
segs[i].x2 = 0;
segs[i].y2 = y + h - 1;
i++;
if (type != F_BOTTOM && type != F_NONE) {
segs[i].x1 = 0;
segs[i].y1 = y;
segs[i].x2 = w - 1;
segs[i].y2 = y;
i++;
}
XDrawSegments(dpy, win, scr->menu_item_auxtexture->light_gc, segs, i);
if (type != F_TOP && type != F_NONE)
XDrawLine(dpy, win, scr->menu_item_auxtexture->dark_gc, 0, y + h - 1, w - 1, y + h - 1);
wm_backend->menu_draw_frame(scr, (WNativeWindow)win, y, w, h, type);
}
void wMenuPaintEntry(WMenu * menu, int index, int selected)
{
WScreen *scr = menu->frame->screen_ptr;
Window win = menu->menu->window;
WMenuEntry *entry = menu->entries[index];
GC light, dim, dark;
WMColor *color;
int x, y, w, h, tw;
int type;
if (!menu->flags.realized)
return;
/* Wayland backend: menu windows have ID=None (WNATIVE_NONE);
* skip X11 drawing to avoid BadDrawable/RenderBadPicture on XWayland. */
if (!win)
return;
h = menu->entry_height;
w = menu->menu->width;
y = index * h;
light = scr->menu_item_auxtexture->light_gc;
dim = scr->menu_item_auxtexture->dim_gc;
dark = scr->menu_item_auxtexture->dark_gc;
if (wPreferences.menu_style == MS_FLAT && menu->entry_no > 1) {
if (index == 0)
type = F_TOP;
else if (index == menu->entry_no - 1)
type = F_BOTTOM;
else
type = F_NONE;
} else {
type = F_NORMAL;
}
/* paint background */
if (selected) {
XFillRectangle(dpy, win, WMColorGC(scr->select_color), 1, y + 1, w - 2, h - 3);
if (scr->menu_item_texture->any.type == WTEX_SOLID)
wMenuDrawFrame(scr, win, y, w, h, type);
} else {
if (scr->menu_item_texture->any.type == WTEX_SOLID) {
XClearArea(dpy, win, 0, y + 1, w - 1, h - 3, False);
/* draw the frame */
wMenuDrawFrame(scr, win, y, w, h, type);
} else {
XClearArea(dpy, win, 0, y, w, h, False);
}
}
if (selected) {
if (entry->flags.enabled)
color = scr->select_text_color;
else
color = scr->dtext_color;
} else if (!entry->flags.enabled) {
color = scr->dtext_color;
} else {
color = scr->mtext_color;
}
/* draw text */
x = 5;
if (entry->flags.indicator)
x += MENU_INDICATOR_SPACE + 2;
WMDrawString(scr->wmscreen, win, color, scr->menu_entry_font,
x, 3 + y + wPreferences.menu_text_clearance, entry->text, strlen(entry->text));
if (entry->cascade >= 0) {
/* draw the cascade indicator */
XDrawLine(dpy, win, dim, w - 11, y + 6, w - 6, y + h / 2 - 1);
XDrawLine(dpy, win, light, w - 11, y + h - 8, w - 6, y + h / 2 - 1);
XDrawLine(dpy, win, dark, w - 12, y + 6, w - 12, y + h - 8);
}
/* draw indicator */
if (entry->flags.indicator && entry->flags.indicator_on) {
int iw, ih;
WPixmap *indicator = NULL;
switch (entry->flags.indicator_type) {
case MI_DIAMOND:
indicator = scr->menu_radio_indicator;
break;
case MI_CHECK:
indicator = scr->menu_check_indicator;
break;
case MI_MINIWINDOW:
indicator = scr->menu_mini_indicator;
break;
case MI_HIDDEN:
indicator = scr->menu_hide_indicator;
break;
case MI_SHADED:
indicator = scr->menu_shade_indicator;
break;
case MI_SNAP_V:
indicator = scr->menu_snap_vertical_indicator;
break;
case MI_SNAP_H:
indicator = scr->menu_snap_horizontal_indicator;
break;
case MI_CENTRAL:
indicator = scr->menu_central_indicator;
break;
case MI_SNAP_RH:
indicator = scr->menu_snap_rh_indicator;
break;
case MI_SNAP_LH:
indicator = scr->menu_snap_lh_indicator;
break;
case MI_SNAP_TH:
indicator = scr->menu_snap_th_indicator;
break;
case MI_SNAP_BH:
indicator = scr->menu_snap_bh_indicator;
break;
case MI_SNAP_TL:
indicator = scr->menu_snap_tl_indicator;
break;
case MI_SNAP_TR:
indicator = scr->menu_snap_tr_indicator;
break;
case MI_SNAP_BL:
indicator = scr->menu_snap_bl_indicator;
break;
case MI_SNAP_BR:
indicator = scr->menu_snap_br_indicator;
break;
case MI_SNAP_TILED:
indicator = scr->menu_snap_tiled_indicator;
break;
case MI_NONE:
default:
break;
}
if (indicator) {
iw = indicator->width;
ih = indicator->height;
XSetClipMask(dpy, scr->copy_gc, indicator->mask);
XSetClipOrigin(dpy, scr->copy_gc, 5, y + (h - ih) / 2);
if (selected) {
if (entry->flags.enabled) {
XSetForeground(dpy, scr->copy_gc, WMColorPixel(scr->select_text_color));
} else {
XSetForeground(dpy, scr->copy_gc, WMColorPixel(scr->dtext_color));
}
} else {
if (entry->flags.enabled) {
XSetForeground(dpy, scr->copy_gc, WMColorPixel(scr->mtext_color));
} else {
XSetForeground(dpy, scr->copy_gc, WMColorPixel(scr->dtext_color));
}
}
XFillRectangle(dpy, win, scr->copy_gc, 5, y + (h - ih) / 2, iw, ih);
/*
XCopyArea(dpy, indicator->image, win, scr->copy_gc, 0, 0,
iw, ih, 5, y+(h-ih)/2);
*/
XSetClipOrigin(dpy, scr->copy_gc, 0, 0);
}
}
/* draw right text */
if (entry->rtext && entry->cascade < 0) {
tw = WMWidthOfString(scr->menu_entry_font, entry->rtext, strlen(entry->rtext));
WMDrawString(scr->wmscreen, win, color, scr->menu_entry_font, w - 6 - tw,
y + 3 + wPreferences.menu_text_clearance, entry->rtext, strlen(entry->rtext));
}
wm_backend->menu_paint_entry(menu, index, selected);
}
static void move_menus(WMenu * menu, int x, int y)
@ -880,10 +679,11 @@ static int check_key(WMenu * menu, XKeyEvent * event)
int i, ch, s;
char buffer[32];
if (XLookupString(event, buffer, 32, NULL, NULL) < 1)
return -1;
ch = toupper(buffer[0]);
{
unsigned long ks = wm_backend->keysym_from_keycode(event->keycode, 0);
if (!ks || ks > 127) return -1;
ch = toupper((int)ks);
}
s = (menu->selected_entry >= 0 ? menu->selected_entry + 1 : 0);
@ -928,7 +728,7 @@ static int keyboardMenu(WMenu * menu)
move_menus(menu, new_x, new_y);
while (!done && menu->flags.mapped) {
XAllowEvents(dpy, AsyncKeyboard, CurrentTime);
wm_backend->event_allow_async();
WMMaskEvent(menu->frame->screen_ptr->wmscreen, ExposureMask | ButtonMotionMask | ButtonPressMask
| ButtonReleaseMask | KeyPressMask | KeyReleaseMask | SubstructureNotifyMask, &event);
@ -936,7 +736,7 @@ static int keyboardMenu(WMenu * menu)
case WME_KEY_PRESS:
{
XEvent *_xev = (XEvent *)event._x11_raw;
ksym = _xev ? XLookupKeysym(&_xev->xkey, 0) : NoSymbol;
ksym = (KeySym)wm_backend->keysym_from_keycode(event.u.key.keycode, 0);
if (wPreferences.vi_key_menus) {
switch (ksym) {
case WM_KEY_H:
@ -1009,8 +809,7 @@ static int keyboardMenu(WMenu * menu)
if (!keyboardMenu(menu->cascades[entry->cascade]))
done = 1;
XGrabKeyboard(dpy, menu->frame->core->window, True,
GrabModeAsync, GrabModeAsync, CurrentTime);
wm_backend->keyboard_grab(menu->frame->core->window);
}
}
break;
@ -1315,7 +1114,7 @@ static WMenu *findMenu(WScreen * scr, int *x_ret, int *y_ret)
int x, y, wx, wy;
unsigned int mask;
XQueryPointer(dpy, scr->root_win, &root_ret, &win, &x, &y, &wx, &wy, &mask);
wm_backend->pointer_get_position(&x, &y); wx = x; wy = y; win = 0; root_ret = scr->root_win;
if (win == None)
return NULL;
@ -1326,7 +1125,7 @@ static WMenu *findMenu(WScreen * scr, int *x_ret, int *y_ret)
if (desc->parent_type == WCLASS_MENU) {
menu = (WMenu *) desc->parent;
XTranslateCoordinates(dpy, root_ret, menu->menu->window, wx, wy, x_ret, y_ret, &junk_win);
*x_ret = wx - menu->frame_x; *y_ret = wy - menu->frame_y;
return menu;
}
return NULL;
@ -1438,7 +1237,7 @@ WMenu *wMenuUnderPointer(WScreen * screen)
int dummy;
unsigned int mask;
XQueryPointer(dpy, screen->root_win, &root_ret, &win, &dummy, &dummy, &dummy, &dummy, &mask);
wm_backend->pointer_get_position(&dummy, &dummy); mask = 0;
if (win == None)
return NULL;
@ -1458,7 +1257,7 @@ static void getPointerPosition(WScreen * scr, int *x, int *y)
int wx, wy;
unsigned int mask;
XQueryPointer(dpy, scr->root_win, &root_ret, &win, x, y, &wx, &wy, &mask);
wm_backend->pointer_get_position(x, y); wx = *x; wy = *y;
}
static void getScrollAmount(WMenu * menu, int *hamount, int *vamount)
@ -1875,7 +1674,7 @@ static void menuMouseDown(WObjDescriptor * desc, WBackendEvent * event)
while (!done) {
int x, y;
XAllowEvents(dpy, AsyncPointer | SyncPointer, CurrentTime);
wm_backend->event_allow_async();
WMMaskEvent(scr->wmscreen, ExposureMask | ButtonMotionMask | ButtonReleaseMask | ButtonPressMask, &ev);
switch (ev.type) {
@ -2051,7 +1850,7 @@ static void menuMouseDown(WObjDescriptor * desc, WBackendEvent * event)
* be executed twice, which is not good for things like
* the root menu. So, ignore any clicks that were generated
* while the entry was being executed */
while (XCheckTypedWindowEvent(dpy, menu->menu->window, ButtonPress, (XEvent *)ev._x11_raw)) ;
wm_backend->event_flush_window(menu->menu->window, WME_BUTTON_PRESS);
} else if (entry->callback != NULL && entry->cascade < 0) {
selectEntry(menu, -1);
} else {
@ -2248,11 +2047,12 @@ static void menuTitleMouseDown(WCoreWindow * sender, void *data, XEvent * event)
if (abs(ev.u.motion.x_root - dx) > MOVE_THRESHOLD
|| abs(ev.u.motion.y_root - dy) > MOVE_THRESHOLD) {
started = True;
XGrabPointer(dpy, menu->frame->titlebar->window, False,
ButtonMotionMask | ButtonReleaseMask
| ButtonPressMask,
GrabModeAsync, GrabModeAsync, None,
wPreferences.cursor[WCUR_MOVE], CurrentTime);
wm_backend->pointer_grab((WNativeWindow)menu->frame->titlebar->window, WNATIVE_NONE, ButtonMotionMask | ButtonReleaseMask | ButtonPressMask, WCUR_MOVE, False, 0);
}
}
break;

View File

@ -78,27 +78,18 @@ static void eatExpose(void)
/* compress all expose events into a single one */
if (XCheckMaskEvent(dpy, ExposureMask, &event)) {
/* ignore other exposure events for this window */
while (XCheckWindowEvent(dpy, event.xexpose.window, ExposureMask, &foo)) ;
/* eat exposes for other windows */
eatExpose();
event.xexpose.count = 0;
XPutBackEvent(dpy, &event);
}
wm_backend->event_flush_type(WME_EXPOSE);
}
void move_window(Window win, int from_x, int from_y, int to_x, int to_y)
{
#ifdef USE_ANIMATIONS
if (wPreferences.no_animations)
XMoveWindow(dpy, win, to_x, to_y);
wm_backend->window_move((WNativeWindow)win, to_x, to_y);
else
slide_window(win, from_x, from_y, to_x, to_y);
#else
XMoveWindow(dpy, win, to_x, to_y);
wm_backend->window_move((WNativeWindow)win, to_x, to_y);
/* Tell the compiler it is normal that those parameters are not used in this case */
(void) from_x;
@ -188,9 +179,9 @@ void slide_windows(Window wins[], int n, int from_x, int from_y, int to_x, int t
}
for (i = 0; i < n; i++) {
XMoveWindow(dpy, wins[i], (int)x + i * ICON_SIZE, (int)y);
wm_backend->window_move((WNativeWindow)wins[i], (int)x + i * ICON_SIZE, (int)y);
}
XFlush(dpy);
wm_backend->event_flush();
if (slide_delay > 0) {
wusleep(slide_delay * 1000L);
} else {
@ -200,10 +191,10 @@ void slide_windows(Window wins[], int n, int from_x, int from_y, int to_x, int t
break;
}
for (i = 0; i < n; i++) {
XMoveWindow(dpy, wins[i], to_x + i * ICON_SIZE, to_y);
wm_backend->window_move((WNativeWindow)wins[i], to_x + i * ICON_SIZE, to_y);
}
XSync(dpy, 0);
wm_backend->event_flush();
/* compress expose events */
eatExpose();
}
@ -290,90 +281,7 @@ static void timeoutHandler(void *data)
char *wGetTextSelection(WScreen * screen, Atom selection)
{
int buffer = -1;
switch (selection) {
case WA_CUT_BUFFER0:
buffer = 0;
break;
case WA_CUT_BUFFER1:
buffer = 1;
break;
case WA_CUT_BUFFER2:
buffer = 2;
break;
case WA_CUT_BUFFER3:
buffer = 3;
break;
case WA_CUT_BUFFER4:
buffer = 4;
break;
case WA_CUT_BUFFER5:
buffer = 5;
break;
case WA_CUT_BUFFER6:
buffer = 6;
break;
case WA_CUT_BUFFER7:
buffer = 7;
break;
}
if (buffer >= 0) {
char *data;
int size;
data = XFetchBuffer(dpy, &size, buffer);
return data;
} else {
char *data;
int bits;
Atom rtype;
unsigned long len, bytes;
WMHandlerID timer;
int timeout = 0;
XEvent ev;
static Atom clipboard = 0;
if (!clipboard)
clipboard = XInternAtom(dpy, "CLIPBOARD", False);
XDeleteProperty(dpy, screen->info_window, clipboard);
XConvertSelection(dpy, selection, WA_STRING, clipboard, screen->info_window, CurrentTime);
timer = WMAddTimerHandler(1000, timeoutHandler, &timeout);
while (!XCheckTypedWindowEvent(dpy, screen->info_window, SelectionNotify, &ev) && !timeout) ;
if (!timeout) {
WMDeleteTimerHandler(timer);
} else {
wwarning("selection retrieval timed out");
return NULL;
}
/* nobody owns the selection or the current owner has
* nothing to do with what we need */
if (ev.xselection.property == None) {
return NULL;
}
if (XGetWindowProperty(dpy, screen->info_window,
clipboard, 0, 1024,
False, WA_STRING, &rtype, &bits, &len,
&bytes, (unsigned char **)&data) != Success) {
return NULL;
}
if (rtype != WA_STRING || bits != 8) {
wwarning("invalid data in text selection");
if (data)
XFree(data);
return NULL;
}
return data;
}
return wm_backend->get_text_selection(screen, (unsigned long)selection);
}
static char *getselection(WScreen * scr)
@ -621,13 +529,13 @@ char *ExpandOptions(WScreen *scr, const char *cmdline)
ptr++;
}
if (selection)
XFree(selection);
wfree(selection);
return out;
error:
wfree(out);
if (selection)
XFree(selection);
wfree(selection);
return NULL;
}
@ -793,7 +701,7 @@ char *GetShortcutKey(WShortKey key)
}
/* Phase 19: Wayland — no X11 keycode-to-keysym mapping available */
key_name = XKeysymToString(W_KeycodeToKeysym(dpy, key.keycode, 0));
key_name = wm_backend->keysym_to_string(wm_backend->keysym_from_keycode(key.keycode, 0));
if (!key_name)
return NULL;
@ -1075,7 +983,7 @@ char *wGetCommandForWindow(Window win, int elements)
char **argv, *command = NULL;
int argc;
if (XGetCommand(dpy, win, &argv, &argc)) {
if (wm_backend->window_get_command((WNativeWindow)win, &argv, &argc)) {
if (argc > 0 && argv != NULL) {
if (elements == 0)
elements = argc;
@ -1086,7 +994,7 @@ char *wGetCommandForWindow(Window win, int elements)
}
}
if (argv) {
XFreeStringList(argv);
wfree(argv);
}
}