You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdedocker/src/util.cpp

325 lines
9.6 KiB

/*
* 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 <X11/Xutil.h>
#include <Xmu/WinUtil.h>
#include <X11/Xatom.h>
#include <X11/cursorfont.h>
#include <stdio.h>
/*
* 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;
}