/* * wmgr_deco.c: Find out size/offset of window manager's decoration * * $Id: wmgr_deco.c,v 1.4 1997/03/17 00:09:40 mb Exp mb $ * * Copyright (c) 1996 Martin Buck * Read COPYING for more information * */ #include #include #include #include #include "misc.h" #include "wmgr_deco.h" #define MAX_BORDER 50 #define MAX_REPARENT_DELAY 10 int wmgr_get_size(Display *dpy, Window tl_win, wmgr_deco_t *wmgr) { static const char *atom_names[] = { "__WM_ROOT", "__SWM_ROOT", NULL }; const char **atom_name; Window vroot, wm_win, root, parent, *children, wdummy; Atom vroot_atom; int nchildren, wm_wf, wm_hf, wm_xf, wm_yf, wf, hf, xf, yf, wm_border, idummy; int lb, rb, tb, bb; /* Try to find a virtual root window by checking the __(S)WM_ROOT-atom (it should contain its * window ID), otherwise assume there's no virtual root window */ vroot = None; for (atom_name = atom_names; *atom_name; atom_name++) { if ((vroot_atom = XInternAtom(dpy, *atom_name, True)) != None) { unsigned char *property; Atom type; int format; unsigned long nitems, after; if (XGetWindowProperty(dpy, tl_win, vroot_atom, 0, 1, False, XA_WINDOW, &type, &format, &nitems, &after, &property) == Success) { if (type == XA_WINDOW && format == 32 && nitems == 1 && after == 0) { vroot = *((Window*)property); #ifdef DEBUG_WMGR fprintf(stderr, "wmgr_get_size: %s property found, virtual root is 0x%lx\n", *atom_name, (unsigned long)vroot); #endif XFree(property); break; } else { #ifdef DEBUG_WMGR if (type == None) { fprintf(stderr, "wmgr_get_size: no %s property found for toplevel window\n", *atom_name); } else { fprintf(stderr, "wmgr_get_size: ignoring bogus %s property\n", *atom_name); } #endif XFree(property); } #ifdef DEBUG_WMGR } else { fprintf(stderr, "wmgr_get_size: XGetWindowProperty(%s) failed\n", *atom_name); #endif } #ifdef DEBUG_WMGR } else { fprintf(stderr, "wmgr_get_size: %s atom doesn't exist\n", *atom_name); #endif } } /* Climb up window tree starting at our main window until we hit the (virtual) root window. * We assume that the wm's decoration window is a child of the root window. */ wm_win = tl_win; while (XQueryTree(dpy, wm_win, &root, &parent, &children, &nchildren)) { XFree(children); if (parent == root || (vroot != None && parent == vroot)) break; wm_win = parent; } /* If we're still at our main window, it obviously hasn't been reparented, so we give up */ if (wm_win == tl_win) { #ifdef DEBUG_WMGR fprintf(stderr, "wmgr_get_size: couldn't find wm's decoration window, giving up\n"); #endif return WMGR_NODECO; } /* Get size & absolute coordinates of our main window and its decoration window */ XGetGeometry(dpy, wm_win, &wdummy, &idummy, &idummy, &wm_wf, &wm_hf, &wm_border, &idummy); XTranslateCoordinates(dpy, wm_win, root, 0, 0, &wm_xf, &wm_yf, &wdummy); XGetGeometry(dpy, tl_win, &wdummy, &idummy, &idummy, &wf, &hf, &idummy, &idummy); XTranslateCoordinates(dpy, tl_win, root, 0, 0, &xf, &yf, &wdummy); /* Calculate decoration-size */ lb = xf - wm_xf + wm_border; tb = yf - wm_yf + wm_border; rb = wm_wf - wf - lb + 2 * wm_border; bb = wm_hf - hf - tb + 2 * wm_border; #ifdef DEBUG_WMGR fprintf(stderr, "wmgr_get_size: tl_win: 0x%lx wmgr_win: 0x%lx\n" " tl_win_geo: %dx%d+%d+%d wmgr_geo: %dx%d+%d+%d\n" " wm_decoration: %d,%d,%d,%d\n", (unsigned long)tl_win, (unsigned long)wm_win, wf, hf, xf, yf, wm_wf, wm_hf, wm_xf, wm_yf, lb, rb, tb, bb); #endif /* Some sanity checks... */ if (lb < 0 || lb > MAX_BORDER || rb < 0 || rb > MAX_BORDER || tb < 0 || tb > MAX_BORDER || bb < 0 || bb > MAX_BORDER) { #ifdef DEBUG_WMGR fprintf(stderr, "wmgr_get_size: decoration-size seems to be bogus, giving up\n"); #endif return WMGR_BOGUS; } wmgr->lb = lb; wmgr->rb = rb; wmgr->tb = tb; wmgr->bb = bb; return WMGR_OK; } void wmgr_prepare_get_offset(int x, int y, Window win, wmgr_deco_t *wmgr) { if (wmgr->orig_set) return; wmgr->orig_x = x; wmgr->orig_y = y; wmgr->orig_win = win; wmgr->orig_set = time(NULL); #ifdef DEBUG_WMGR fprintf(stderr, "wmgr_prepare_get_offset: origin %d, %d, window 0x%lx, time %lu\n", x, y, (unsigned long)win, (unsigned long)wmgr->orig_set); #endif } int wmgr_get_offset(int x, int y, Window win, wmgr_deco_t *wmgr) { if (!wmgr->orig_set || win != wmgr->orig_win) return WMGR_ERR; if (time(NULL) - wmgr->orig_set > MAX_REPARENT_DELAY) { #ifdef DEBUG_WMGR fprintf(stderr, "wmgr_get_offset: timeout: %lu\n", (unsigned long)time(NULL)); #endif return WMGR_TIMEOUT; } wmgr->ofs_x = wmgr->orig_x - x; wmgr->ofs_y = wmgr->orig_y - y; #ifdef DEBUG_WMGR fprintf(stderr, "wmgr_get_offset: offset %d,%d\n", wmgr->ofs_x, wmgr->ofs_y); #endif if (wmgr->ofs_x < -MAX_BORDER || wmgr->ofs_x > MAX_BORDER || wmgr->ofs_y < -MAX_BORDER || wmgr->ofs_y > MAX_BORDER) { #ifdef DEBUG_WMGR fprintf(stderr, "wmgr_get_offset: window offset seems to be bogus, giving up\n"); return WMGR_BOGUS; #endif } return WMGR_OK; } int wmgr_inc_ignore_xconfigure(wmgr_deco_t *wmgr) { if (!wmgr->orig_set) { wmgr->ignore_xconfigure++; #ifdef DEBUG_WMGR fprintf(stderr, "wmgr_inc_ignore_xconfigure: new value: %d\n", wmgr->ignore_xconfigure); } else { fprintf(stderr, "wmgr_inc_ignore_xconfigure: orig already set\n"); #endif } return wmgr->ignore_xconfigure; } int wmgr_dec_ignore_xconfigure(wmgr_deco_t *wmgr) { if (wmgr->ignore_xconfigure) { #ifdef DEBUG_WMGR fprintf(stderr, "wmgr_dec_ignore_xconfigure: current value: %d\n", wmgr->ignore_xconfigure); #endif return wmgr->ignore_xconfigure--; } else { #ifdef DEBUG_WMGR fprintf(stderr, "wmgr_dec_ignore_xconfigure: no events to ignore\n"); #endif return 0; } }