/* Copyright 1989 GROUPE BULL -- See license conditions in file COPYRIGHT * Copyright 1989 Massachusetts Institute of Technology */ /**************************************************************\ * * * X11 BULL WINDOW MANAGER. * * * * MODULE FOR OPERATIONS THAT MAY BE CALLED FROM Lisp. * * * \**************************************************************/ /* include */ #include "EXTERN.h" #include "wool.h" #include "wl_atom.h" #include "gwm.h" #include "wl_number.h" #include "wl_string.h" #include "wl_client.h" #include "wl_menu.h" #include "wl_name.h" #include "wl_event.h" #include "wl_pixmap.h" /* local constants */ /* external */ extern XError(), NoXError(); extern WOB_METHOD ClientWindowClass[]; extern WOOL_OBJECT UserMoveWindow(), UserResizeWindow(); extern WOOL_OBJECT UserMoveSeveralWindows(); extern WOOL_OBJECT MwmLikeUserResizeWindow(); extern ClientWindow ClientWindowLeader(); /* routines */ char *NoRootError="Window function called on root window%s"; #define NoRoot(w) ((w)->status != RootStatus ? (w) : \ (wool_error(NoRootError, ""),w)) /* * GetTarget returns window having status in ancestors of current wob */ Wob GetTarget(flag) unsigned long flag; { Wob wob = TargetWob; while ((wob -> parent != NULL) && (wob -> status & flag) == 0) wob = wob -> parent; return wob; } /* * SetTarget makes TargetWob, TargetWindow and Context */ SetTarget(wob) Wob wob; { extern WOOL_Namespace ContextNamespace; TargetWob = wob; while (!(wob -> status & (TargetWindowStatus))) wob = wob -> parent; TargetWindow = (ClientWindow) wob; Context = TargetWindow -> screen; ContextNamespace -> current = Context -> screen; } WOOL_OBJECT MapWindow(argc, argv) int argc; WOOL_Number argv[]; { ClientWindow cw; if (argc) cw = (ClientWindow) argv[0] -> number; else cw = TargetWindow; ClientWindowMap(cw); return NIL; } WOOL_OBJECT UnmapWindow(argc, argv) int argc; WOOL_Number argv[]; { ClientWindow cw; if (argc) cw = (ClientWindow) argv[0] -> number; else cw = TargetWindow; ClientWindowUnmap(cw); return NIL; } WOOL_OBJECT IconifyWindow() { if (TargetWindow) { if (TargetWindow -> mapped) { XUnmapWindow(dpy, TargetWindow -> hook); if (TargetWindow -> client && !TargetWindow -> client_wob) XUnmapWindow(dpy, TargetWindow -> client); TargetWindow -> mapped = 0; } if (TargetWindow -> status & IconStatus) { /* de-iconify */ SetTarget(TargetWindow -> window); } else { /* iconify */ if (!(TargetWindow -> icon)) { if (!RealizeIconWindow(TargetWindow)) { ClientWindowMap(TargetWindow); wool_error("Error in wool code for decorating icon %s", ((WOOL_String) TargetWindow->cached_props->iconname)->string); return NIL; } } SetTarget(TargetWindow -> icon); } ClientWindowMap(TargetWindow); } return NIL; } /* move window returns () if Ok, else: * 0 if X problem with server/window * 1 if pointer was not on screen * 2 if user cancelled move * 3 if button was released before entering function */ WOOL_OBJECT MoveSeveralWindows(argc, argv) int argc; WOOL_Number argv[]; { ClientWindow cwl[255]; int i; for (i = 0; i < argc; i++) { must_be_number(argv[i], i); cwl[i] = (ClientWindow) argv[i]->number; } return UserMoveSeveralWindows(argc, cwl); } WOOL_OBJECT MoveWindow(argc, argv) int argc; WOOL_Number argv[]; { int i; ClientWindow cw = TargetWindow; for(i=0; i< argc; i++) /* MOVE HOOK */ must_be_number(argv[i], i); switch (argc) { case 1: cw = (ClientWindow) argv[0] -> number; case 0: return UserMoveWindow(cw); break; case 2: XMoveWindow(dpy, TargetWindow -> hook, TargetWindow -> box.x = argv[0] -> number, TargetWindow -> box.y = argv[1] -> number); SendSyntheticMoveEvent(TargetWindow); break; default: XMoveWindow(dpy, ((Wob) (argv[0] -> number)) -> hook, ((Wob) (argv[0] -> number)) -> box.x = argv[1] -> number, ((Wob) (argv[0] -> number)) -> box.y = argv[2] -> number); SendSyntheticMoveEvent(argv[0] -> number); break; } return NIL; } /* resize window returns () if Ok, else: * 0 if X problem with server/window * 1 if pointer was not on screen * 2 if user cancelled resize * 3 if button was released before entering function */ WOOL_OBJECT ResizeWindow(argc, argv) int argc; WOOL_Number argv[]; { int width, height; int i; ClientWindow cw = TargetWindow; for(i=0; i< argc; i++) must_be_number(argv[i], i); switch (argc) { case 1: cw = (ClientWindow) argv[0] -> number; case 0: if (cw -> client) if (GWM_resize_style) return MwmLikeUserResizeWindow(cw); else return UserResizeWindow(cw); break; case 2: if (TargetWindow -> client) width = argv[0] -> number; height = argv[1] -> number; dims_outer_to_inner(TargetWindow, &width, &height); conform_to_hints(&(TargetWindow -> cached_props -> normal_hints), &width, &height); XResizeWindow(dpy, TargetWindow -> client, width, height); ReconfigureClientWindow(TargetWindow, TargetWindow -> client); break; default: if (!(cw = ((ClientWindow) argv[0] -> number)) -> client) return NIL; width = argv[1] -> number; height = argv[2] -> number; dims_outer_to_inner(cw, &width, &height); conform_to_hints(&(cw -> cached_props -> normal_hints), &width, &height); XResizeWindow(dpy, cw -> client, width, height); ReconfigureClientWindow(cw, cw -> client); break; } return NIL; } /* * Raise window (optionally % other top-level window) */ WOOL_OBJECT RaiseWindow(argc, argv) int argc; WOOL_Number argv[]; { XWindowChanges values; switch (argc) { case 0: XRaiseWindow(dpy, TargetWindow -> hook); break; case 1: must_be_number(argv[0], 0); values.sibling = ((Wob) (argv[0] -> number)) -> hook; values.stack_mode = Above; XConfigureWindow(dpy, TargetWindow -> hook, CWStackMode | CWSibling, &values); break; } return NIL; } /* * Lower window (optionally % other top-level window) */ WOOL_OBJECT LowerWindow(argc, argv) int argc; WOOL_Number argv[]; { XWindowChanges values; switch (argc) { case 0: XLowerWindow(dpy, TargetWindow -> hook); break; case 1: must_be_number(argv[0], 0); values.sibling = ((Wob) (argv[0] -> number)) -> hook; values.stack_mode = Below; XConfigureWindow(dpy, TargetWindow -> hook, CWStackMode | CWSibling, &values); break; } return NIL; } WOOL_OBJECT KillWindow(argc, argv) int argc; WOOL_Number argv[]; { ClientWindow cw = TargetWindow; Wob wob; if (argc) cw = (ClientWindow) argv[0] -> number; /* kill always main window, not icon! */ cw = cw -> window; if (wob = (Wob) LookUpWob(cw -> client)) WOOL_send(WOOL_close, wob, (wob)); /* don't kill gwm! */ else if (cw -> client) XKillClient(dpy, cw -> client); return NIL; } WOOL_OBJECT ReDecorateWindow(argc, argv) int argc; WOOL_Number argv[]; { ClientWindow cw = TargetWindow; int new_target = 0; int was_mapped; Window window; WOOL_List window_group; if (argc) cw = (ClientWindow) (argv[0] -> number); if (cw && cw -> type == ClientWindowClass) { GWM_ProcessingExistingWindows = 1; if (cw == TargetWindow) new_target = 1; cw = cw -> window; window = cw -> client; if (was_mapped = cw -> mapped) ClientWindowUnmap(cw); SetTarget(cw); if (cw == ClientWindowLeader(cw)) { increase_reference(window_group = (WOOL_List) wool_window_group_get()); } else { window_group = 0; } UnDecorateWindow(cw, 1, 1); if (cw = (ClientWindow) DecorateWindow(window, Context->rootWob, 1, 1)) { if (was_mapped) { ClientWindowMap(cw); wool_process_unmap_events(window); } else { ClientWindowInitialMap(cw); } if (window_group && window_group != (WOOL_List) NIL) { int i; for (i=1; isize; i++) { AddWindowToGroupLeader( ((WOOL_Number)window_group->list[i]) ->number, cw); } } GWM_ProcessingExistingWindows = 0; if (new_target) SetTarget(cw); return (WOOL_OBJECT) WLNumber_make(cw); } else { XMapWindow(dpy, window); } decrease_reference(window_group); } return NIL; } /* returns NIL if OK * (pop-up [menu [item]]) * if menu = () takes default * item is the nth item in the menu (starting with 0). * If pointer is not on screen, do nothing and returns 0 * if cannot grab, returns 1, Ok= () * returns pointer (modifier + buttons status) mask */ WOOL_OBJECT PopMenu(argc, argv) int argc; WOOL_Menu argv[]; { WOOL_Menu wl_menu = (WOOL_Menu) TargetWob -> menu; int x, y, rx, ry, item = 0, i; Window root, child; Menu menu; int floating = 1; unsigned int mask; for (i = 0; i < argc; i++) { if (argv[i] -> type == WLNumber) item = ((WOOL_Number) argv[i]) -> number; else if (argv[i] -> type == WLMenu) wl_menu = argv[i]; else if (argv[i] == (WOOL_Menu) WA_here) floating = 0; } menu = wl_menu -> wob_menu; set_grab(Context -> rootWob); XQueryPointer(dpy, Context -> root, &root, &child, &x, &y, &rx, &ry, &mask); if (root == Context -> root) { if (floating) { PlaceMenu(item, menu, x, y, TargetWob); XMoveWindow(dpy, menu -> hook, menu -> box.x, menu -> box.y); } XMapRaised(dpy, menu -> hook); if (NIL == set_grab(menu)) { /* ok */ XSync(dpy, 0); wool_process_exposes(); menu -> parent = (TargetWob == (Wob) menu ? (Wob) Context -> rootWob :TargetWob) ; return NIL; } else { /* grab failed */ remove_grab(0); XUnmapWindow(dpy, menu -> hook); return (WOOL_OBJECT) WLNumber_make(1); } } else { /* not good screen */ remove_grab(0); return (WOOL_OBJECT) WLNumber_make(0); } } /* de-pop a menu previously popped by PopMenu */ WOOL_OBJECT UnpopMenu(argc, argv) int argc; WOOL_Menu argv[]; { Menu menu; WOOL_Menu wl_menu; menu = (Menu) GetTarget(MenuStatus); if (argc) { wl_menu = argv[0]; if (wl_menu == (WOOL_Menu) NIL) return NIL; if (wl_menu -> type == WLMenu) menu = wl_menu -> wob_menu; else menu = (Menu) ((WOOL_Number) wl_menu) -> number; } remove_grab(menu); XUnmapWindow(dpy, menu -> hook); menu -> parent = (Wob) Context -> rootWob; XSync(dpy, 0); return (WOOL_OBJECT) WLNumber_make(menu); } PlaceMenu(item, menu, x, y, wob) int item; /* item to place it */ Menu menu; /* the menu */ int x,y; /* mouse coordinates */ Wob wob; /* triggering wob */ { int oldx, oldy; int bw = 2 * menu -> box.borderwidth; if (item >= menu -> nbars) /* if out put to last */ item = menu -> nbars - 1; /* set pointer in item-th item */ oldx = menu -> box.x = x - menu -> box.width / 2; oldy = menu -> box.y = y - (menu -> bars[item] -> box.y + menu -> bars[item] -> box.height / 2); /* place full pop on screen */ if (menu -> box.x < 0) menu -> box.x = 0; if (menu -> box.y < 0) menu -> box.y = 0; if (menu -> box.x + menu -> box.width + bw > Context -> width) menu -> box.x = Context -> width - menu -> box.width - bw; if (menu -> box.y + menu -> box.height + bw > Context -> height) menu -> box.y = Context -> height - menu -> box.height - bw; if (!GWM_never_warp_pointer && (menu -> box.x != oldx || menu -> box.y != oldy)) XWarpPointer(dpy, None, None, 0, 0, 0, 0, menu -> box.x - oldx, menu -> box.y - oldy); } WOOL_OBJECT CirculateWindowsDown() { XCirculateSubwindowsDown(dpy, Context->root); return NIL; } WOOL_OBJECT CirculateWindowsUp() { XCirculateSubwindowsUp(dpy, Context->root); return NIL; } /* * the "current-window" functions */ WOOL_OBJECT wool_current_window() { if (TargetWindow) return (WOOL_OBJECT) WLNumber_make(TargetWindow); else return NIL; } WOOL_OBJECT wool_set_current_window(number) WOOL_Number number; { must_be_number(number, 0); if (WobIsValid(number->number) && ( (((Wob)(number->number))->type == ClientWindowClass) || (((Wob)(number->number))->type == ScreenClass))) { SetTarget(number -> number); return (WOOL_OBJECT) number; } else { return wool_error(INTERNAL_ERROR, "Not a Window!"); } } WOOL_OBJECT wool_current_window_is_mapped() { if (TargetWindow -> mapped) return TRU; else return NIL; } WOOL_OBJECT wool_current_window_name() { return (WOOL_OBJECT) NoRoot(TargetWindow) -> cached_props -> windowname; } WOOL_OBJECT wool_current_window_name_set(name) WOOL_String name; { XStoreName(dpy, NoRoot(TargetWindow) -> client, name -> string); return (WOOL_OBJECT) name; } WOOL_OBJECT wool_current_window_client_name() { return (WOOL_OBJECT) NoRoot(TargetWindow) -> cached_props -> clientname; } WOOL_OBJECT wool_current_window_client_class() { return (WOOL_OBJECT) NoRoot(TargetWindow) -> cached_props -> clientclass; } WOOL_OBJECT wool_current_window_machine_name() { return (WOOL_OBJECT) NoRoot(TargetWindow) -> cached_props -> machinename; } WOOL_OBJECT wool_current_window_icon_name() { return (WOOL_OBJECT) NoRoot(TargetWindow) -> cached_props -> iconname; } WOOL_OBJECT wool_current_window_icon_name_set(name) WOOL_String name; { XSetIconName(dpy, NoRoot(TargetWindow) -> client, name -> string); return (WOOL_OBJECT) name; } WOOL_OBJECT wool_current_window_geometry(measure) int measure; { Window root; unsigned int measures[6]; XGetGeometry(dpy, TargetWindow -> client, &root, (int *)&measures[0], (int *)&measures[1], &measures[2], &measures[3], &measures[4], &measures[5]); return (WOOL_OBJECT) WLNumber_make(measures[measure]); } /* sets Context to those of the root of a window */ int ContextOfXWindow(window) Window window; { Window root; unsigned int measures[6]; int result; XSetErrorHandler(NoXError); result = XGetGeometry(dpy, window, &root, (int *)&measures[0], (int *)&measures[1], &measures[2], &measures[3], &measures[4], &measures[5]); XSync(dpy, 0); XSetErrorHandler(XError); if (!result) return result; result = ScreenOfRoot(root); if (result == -1) return result; SetTarget(GWMManagedScreens[result] -> rootWob); return 0; } WOOL_OBJECT wool_current_client_x() { return wool_current_window_geometry(0); } WOOL_OBJECT wool_current_client_y() { return wool_current_window_geometry(1); } WOOL_OBJECT wool_current_client_width() { return wool_current_window_geometry(2); } WOOL_OBJECT wool_current_client_height() { return wool_current_window_geometry(3); } WOOL_OBJECT wool_current_client_borderwidth() { return wool_current_window_geometry(4); } WOOL_OBJECT wool_current_window_x() { return (WOOL_OBJECT) WLNumber_make(TargetWindow -> box.x); } WOOL_OBJECT wool_current_window_y() { return (WOOL_OBJECT) WLNumber_make(TargetWindow -> box.y); } WOOL_OBJECT wool_current_window_width() { return (WOOL_OBJECT) WLNumber_make(TargetWindow -> box.width); } WOOL_OBJECT wool_current_window_height() { return (WOOL_OBJECT) WLNumber_make(TargetWindow -> box.height); } /* returns client-managed icon window, if any, but first check that it exists */ WOOL_OBJECT wool_current_window_icon_window() { Window dummy_win; if (NoRoot(TargetWindow) -> cached_props -> wm_hints.flags & IconWindowHint && !TrapXErrors(XGetTransientForHint(dpy, TargetWindow -> cached_props -> wm_hints.icon_window, &dummy_win)) ) { return (WOOL_OBJECT) WLNumber_make( TargetWindow -> cached_props -> wm_hints.icon_window); } return NIL; } /* each time this function is called, construct the icon pixmap from the hints * (this to allow for applications changing their icons and user to change * color via the foreground and background variables) */ WOOL_OBJECT wool_current_window_icon_bitmap() { if (TargetWindow -> cached_props -> wm_hints.flags & IconPixmapHint) { WOOL_Pixmap pixmap = WLPixmap_make(TargetWindow -> cached_props -> wm_hints.icon_pixmap); if (TargetWindow -> cached_props -> wm_hints.flags & IconMaskHint) { Window root; int x_hot, y_hot; unsigned int width, height, bw, depth; GC gc; Pixmap mask = TargetWindow -> cached_props -> wm_hints.icon_mask; XGetGeometry(dpy, mask, &root, &x_hot, &y_hot, &width, &height, &bw, &depth); Trace('p', ("wool_current_window_icon_bitmap: create pixmap %d %d %d\n", width, height, depth)); pixmap -> mask = XCreatePixmap(dpy, root, width, height, depth); gc = XCreateGC(dpy, pixmap -> mask, 0, 0); XCopyArea(dpy, mask, pixmap -> mask, gc, 0, 0, width, height, 0, 0); } return (WOOL_OBJECT) pixmap; } else { return NIL; } } WOOL_OBJECT wool_current_window_icon_bitmap_id() { if (TargetWindow -> cached_props -> wm_hints.flags & IconPixmapHint) { return (WOOL_OBJECT) WLNumber_make(TargetWindow -> cached_props -> wm_hints.icon_pixmap); } else { return NIL; } } WOOL_OBJECT wool_current_window_US_position() { if (NoRoot(TargetWindow) -> status & IconStatus) { if (TargetWindow -> cached_props -> wm_hints.flags & IconPositionHint) return TRU; } else { if (TargetWindow && TargetWindow -> cached_props -> normal_hints.flags & USPosition) return TRU; } return NIL; } WOOL_OBJECT wool_current_window_US_size() { if (TargetWindow && TargetWindow -> cached_props -> normal_hints.flags & USSize) return TRU; else return NIL; } WOOL_OBJECT wool_current_window_P_position() { if (TargetWindow && TargetWindow -> cached_props -> normal_hints.flags & PPosition) return TRU; else return NIL; } WOOL_OBJECT wool_current_window_P_size() { if (TargetWindow && TargetWindow -> cached_props -> normal_hints.flags & PSize) return TRU; else return NIL; } WOOL_OBJECT wool_current_window_is_transient_for() { if (NoRoot(TargetWindow) && TargetWindow -> cached_props -> transient_for) { return TargetWindow -> cached_props -> transient_for; } else { return NIL; } } WOOL_OBJECT wool_window_map_as_icon_get() { if ((TargetWindow && TargetWindow -> cached_props -> wm_hints.flags & StateHint) && (TargetWindow -> cached_props -> wm_hints.initial_state == 3)) return TRU; else return NIL; } WOOL_OBJECT wool_window_map_as_icon_set(flag) WOOL_OBJECT flag; { if (TargetWindow) { TargetWindow -> cached_props -> wm_hints.flags |= StateHint; TargetWindow -> cached_props -> wm_hints.initial_state = (flag == NIL ? 1 : 3); } return flag; } /* * set focus on * current client if no arg (do nothing if input hint is false) * other window's client if arg * if arg = NIL, rootwindow */ WOOL_OBJECT wool_set_focus(argc, argv) int argc; WOOL_Number argv[]; { ClientWindow cw = TargetWindow; if (!cw) return NIL; if (argc) { if (argv[0] == (WOOL_Number) NIL) { XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); return TRU; } else { cw = (ClientWindow) argv[0] -> number; } } if (GWM_No_set_focus) return NIL; if (GWM_check_input_focus_flag || ((cw -> cached_props -> wm_hints.flags & InputHint) && (cw -> cached_props -> wm_hints.input) && cw -> client)) { TrapXErrors(XSetInputFocus(dpy, cw -> client, RevertToPointerRoot, CurrentTime)); } if (cw -> type == ClientWindowClass) { if (cw -> cached_props -> wm_take_focus) { send_protocol_message(cw -> client, XA_WM_TAKE_FOCUS, GWMTime, 0, 0); if ((cw -> cached_props ->wm_hints.flags & InputHint) && (cw -> cached_props -> wm_hints.input)) { TrapXErrors(XSetInputFocus(dpy, cw -> client, RevertToPointerRoot, CurrentTime)); } } } else { TrapXErrors(XSetInputFocus(dpy, cw -> hook, RevertToPointerRoot, CurrentTime)); } return TRU; } /* * returns [x y modifiers screen] */ WOOL_OBJECT wool_current_mouse_position() { unsigned int ptrmask; /* state of ptr when queried */ Window root, sub_window; int root_x, root_y, cur_x, cur_y; WOOL_List wl_list = wool_list_make(4); root=0; XQueryPointer(dpy, Context->root, &root, &sub_window, &root_x, &root_y, &cur_x, &cur_y, &ptrmask); increase_reference(wl_list -> list[0] = (WOOL_OBJECT) WLNumber_make(cur_x)); increase_reference(wl_list -> list[1] = (WOOL_OBJECT) WLNumber_make(cur_y)); increase_reference(wl_list -> list[2] = (WOOL_OBJECT) WLNumber_make(ptrmask)); increase_reference(wl_list -> list[3] = (WOOL_OBJECT) (root ? WLNumber_make(ScreenOfRoot(root)) : WLNumber_make(0))); return (WOOL_OBJECT) wl_list; } /* warps pointer to pos * (warp-pointer x y [window-relative-to]) */ WOOL_OBJECT wool_warp_pointer(argc, argv) int argc; WOOL_Number argv[]; { Window dest_w = None; if (argc < 2 || argc > 3) wool_error(BAD_NUMBER_OF_ARGS, argc); must_be_number(argv[0], 0); must_be_number(argv[1], 1); if (argc == 3) { must_be_number(argv[2], 2); dest_w = ((Wob) (argv[2] -> number)) -> hook; } if (!GWM_never_warp_pointer) { XWarpPointer(dpy, None, dest_w, 0, 0, 0, 0, argv[0] -> number, argv[1] -> number); } return NIL; } /* * logical size of a window is size divided by resize increments (+ base) */ WOOL_OBJECT wool_window_logical_size_get() { WOOL_List wl_list = wool_list_make(2); unsigned int w = 0, h = 0; if (TargetWindow -> client) { pixel_to_logical_size(&(TargetWindow -> cached_props -> normal_hints), TargetWindow -> inner_width, TargetWindow -> inner_height, &w, &h); } increase_reference(wl_list -> list[0] = (WOOL_OBJECT) WLNumber_make(w)); increase_reference(wl_list -> list[1] = (WOOL_OBJECT) WLNumber_make(h)); return (WOOL_OBJECT) wl_list; } WOOL_OBJECT wool_window_logical_size_set(list) WOOL_List list; { unsigned int w, h; if (list -> type != WLList || list == (WOOL_List) NIL || list -> size != 2 || list -> list[0] -> type != WLNumber || list -> list[1] -> type != WLNumber) bad_argument(list, 0, "list of two numbers"); logical_to_pixel_size(&(TargetWindow -> cached_props -> normal_hints), ((WOOL_Number) list -> list[0]) -> number, ((WOOL_Number) list -> list[1]) -> number, &w, &h); XResizeWindow(dpy, TargetWindow -> client, w, h); ReconfigureClientWindow(TargetWindow, TargetWindow -> client); return NIL; } /* moves a window at x,y and gravity * WARNING: xpt & yptr are pointers on SHORTS */ PlaceWinWithGravity(w, gravity, anchor_x, anchor_y, xptr, yptr, width, height, borderwidth) Window w; int gravity, anchor_x, anchor_y; short *xptr, *yptr; unsigned int width, height, borderwidth; { int x = *xptr, y = *yptr; switch((gravity - 1) % 3) { case 0: x = anchor_x; break; case 1: x = anchor_x - width/2 - borderwidth; break; case 2: x = anchor_x - width - 2*borderwidth; break; } switch((gravity - 1) / 3) { case 0: y = anchor_y; break; case 1: y = anchor_y - height/2 - borderwidth; break; case 2: y = anchor_y - height - 2*borderwidth; break; } if (*xptr != x || *yptr != y) { *xptr = x; *yptr = y; XMoveWindow(dpy, w, x, y); } }