qt_demoe/3rd_qxtglobalshortcut/qxtwindowsystem_x11.cpp

190 lines
6.4 KiB
C++

#include "qxtwindowsystem.h"
/****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of the LibQxt project nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** <http://libqxt.org> <foundation@libqxt.org>
*****************************************************************************/
#include <QLibrary>
#include <QX11Info>
#include <X11/Xutil.h>
static WindowList qxt_getWindows(Atom prop)
{
WindowList res;
Atom type = 0;
int format = 0;
uchar* data = 0;
ulong count, after;
Display* display = QX11Info::display();
Window window = QX11Info::appRootWindow();
if (XGetWindowProperty(display, window, prop, 0, 1024 * sizeof(Window) / 4, False, AnyPropertyType,
&type, &format, &count, &after, &data) == Success)
{
Window* list = reinterpret_cast<Window*>(data);
for (uint i = 0; i < count; ++i)
res += list[i];
if (data)
XFree(data);
}
return res;
}
WindowList QxtWindowSystem::windows()
{
static Atom net_clients = 0;
if (!net_clients)
net_clients = XInternAtom(QX11Info::display(), "_NET_CLIENT_LIST_STACKING", True);
return qxt_getWindows(net_clients);
}
WId QxtWindowSystem::activeWindow()
{
static Atom net_active = 0;
if (!net_active)
net_active = XInternAtom(QX11Info::display(), "_NET_ACTIVE_WINDOW", True);
return qxt_getWindows(net_active).value(0);
}
WId QxtWindowSystem::findWindow(const QString& title)
{
Window result = 0;
WindowList list = windows();
foreach (const Window &wid, list)
{
if (windowTitle(wid) == title)
{
result = wid;
break;
}
}
return result;
}
WId QxtWindowSystem::windowAt(const QPoint& pos)
{
Window result = 0;
WindowList list = windows();
for (int i = list.size() - 1; i >= 0; --i)
{
WId wid = list.at(i);
if (windowGeometry(wid).contains(pos))
{
result = wid;
break;
}
}
return result;
}
QString QxtWindowSystem::windowTitle(WId window)
{
QString name;
char* str = 0;
if (XFetchName(QX11Info::display(), window, &str))
name = QString::fromLatin1(str);
if (str)
XFree(str);
return name;
}
QRect QxtWindowSystem::windowGeometry(WId window)
{
int x, y;
uint width, height, border, depth;
Window root, child;
Display* display = QX11Info::display();
XGetGeometry(display, window, &root, &x, &y, &width, &height, &border, &depth);
XTranslateCoordinates(display, window, root, x, y, &x, &y, &child);
static Atom net_frame = 0;
if (!net_frame)
net_frame = XInternAtom(QX11Info::display(), "_NET_FRAME_EXTENTS", True);
QRect rect(x, y, width, height);
Atom type = 0;
int format = 0;
uchar* data = 0;
ulong count, after;
if (XGetWindowProperty(display, window, net_frame, 0, 4, False, AnyPropertyType,
&type, &format, &count, &after, &data) == Success)
{
// _NET_FRAME_EXTENTS, left, right, top, bottom, CARDINAL[4]/32
if (count == 4)
{
long* extents = reinterpret_cast<long*>(data);
rect.adjust(-extents[0], -extents[2], extents[1], extents[3]);
}
if (data)
XFree(data);
}
return rect;
}
typedef struct {
Window window; /* screen saver window - may not exist */
int state; /* ScreenSaverOff, ScreenSaverOn, ScreenSaverDisabled*/
int kind; /* ScreenSaverBlanked, ...Internal, ...External */
unsigned long til_or_since; /* time til or since screen saver */
unsigned long idle; /* total time since last user input */
unsigned long eventMask; /* currently selected events for this client */
} XScreenSaverInfo;
typedef XScreenSaverInfo* (*XScreenSaverAllocInfo)();
typedef Status (*XScreenSaverQueryInfo)(Display* display, Drawable drawable, XScreenSaverInfo* info);
static XScreenSaverAllocInfo _xScreenSaverAllocInfo = 0;
static XScreenSaverQueryInfo _xScreenSaverQueryInfo = 0;
uint QxtWindowSystem::idleTime()
{
static bool xssResolved = false;
if (!xssResolved) {
QLibrary xssLib(QLatin1String("Xss"), 1);
if (xssLib.load()) {
_xScreenSaverAllocInfo = (XScreenSaverAllocInfo) xssLib.resolve("XScreenSaverAllocInfo");
_xScreenSaverQueryInfo = (XScreenSaverQueryInfo) xssLib.resolve("XScreenSaverQueryInfo");
xssResolved = true;
}
}
uint idle = 0;
if (xssResolved)
{
XScreenSaverInfo* info = _xScreenSaverAllocInfo();
const int screen = QX11Info::appScreen();
unsigned long rootWindow = (unsigned long)QX11Info::appRootWindow(screen);
_xScreenSaverQueryInfo(QX11Info::display(), (Drawable) rootWindow, info);
idle = info->idle;
if (info)
XFree(info);
}
return idle;
}