/* * Copyright (C) 2004 Girish Ramakrishnan All Rights Reserved. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ // $Id: util.cpp,v 1.7 2005/01/29 09:56:08 cs19713 Exp $ #include "trace.h" #include "util.h" #include #include #include #include #include /* * Assert validity of the window id. Get window attributes for the heck of it * and see if the request went through. */ bool isValidWindowId(Display *display, Window w) { XWindowAttributes attrib; return XGetWindowAttributes(display, w, &attrib) != 0; } /* * Checks if this window is a normal window (i.e) * - Has a WM_STATE * - Not modal window * - Not a purely transient window (with no window type set) * - Not a special window (desktop/menu/util) as indicated in the window type */ bool isNormalWindow(Display *display, Window w) { Atom __attribute__ ((unused)) type; int __attribute__ ((unused)) format; unsigned long __attribute__ ((unused)) left; Atom *data = NULL; unsigned long nitems; Window transient_for = None; static Atom wmState = XInternAtom(display, "WM_STATE", False); static Atom windowState = XInternAtom(display, "_NET_WM_STATE", False); static Atom modalWindow = XInternAtom(display, "_NET_WM_STATE_MODAL", False); static Atom windowType = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False); static Atom normalWindow = XInternAtom(display, "_NET_WM_WINDOW_TYPE_NORMAL", False); static Atom dialogWindow = XInternAtom(display, "_NET_WM_WINDOW_TYPE_DIALOG", False); int ret = XGetWindowProperty(display, w, wmState, 0, 10, False, AnyPropertyType, &type, &format, &nitems, &left, (unsigned char **) &data); TRACE("0x%x (%i)", (unsigned) w, (unsigned) w); if (ret != Success || data == NULL) return false; TRACE("\tHas WM_STATE"); if (data) XFree(data); ret = XGetWindowProperty(display, w, windowState, 0, 10, False, AnyPropertyType, &type, &format, &nitems, &left, (unsigned char **) &data); if (ret == Success) { unsigned int i; for (i = 0; i < nitems; i++) { if (data[i] == modalWindow) break; } XFree(data); if (i < nitems) { TRACE("\tMODAL"); return false; } } else TRACE("\tNo _NET_WM_STATE"); XGetTransientForHint(display, w, &transient_for); TRACE("\tTransientFor=0x%x", (unsigned) transient_for); ret = XGetWindowProperty(display, w, windowType, 0, 10, False, AnyPropertyType, &type, &format, &nitems, &left, (unsigned char **) &data); if ((ret == Success) && data) { unsigned int i; for (i = 0; i < nitems; i++) { if (data[i] != normalWindow && data[i] != dialogWindow) break; } XFree(data); TRACE("\tAbnormal = %i", (i == nitems)); return (i == nitems); } else return (transient_for == None); } /* * Returns the contents of the _NET_WM_PID (which is supposed to contain the * process id of the application that created the window) */ pid_t pid(Display *display, Window w) { Atom actual_type; int actual_format; unsigned long nitems, leftover; unsigned char *pid; pid_t pid_return = -1; if (XGetWindowProperty(display, w, XInternAtom(display, "_NET_WM_PID", False), 0, 1, False, XA_CARDINAL, &actual_type, &actual_format, &nitems, &leftover, &pid) == Success) { if (pid) pid_return = *(pid_t *) pid; XFree(pid); } TRACE("0x%x has PID=%i", (unsigned) w, pid_return); return pid_return; } /* * Sends ClientMessage to a window */ void sendMessage(Display* display, Window to, Window w, char* type, int format, long mask, void* data, int size) { XEvent ev; memset(&ev, 0, sizeof(ev)); ev.xclient.type = ClientMessage; ev.xclient.window = w; ev.xclient.message_type = XInternAtom(display, type, True); ev.xclient.format = format; memcpy((char *) &ev.xclient.data, (const char *) data, size); XSendEvent(display, to, False, mask, &ev); XSync(display, False); } /* * The Grand Window Analyzer. Checks if window w has a expected pid of epid * or a expected name of ename */ bool analyzeWindow(Display *display, Window w, pid_t epid, const QString &ename) { XClassHint ch; pid_t apid = pid(display, w); TRACE("WID=0x%x PID=%i ExpectedName=%s", (unsigned) w, (unsigned) epid, ename.latin1()); if (epid == apid) return true; // no plans to analyze windows without a name char *window_name = NULL; if (!XFetchName(display, w, &window_name)) return false; TRACE("Window has name [%s]", window_name); if (window_name) XFree(window_name); else return false; bool this_is_our_man = false; // lets try the program name if (XGetClassHint(display, w, &ch)) { if (QString(ch.res_name).find(ename, 0, FALSE) != -1) { TRACE("ResName [%s] matched", ch.res_name); this_is_our_man = true; } else if (QString(ch.res_class).find(ename, 0, FALSE) != -1) { TRACE("ResClass [%s] matched", ch.res_class); this_is_our_man = true; } else { // sheer desperation char *wm_name = NULL; XFetchName(display, w, &wm_name); if (wm_name && (QString(wm_name).find(ename, 0, FALSE) != -1)) { TRACE("WM_NAME [%s] matched", wm_name); this_is_our_man = true; } } if (ch.res_class) XFree(ch.res_class); if (ch.res_name) XFree(ch.res_name); } // its probably a good idea to check (obsolete) WM_COMMAND here return this_is_our_man; } Window activeWindow(Display *display) { Atom active_window_atom = XInternAtom(display, "_NET_ACTIVE_WINDOW", True); Atom type = None; int format; unsigned long nitems, after; unsigned char *data = NULL; int screen = DefaultScreen(display); Window root = RootWindow(display, screen); int r = XGetWindowProperty(display, root, active_window_atom,0, 1, False, AnyPropertyType, &type, &format, &nitems, &after, &data); Window w = None; if ((r == Success) && data && (*(Window *)data != None)) w = *(Window *)data; else { int revert; XGetInputFocus(display, &w, &revert); } TRACE("Active window is 0x%x", (unsigned) w); return w; } /* * Requests user to select a window by grabbing the mouse. A left click will * select the application. Clicking any other button will abort the selection */ Window selectWindow(Display *display, const char **err) { int screen = DefaultScreen(display); Window root = RootWindow(display, screen); if (err) *err = NULL; Cursor cursor = XCreateFontCursor(display, XC_draped_box); if (cursor == None) { if (err) *err = "Failed to create XC_draped_box"; return None; } if (XGrabPointer(display, root, False, ButtonPressMask | ButtonReleaseMask, GrabModeSync, GrabModeAsync, None, cursor, CurrentTime) != GrabSuccess) { if (err) *err = "Failed to grab mouse"; return None; } XAllowEvents(display, SyncPointer, CurrentTime); XEvent event; XWindowEvent(display, root, ButtonPressMask, &event); Window selected_window = (event.xbutton.subwindow == None) ? RootWindow(display, screen) : event.xbutton.subwindow; XUngrabPointer(display, CurrentTime); XFreeCursor(display, cursor); if (event.xbutton.button != Button1) return None; return XmuClientWindow(display, selected_window); } void subscribe(Display *display, Window w, long mask, bool set) { Window root = RootWindow(display, DefaultScreen(display)); XWindowAttributes attr; TRACE("Window=0x%x Mask=%ld Set=%i", (unsigned) w, mask, set); XGetWindowAttributes(display, w == None ? root : w, &attr); if (set && (attr.your_event_mask & mask == mask)) return; if (!set && (attr.your_event_mask | mask == attr.your_event_mask)) return; XSelectInput(display, w == None ? root : w, set ? attr.your_event_mask | mask : attr.your_event_mask & mask); XSync(display, False); } // Returns the state of the SystemTray and the Wid if it exists SysTrayState sysTrayStatus(Display *display, Window *tray) { Screen *screen = XDefaultScreenOfDisplay(display); Window sys_tray; Atom selection = None; char temp[50]; sprintf(temp, "_NET_SYSTEM_TRAY_S%i", XScreenNumberOfScreen(screen)); selection = XInternAtom(display, temp, True); if (selection == None) return SysTrayAbsent; sys_tray = XGetSelectionOwner(display, selection); if (tray) *tray = sys_tray; return sys_tray == None ? SysTrayHidden : SysTrayPresent; } bool getCardinalProperty(Display *display, Window w, Atom prop, long *data) { Atom type; int format; unsigned long nitems, bytes; unsigned char *d = NULL; if (XGetWindowProperty(display, w, prop, 0, 1, False, XA_CARDINAL,&type, &format, &nitems, &bytes, &d) == Success && d) { TRACE("%ld", *(long *)d); if (data) *data = *(long *)d; XFree(d); return true; } TRACE("FAILED"); return false; }