ewmh.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*
  2. * wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
  3. * For license, see COPYING.
  4. */
  5. #include "ewmh.h"
  6. #include "util.h"
  7. #include "screen.h"
  8. #include "client.h"
  9. /* Taken From standards.freedesktop.org */
  10. #define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
  11. #define _NET_WM_STATE_ADD 1 /* add/set property */
  12. #define _NET_WM_STATE_TOGGLE 2 /* toggle property */
  13. void
  14. ewmh_init(void)
  15. {
  16. int b = 1;
  17. W->net_atom = xcalloc(net_last, sizeof(Atom));
  18. /* EWMH hints */
  19. W->net_atom[wm_state] = ATOM("WM_STATE");
  20. W->net_atom[wm_class] = ATOM("WM_CLASS");
  21. W->net_atom[net_supported] = ATOM("_NET_SUPPORTED");
  22. W->net_atom[net_client_list] = ATOM("_NET_CLIENT_LIST");
  23. W->net_atom[net_frame_extents] = ATOM("_NET_FRAME_EXTENTS");
  24. W->net_atom[net_number_of_desktops] = ATOM("_NET_NUMBER_OF_DESKTOPS");
  25. W->net_atom[net_current_desktop] = ATOM("_NET_CURRENT_DESKTOP");
  26. W->net_atom[net_desktop_names] = ATOM("_NET_DESKTOP_NAMES");
  27. W->net_atom[net_desktop_geometry] = ATOM("_NET_DESKTOP_GEOMETRY");
  28. W->net_atom[net_active_window] = ATOM("_NET_ACTIVE_WINDOW");
  29. W->net_atom[net_close_window] = ATOM("_NET_CLOSE_WINDOW");
  30. W->net_atom[net_wm_name] = ATOM("_NET_WM_NAME");
  31. W->net_atom[net_wm_pid] = ATOM("_NET_WM_PID");
  32. W->net_atom[net_wm_desktop] = ATOM("_NET_WM_DESKTOP");
  33. W->net_atom[net_showing_desktop] = ATOM("_NET_SHOWING_DESKTOP");
  34. W->net_atom[net_wm_icon_name] = ATOM("_NET_WM_ICON_NAME");
  35. W->net_atom[net_wm_window_type] = ATOM("_NET_WM_WINDOW_TYPE");
  36. W->net_atom[net_supporting_wm_check] = ATOM("_NET_SUPPORTING_WM_CHECK");
  37. W->net_atom[net_wm_window_opacity] = ATOM("_NET_WM_WINDOW_OPACITY");
  38. W->net_atom[net_wm_window_type_normal] = ATOM("_NET_WM_WINDOW_TYPE_NORMAL");
  39. W->net_atom[net_wm_window_type_dock] = ATOM("_NET_WM_WINDOW_TYPE_DOCK");
  40. W->net_atom[net_wm_window_type_splash] = ATOM("_NET_WM_WINDOW_TYPE_SPLASH");
  41. W->net_atom[net_wm_window_type_dialog] = ATOM("_NET_WM_WINDOW_TYPE_DIALOG");
  42. W->net_atom[net_wm_icon] = ATOM("_NET_WM_ICON");
  43. W->net_atom[net_wm_state] = ATOM("_NET_WM_STATE");
  44. W->net_atom[net_wm_state_fullscreen] = ATOM("_NET_WM_STATE_FULLSCREEN");
  45. W->net_atom[net_wm_state_sticky] = ATOM("_NET_WM_STATE_STICKY");
  46. W->net_atom[net_wm_state_demands_attention] = ATOM("_NET_WM_STATE_DEMANDS_ATTENTION");
  47. W->net_atom[net_wm_state_hidden] = ATOM("_NET_WM_STATE_HIDDEN");
  48. W->net_atom[net_system_tray_s] = ATOM("_NET_SYSTEM_TRAY_S0");
  49. W->net_atom[net_system_tray_opcode] = ATOM("_NET_SYSTEM_TRAY_OPCODE");
  50. W->net_atom[net_system_tray_message_data] = ATOM("_NET_SYSTEM_TRAY_MESSAGE_DATA");
  51. W->net_atom[net_system_tray_visual] = ATOM("_NET_SYSTEM_TRAY_VISUAL");
  52. W->net_atom[net_system_tray_orientation] = ATOM("_NET_SYSTEM_TRAY_ORIENTATION");
  53. W->net_atom[xembed] = ATOM("_XEMBED");
  54. W->net_atom[xembedinfo] = ATOM("_XEMBED_INFO");
  55. W->net_atom[manager] = ATOM("MANAGER");
  56. W->net_atom[utf8_string] = ATOM("UTF8_STRING");
  57. /* WMFS hints */
  58. W->net_atom[wmfs_running] = ATOM("_WMFS_RUNNING");
  59. W->net_atom[wmfs_focus] = ATOM("_WMFS_FOCUS");
  60. W->net_atom[wmfs_update_hints] = ATOM("_WMFS_UPDATE_HINTS");
  61. W->net_atom[wmfs_set_screen] = ATOM("_WMFS_SET_SCREEN");
  62. W->net_atom[wmfs_screen_count] = ATOM("_WMFS_SCREEN_COUNT");
  63. W->net_atom[wmfs_current_tag] = ATOM("_WMFS_CURRENT_TAG");
  64. W->net_atom[wmfs_tag_list] = ATOM("_WMFS_TAG_LIST");
  65. W->net_atom[wmfs_current_screen] = ATOM("_WMFS_CURRENT_SCREEN");
  66. W->net_atom[wmfs_current_layout] = ATOM("_WMFS_CURRENT_LAYOUT");
  67. W->net_atom[wmfs_function] = ATOM("_WMFS_FUNCTION");
  68. W->net_atom[wmfs_cmd] = ATOM("_WMFS_CMD");
  69. XChangeProperty(W->dpy, W->root, W->net_atom[net_supported], XA_ATOM, 32,
  70. PropModeReplace, (unsigned char*)W->net_atom, net_last);
  71. XChangeProperty(W->dpy, W->root, W->net_atom[wmfs_running], XA_CARDINAL, 32,
  72. PropModeReplace, (unsigned char*)&b, 1);
  73. /* Set _NET_SUPPORTING_WM_CHECK */
  74. XChangeProperty(W->dpy, W->root, W->net_atom[net_supporting_wm_check], XA_WINDOW, 32,
  75. PropModeReplace, (unsigned char*)&W->root, 1);
  76. XChangeProperty(W->dpy, W->root, ATOM("WM_CLASS"), XA_STRING, 8,
  77. PropModeReplace, (unsigned char*)&"wmfs", 4);
  78. XChangeProperty(W->dpy, W->root, W->net_atom[net_wm_name], W->net_atom[utf8_string], 8,
  79. PropModeReplace, (unsigned char*)&"wmfs2", 5);
  80. /*
  81. * Set _NET_WM_PID
  82. XChangeProperty(W->dpy, W->root, W->net_atom[net_wm_pid], XA_CARDINAL, 32,
  83. PropModeReplace, (unsigned char*)&pid, 1);
  84. * Set _NET_SHOWING_DESKTOP
  85. XChangeProperty(W->dpy, W->root, W->net_atom[net_showing_desktop], XA_CARDINAL, 32,
  86. PropModeReplace, (unsigned char*)&showing_desk, 1);
  87. */
  88. }
  89. void
  90. ewmh_set_wm_state(Window w, int state)
  91. {
  92. unsigned char d[] = { state, None };
  93. XChangeProperty(W->dpy, w, W->net_atom[wm_state],
  94. W->net_atom[wm_state], 32, PropModeReplace, d, 2);
  95. }
  96. /*
  97. * Get xembed state
  98. */
  99. long
  100. ewmh_get_xembed_state(Window win)
  101. {
  102. Atom rf;
  103. int f;
  104. long ret = 0;
  105. unsigned long n, il;
  106. unsigned char *data = NULL;
  107. if(XGetWindowProperty(W->dpy, win, W->net_atom[xembedinfo], 0L, 2, False,
  108. W->net_atom[xembedinfo], &rf, &f, &n, &il, &data) != Success)
  109. return 0;
  110. if(rf == W->net_atom[xembedinfo] && n == 2)
  111. ret = (long)data[1];
  112. if(n && data)
  113. XFree(data);
  114. return ret;
  115. }
  116. void
  117. ewmh_update_wmfs_props(void)
  118. {
  119. struct screen *s;
  120. int i, ns = 0;
  121. long *cts = NULL;
  122. SLIST_FOREACH(s, &W->h.screen, next)
  123. ++ns;
  124. cts = xcalloc(ns, sizeof(long));
  125. for(i = 0; i < ns; ++i)
  126. {
  127. s = screen_gb_id(i);
  128. cts[i] = (s->seltag ? s->seltag->id : 0);
  129. }
  130. XChangeProperty(W->dpy, W->root, W->net_atom[wmfs_current_tag], XA_CARDINAL, 32,
  131. PropModeReplace, (unsigned char*)cts, ns);
  132. if(W->client)
  133. XChangeProperty(W->dpy, W->root, W->net_atom[wmfs_focus], XA_WINDOW, 32,
  134. PropModeReplace, (unsigned char*)&W->client->win, 1);
  135. free(cts);
  136. }
  137. void
  138. ewmh_manage_state(long data[], struct client *c)
  139. {
  140. /* _NET_WM_STATE_FULLSCREEN */
  141. if(data[1] == (long)W->net_atom[net_wm_state_fullscreen])
  142. {
  143. if(data[0] == _NET_WM_STATE_ADD
  144. || (data[0] == _NET_WM_STATE_TOGGLE && !(c->flags & CLIENT_FULLSCREEN)))
  145. {
  146. c->flags |= CLIENT_FULLSCREEN;
  147. XReparentWindow(W->dpy, c->win, W->root, c->screen->geo.x, c->screen->geo.y);
  148. XResizeWindow(W->dpy, c->win, c->screen->geo.w, c->screen->geo.h);
  149. XChangeProperty(W->dpy, c->win, W->net_atom[net_wm_state], XA_ATOM, 32, PropModeReplace,
  150. (unsigned char*)&W->net_atom[net_wm_state_fullscreen], true);
  151. client_focus(c);
  152. XRaiseWindow(W->dpy, c->win);
  153. }
  154. else if(data[0] == _NET_WM_STATE_REMOVE
  155. || (data[0] == _NET_WM_STATE_TOGGLE && c->flags & CLIENT_FULLSCREEN))
  156. {
  157. c->flags &= ~CLIENT_FULLSCREEN;
  158. XReparentWindow(W->dpy, c->win, c->frame, c->wgeo.x, c->wgeo.y);
  159. XChangeProperty(W->dpy, c->win, W->net_atom[net_wm_state], XA_ATOM, 32, PropModeReplace,
  160. (unsigned char*)&W->net_atom[net_wm_state_fullscreen], false);
  161. client_moveresize(c, &c->geo);
  162. }
  163. }
  164. }
  165. void
  166. ewmh_manage_window_type(struct client *c)
  167. {
  168. Atom *atom, rf;
  169. int f;
  170. unsigned long n, il, i;
  171. unsigned char *data = NULL;
  172. long ldata[5] = { _NET_WM_STATE_ADD };
  173. /* _NET_WM_STATE at window mangement */
  174. if(XGetWindowProperty(W->dpy, c->win, W->net_atom[net_wm_state], 0L, 0x7FFFFFFFL, false,
  175. XA_ATOM, &rf, &f, &n, &il, &data) == Success && n)
  176. {
  177. atom = (Atom*)data;
  178. for(i = 0; i < n; ++i)
  179. {
  180. ldata[1] = atom[i];
  181. ewmh_manage_state(ldata, c);
  182. }
  183. XFree(data);
  184. }
  185. }