#include #include #include #include #undef Bool #undef CursorShape #undef Expose #undef KeyPress #undef KeyRelease #undef FocusIn #undef FocusOut #undef FontChange #undef None #undef Status #undef Unsorted #include #include #include #include static Display *xdisplay = 0; Display *disp() { if (!xdisplay) xdisplay = XOpenDisplay(NULL); return xdisplay; } void cleanupDisplay() { if (!xdisplay) return; XCloseDisplay(xdisplay); xdisplay = 0; } static bool ewmhIsSupported() { Display *display = disp(); Atom netSupportingWmCheck = XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", true); Atom actualType; int format = 0; unsigned long num = 0, bytes = 0; unsigned char *data = NULL; Window ewmh_window = 0; int status = XGetWindowProperty(display, DefaultRootWindow(display), netSupportingWmCheck, 0L, 1L, false, XA_WINDOW, &actualType, &format, &num, &bytes, &data); if (status == Success) { if (num > 0) { ewmh_window = ((Window *)data)[0]; } if (data) { XFree(data); data = NULL; } } if (ewmh_window) { status = XGetWindowProperty(display, ewmh_window, netSupportingWmCheck, 0L, 1L, false, XA_WINDOW, &actualType, &format, &num, &bytes, &data); if (status != Success || num == 0 || ewmh_window != ((Window *)data)[0]) { ewmh_window = 0; } if (status == Success && data) { XFree(data); } } return ewmh_window != 0; } static QStringList getStates(Window window) { QStringList states; if (!ewmhIsSupported()) return states; Atom wmState = XInternAtom(disp(), "_NET_WM_STATE", true), type; int format; unsigned long num, bytes; unsigned char *data; int status = XGetWindowProperty(disp(), window, wmState, 0, ~0L, false, AnyPropertyType, &type, &format, &num, &bytes, &data); if (status == Success) for (unsigned long i = 0; i < num; i++) states.append(QString( XGetAtomName(disp(), ((Atom *)data)[i]))); return states; } static std::vector getTopLevelWindows() { std::vector res; res.resize(0); if (!ewmhIsSupported()) { return res; } Atom netClList = XInternAtom(disp(), "_NET_CLIENT_LIST", true); Atom actualType; int format; unsigned long num, bytes; Window *data = 0; for (int i = 0; i < ScreenCount(disp()); ++i) { Window rootWin = RootWindow(disp(), i); int status = XGetWindowProperty(disp(), rootWin, netClList, 0L, ~0L, false, AnyPropertyType, &actualType, &format, &num, &bytes, (uint8_t **)&data); if (status != Success) { continue; } for (unsigned long i = 0; i < num; ++i) res.emplace_back(data[i]); XFree(data); } return res; } static std::string GetWindowTitle(size_t i) { Window w = getTopLevelWindows().at(i); std::string windowTitle; char *name; XTextProperty text; int status = XGetTextProperty( disp(), w, &text, XInternAtom(disp(), "_NET_WM_NAME", true)); if (status == 0) status = XGetTextProperty(disp(), w, &text, XInternAtom(disp(), "WM_NAME", true)); name = reinterpret_cast(text.value); if (status != 0 && name != nullptr) { std::string str(name); windowTitle = str; XFree(name); } return windowTitle; } void GetWindowList(std::vector &windows) { windows.resize(0); for (size_t i = 0; i < getTopLevelWindows().size(); ++i) { if (GetWindowTitle(i) != "") windows.emplace_back(GetWindowTitle(i)); } } // Overloaded void GetWindowList(QStringList &windows) { windows.clear(); for (size_t i = 0; i < getTopLevelWindows().size(); ++i) { if (GetWindowTitle(i) != "") windows << QString::fromStdString(GetWindowTitle(i)); } } void GetCurrentWindowTitle(std::string &title) { if (!ewmhIsSupported()) { return; } Atom active = XInternAtom(disp(), "_NET_ACTIVE_WINDOW", true); Atom actualType; int format; unsigned long num, bytes; Window *data = 0; char *name; Window rootWin = RootWindow(disp(), 0); int xstatus = XGetWindowProperty(disp(), rootWin, active, 0L, ~0L, false, AnyPropertyType, &actualType, &format, &num, &bytes, (uint8_t **)&data); if (data == nullptr) { return; } int status = 0; XTextProperty text; if (xstatus == Success) { status = XGetTextProperty(disp(), data[0], &text, XInternAtom(disp(), "_NET_WM_NAME", true)); if (status == 0) status = XGetTextProperty(disp(), data[0], &text, XInternAtom(disp(), "WM_NAME", true)); } name = reinterpret_cast(text.value); if (status != 0 && name != nullptr) { std::string str(name); title = str; XFree(name); } } std::pair getCursorPos() { std::pair pos(0, 0); Display *dpy; Window root; Window ret_root; Window ret_child; int root_x; int root_y; int win_x; int win_y; unsigned int mask; dpy = XOpenDisplay(NULL); root = XDefaultRootWindow(dpy); if (XQueryPointer(dpy, root, &ret_root, &ret_child, &root_x, &root_y, &win_x, &win_y, &mask)) { pos = std::pair(root_x, root_y); } XCloseDisplay(dpy); return pos; } bool isMaximized(const std::string &title) { if (!ewmhIsSupported()) return false; // Find switch in top level windows std::vector windows = getTopLevelWindows(); for (auto &window : windows) { XTextProperty text; int status = XGetTextProperty( disp(), window, &text, XInternAtom(disp(), "_NET_WM_NAME", true)); if (status == 0) status = XGetTextProperty(disp(), window, &text, XInternAtom(disp(), "WM_NAME", true)); char *name = reinterpret_cast(text.value); if (status == 0 || name == nullptr) continue; // True if switch equals window bool equals = (title == name); // True if switch matches window bool matches = QString::fromStdString(name).contains( QRegularExpression(QString::fromStdString(title))); // If found, check if switch is maximized if (equals || matches) { QStringList states = getStates(window); if (!states.isEmpty()) { // True if window is maximized vertically bool vertical = states.contains( "_NET_WM_STATE_MAXIMIZED_VERT"); // True if window is maximized horizontally bool horizontal = states.contains( "_NET_WM_STATE_MAXIMIZED_HORZ"); return (vertical && horizontal); } break; } } return false; } bool isFullscreen(const std::string &title) { if (!ewmhIsSupported()) return false; // Find switch in top level windows std::vector windows = getTopLevelWindows(); for (auto &window : windows) { XTextProperty text; int status = XGetTextProperty( disp(), window, &text, XInternAtom(disp(), "_NET_WM_NAME", true)); if (status == 0) status = XGetTextProperty(disp(), window, &text, XInternAtom(disp(), "WM_NAME", true)); char *name = reinterpret_cast(text.value); if (status == 0 || name == nullptr) continue; // True if switch equals window bool equals = (title == name); // True if switch matches window bool matches = QString::fromStdString(name).contains( QRegularExpression(QString::fromStdString(title))); // If found, check if switch is fullscreen if (equals || matches) { QStringList states = getStates(window); if (!states.isEmpty()) { // True if window is fullscreen bool fullscreen = states.contains( "_NET_WM_STATE_FULLSCREEN"); return (fullscreen); } break; } } return false; } //exe switch is not quite what is expected but it works for now void GetProcessList(QStringList &processes) { processes.clear(); for (size_t i = 0; i < getTopLevelWindows().size(); ++i) { std::string s = GetWindowTitle(i); if (s != "") processes << QString::fromStdString(s); } } bool isInFocus(const QString &executable) { std::string current; GetCurrentWindowTitle(current); // True if executable switch equals current window bool equals = (executable.toStdString() == current); // True if executable switch matches current window bool matches = QString::fromStdString(current).contains( QRegularExpression(executable)); return (equals || matches); } int secondsSinceLastInput() { time_t idle_time; static XScreenSaverInfo *mit_info; Display *display; int screen; mit_info = XScreenSaverAllocInfo(); if ((display = XOpenDisplay(NULL)) == NULL) { return (-1); } screen = DefaultScreen(display); XScreenSaverQueryInfo(display, RootWindow(display, screen), mit_info); idle_time = (mit_info->idle) / 1000; XFree(mit_info); XCloseDisplay(display); return idle_time; }