auto-scene-switcher-nix.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #include <X11/Xlib.h>
  2. #include <X11/Xatom.h>
  3. #include <X11/Xutil.h>
  4. #undef Bool
  5. #undef CursorShape
  6. #undef Expose
  7. #undef KeyPress
  8. #undef KeyRelease
  9. #undef FocusIn
  10. #undef FocusOut
  11. #undef FontChange
  12. #undef None
  13. #undef Status
  14. #undef Unsorted
  15. #include <util/platform.h>
  16. #include "auto-scene-switcher.hpp"
  17. using namespace std;
  18. static Display *xdisplay = 0;
  19. Display *disp()
  20. {
  21. if (!xdisplay)
  22. xdisplay = XOpenDisplay(NULL);
  23. return xdisplay;
  24. }
  25. void CleanupSceneSwitcher()
  26. {
  27. if (!xdisplay)
  28. return;
  29. XCloseDisplay(xdisplay);
  30. xdisplay = 0;
  31. }
  32. static bool ewmhIsSupported()
  33. {
  34. Display *display = disp();
  35. Atom netSupportingWmCheck =
  36. XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", true);
  37. Atom actualType;
  38. int format = 0;
  39. unsigned long num = 0, bytes = 0;
  40. unsigned char *data = NULL;
  41. Window ewmh_window = 0;
  42. Window root_window = 0;
  43. root_window = DefaultRootWindow(display);
  44. if (!root_window) {
  45. return false;
  46. }
  47. int status = XGetWindowProperty(display, root_window,
  48. netSupportingWmCheck, 0L, 1L, false,
  49. XA_WINDOW, &actualType, &format, &num,
  50. &bytes, &data);
  51. if (status == Success) {
  52. if (num > 0) {
  53. ewmh_window = ((Window *)data)[0];
  54. }
  55. if (data) {
  56. XFree(data);
  57. data = NULL;
  58. }
  59. }
  60. if (ewmh_window) {
  61. status = XGetWindowProperty(display, ewmh_window,
  62. netSupportingWmCheck, 0L, 1L, false,
  63. XA_WINDOW, &actualType, &format,
  64. &num, &bytes, &data);
  65. if (status != Success || num == 0 ||
  66. ewmh_window != ((Window *)data)[0]) {
  67. ewmh_window = 0;
  68. }
  69. if (status == Success && data) {
  70. XFree(data);
  71. }
  72. }
  73. return ewmh_window != 0;
  74. }
  75. static std::vector<Window> getTopLevelWindows()
  76. {
  77. std::vector<Window> res;
  78. res.resize(0);
  79. if (!ewmhIsSupported()) {
  80. return res;
  81. }
  82. Atom netClList = XInternAtom(disp(), "_NET_CLIENT_LIST", true);
  83. Atom actualType;
  84. int format;
  85. unsigned long num, bytes;
  86. Window *data = 0;
  87. for (int i = 0; i < ScreenCount(disp()); ++i) {
  88. Window rootWin = RootWindow(disp(), i);
  89. if (!rootWin) {
  90. continue;
  91. }
  92. int status = XGetWindowProperty(disp(), rootWin, netClList, 0L,
  93. ~0L, false, AnyPropertyType,
  94. &actualType, &format, &num,
  95. &bytes, (uint8_t **)&data);
  96. if (status != Success) {
  97. continue;
  98. }
  99. for (unsigned long i = 0; i < num; ++i)
  100. res.emplace_back(data[i]);
  101. XFree(data);
  102. }
  103. return res;
  104. }
  105. static std::string GetWindowTitle(size_t i)
  106. {
  107. Window w = getTopLevelWindows().at(i);
  108. if (!w) {
  109. return "";
  110. }
  111. std::string windowTitle;
  112. char *name;
  113. int status = XFetchName(disp(), w, &name);
  114. if (status >= Success && name != nullptr) {
  115. std::string str(name);
  116. windowTitle = str;
  117. XFree(name);
  118. } else {
  119. XTextProperty xtp_new_name;
  120. if (XGetWMName(disp(), w, &xtp_new_name) != 0 &&
  121. xtp_new_name.value != nullptr) {
  122. std::string str((const char *)xtp_new_name.value);
  123. windowTitle = str;
  124. XFree(xtp_new_name.value);
  125. }
  126. }
  127. return windowTitle;
  128. }
  129. void GetWindowList(vector<string> &windows)
  130. {
  131. windows.resize(0);
  132. for (size_t i = 0; i < getTopLevelWindows().size(); ++i) {
  133. if (GetWindowTitle(i) != "")
  134. windows.emplace_back(GetWindowTitle(i));
  135. }
  136. }
  137. void GetCurrentWindowTitle(string &title)
  138. {
  139. if (!ewmhIsSupported()) {
  140. return;
  141. }
  142. Atom active = XInternAtom(disp(), "_NET_ACTIVE_WINDOW", true);
  143. Atom actualType;
  144. int format;
  145. unsigned long num, bytes;
  146. Window *data = 0;
  147. char *name;
  148. Window rootWin = RootWindow(disp(), 0);
  149. if (!rootWin) {
  150. return;
  151. }
  152. XGetWindowProperty(disp(), rootWin, active, 0L, ~0L, false,
  153. AnyPropertyType, &actualType, &format, &num, &bytes,
  154. (uint8_t **)&data);
  155. if (!data[0]) {
  156. return;
  157. }
  158. int status = XFetchName(disp(), data[0], &name);
  159. if (status >= Success && name != nullptr) {
  160. std::string str(name);
  161. title = str;
  162. } else {
  163. XTextProperty xtp_new_name;
  164. if (XGetWMName(disp(), data[0], &xtp_new_name) != 0 &&
  165. xtp_new_name.value != nullptr) {
  166. std::string str((const char *)xtp_new_name.value);
  167. title = str;
  168. XFree(xtp_new_name.value);
  169. }
  170. }
  171. XFree(name);
  172. }