|
@@ -0,0 +1,211 @@
|
|
|
+#include <X11/Xlib.h>
|
|
|
+#include <X11/Xatom.h>
|
|
|
+#include <X11/Xutil.h>
|
|
|
+#undef Bool
|
|
|
+#undef CursorShape
|
|
|
+#undef Expose
|
|
|
+#undef KeyPress
|
|
|
+#undef KeyRelease
|
|
|
+#undef FocusIn
|
|
|
+#undef FocusOut
|
|
|
+#undef FontChange
|
|
|
+#undef None
|
|
|
+#undef Status
|
|
|
+#undef Unsorted
|
|
|
+#include <util/platform.h>
|
|
|
+#include "auto-scene-switcher.hpp"
|
|
|
+
|
|
|
+using namespace std;
|
|
|
+
|
|
|
+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 std::vector<Window> getTopLevelWindows()
|
|
|
+{
|
|
|
+ std::vector<Window> 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;
|
|
|
+
|
|
|
+ int status = XFetchName(disp(), w, &name);
|
|
|
+ if (status >= Success && name != nullptr)
|
|
|
+ {
|
|
|
+ std::string str(name);
|
|
|
+ windowTitle = str;
|
|
|
+ }
|
|
|
+
|
|
|
+ XFree(name);
|
|
|
+
|
|
|
+ return windowTitle;
|
|
|
+}
|
|
|
+
|
|
|
+void GetWindowList(vector<string> &windows)
|
|
|
+{
|
|
|
+ windows.resize(0);
|
|
|
+
|
|
|
+ for (size_t i = 0; i < getTopLevelWindows().size(); ++i){
|
|
|
+ if (GetWindowTitle(i) != "")
|
|
|
+ windows.emplace_back(GetWindowTitle(i));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void GetCurrentWindowTitle(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);
|
|
|
+
|
|
|
+ XGetWindowProperty(
|
|
|
+ disp(),
|
|
|
+ rootWin,
|
|
|
+ active,
|
|
|
+ 0L,
|
|
|
+ ~0L,
|
|
|
+ false,
|
|
|
+ AnyPropertyType,
|
|
|
+ &actualType,
|
|
|
+ &format,
|
|
|
+ &num,
|
|
|
+ &bytes,
|
|
|
+ (uint8_t**)&data);
|
|
|
+
|
|
|
+ int status = XFetchName(disp(), data[0], &name);
|
|
|
+
|
|
|
+ if (status >= Success && name != nullptr) {
|
|
|
+ std::string str(name);
|
|
|
+ title = str;
|
|
|
+ }
|
|
|
+
|
|
|
+ XFree(name);
|
|
|
+}
|