ewmh.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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_system_tray_s] = ATOM("_NET_SYSTEM_TRAY_S0");
  48. W->net_atom[net_system_tray_opcode] = ATOM("_NET_SYSTEM_TRAY_OPCODE");
  49. W->net_atom[net_system_tray_message_data] = ATOM("_NET_SYSTEM_TRAY_MESSAGE_DATA");
  50. W->net_atom[net_system_tray_visual] = ATOM("_NET_SYSTEM_TRAY_VISUAL");
  51. W->net_atom[net_system_tray_orientation] = ATOM("_NET_SYSTEM_TRAY_ORIENTATION");
  52. W->net_atom[xembed] = ATOM("_XEMBED");
  53. W->net_atom[xembedinfo] = ATOM("_XEMBED_INFO");
  54. W->net_atom[manager] = ATOM("MANAGER");
  55. W->net_atom[utf8_string] = ATOM("UTF8_STRING");
  56. /* WMFS hints */
  57. W->net_atom[wmfs_running] = ATOM("_WMFS_RUNNING");
  58. W->net_atom[wmfs_focus] = ATOM("_WMFS_FOCUS");
  59. W->net_atom[wmfs_update_hints] = ATOM("_WMFS_UPDATE_HINTS");
  60. W->net_atom[wmfs_set_screen] = ATOM("_WMFS_SET_SCREEN");
  61. W->net_atom[wmfs_screen_count] = ATOM("_WMFS_SCREEN_COUNT");
  62. W->net_atom[wmfs_current_tag] = ATOM("_WMFS_CURRENT_TAG");
  63. W->net_atom[wmfs_tag_list] = ATOM("_WMFS_TAG_LIST");
  64. W->net_atom[wmfs_current_screen] = ATOM("_WMFS_CURRENT_SCREEN");
  65. W->net_atom[wmfs_current_layout] = ATOM("_WMFS_CURRENT_LAYOUT");
  66. W->net_atom[wmfs_function] = ATOM("_WMFS_FUNCTION");
  67. W->net_atom[wmfs_cmd] = ATOM("_WMFS_CMD");
  68. XChangeProperty(W->dpy, W->root, W->net_atom[net_supported], XA_ATOM, 32,
  69. PropModeReplace, (unsigned char*)W->net_atom, net_last);
  70. XChangeProperty(W->dpy, W->root, W->net_atom[wmfs_running], XA_CARDINAL, 32,
  71. PropModeReplace, (unsigned char*)&b, 1);
  72. /* Set _NET_SUPPORTING_WM_CHECK */
  73. XChangeProperty(W->dpy, W->root, W->net_atom[net_supporting_wm_check], XA_WINDOW, 32,
  74. PropModeReplace, (unsigned char*)&W->root, 1);
  75. XChangeProperty(W->dpy, W->root, ATOM("WM_CLASS"), XA_STRING, 8,
  76. PropModeReplace, (unsigned char*)&"wmfs", 4);
  77. XChangeProperty(W->dpy, W->root, W->net_atom[net_wm_name], W->net_atom[utf8_string], 8,
  78. PropModeReplace, (unsigned char*)&"wmfs2", 5);
  79. /*
  80. * Set _NET_WM_PID
  81. XChangeProperty(W->dpy, W->root, W->net_atom[net_wm_pid], XA_CARDINAL, 32,
  82. PropModeReplace, (unsigned char*)&pid, 1);
  83. * Set _NET_SHOWING_DESKTOP
  84. XChangeProperty(W->dpy, W->root, W->net_atom[net_showing_desktop], XA_CARDINAL, 32,
  85. PropModeReplace, (unsigned char*)&showing_desk, 1);
  86. */
  87. }
  88. void
  89. ewmh_set_wm_state(Window w, int state)
  90. {
  91. unsigned char d[] = { state, None };
  92. XChangeProperty(W->dpy, w, W->net_atom[wm_state],
  93. W->net_atom[wm_state], 32, PropModeReplace, d, 2);
  94. }
  95. /*
  96. * Get xembed state
  97. */
  98. long
  99. ewmh_get_xembed_state(Window win)
  100. {
  101. Atom rf;
  102. int f;
  103. long ret = 0;
  104. unsigned long n, il;
  105. unsigned char *data = NULL;
  106. if(XGetWindowProperty(W->dpy, win, W->net_atom[xembedinfo], 0L, 2, False,
  107. W->net_atom[xembedinfo], &rf, &f, &n, &il, &data) != Success)
  108. return 0;
  109. if(rf == W->net_atom[xembedinfo] && n == 2)
  110. ret = (long)data[1];
  111. if(n && data)
  112. XFree(data);
  113. return ret;
  114. }
  115. void
  116. ewmh_update_wmfs_props(void)
  117. {
  118. struct screen *s;
  119. int i, ns = 0;
  120. long *cts = NULL;
  121. SLIST_FOREACH(s, &W->h.screen, next)
  122. ++ns;
  123. cts = xcalloc(ns, sizeof(long));
  124. for(i = 0; i < ns; ++i)
  125. {
  126. s = screen_gb_id(i);
  127. cts[i] = (s->seltag ? s->seltag->id : 0);
  128. }
  129. XChangeProperty(W->dpy, W->root, W->net_atom[wmfs_current_tag], XA_CARDINAL, 32,
  130. PropModeReplace, (unsigned char*)cts, ns);
  131. if(W->client)
  132. XChangeProperty(W->dpy, W->root, W->net_atom[wmfs_focus], XA_WINDOW, 32,
  133. PropModeReplace, (unsigned char*)&W->client->win, 1);
  134. free(cts);
  135. }
  136. void
  137. ewmh_manage_state(long data[], struct client *c)
  138. {
  139. /* _NET_WM_STATE_FULLSCREEN */
  140. if(data[1] == (long)W->net_atom[net_wm_state_fullscreen])
  141. {
  142. if(data[0] == _NET_WM_STATE_ADD
  143. || (data[0] == _NET_WM_STATE_TOGGLE && !(c->flags & CLIENT_FULLSCREEN)))
  144. {
  145. c->flags |= CLIENT_FULLSCREEN;
  146. XReparentWindow(W->dpy, c->win, W->root, c->screen->geo.x, c->screen->geo.y);
  147. XResizeWindow(W->dpy, c->win, c->screen->geo.w, c->screen->geo.h);
  148. XChangeProperty(W->dpy, c->win, W->net_atom[net_wm_state], XA_ATOM, 32, PropModeReplace,
  149. (unsigned char*)&W->net_atom[net_wm_state_fullscreen], true);
  150. client_focus(c);
  151. XRaiseWindow(W->dpy, c->win);
  152. }
  153. else if(data[0] == _NET_WM_STATE_REMOVE
  154. || (data[0] == _NET_WM_STATE_TOGGLE && c->flags & CLIENT_FULLSCREEN))
  155. {
  156. c->flags &= ~CLIENT_FULLSCREEN;
  157. XReparentWindow(W->dpy, c->win, c->frame, c->wgeo.x, c->wgeo.y);
  158. XChangeProperty(W->dpy, c->win, W->net_atom[net_wm_state], XA_ATOM, 32, PropModeReplace,
  159. (unsigned char*)&W->net_atom[net_wm_state_fullscreen], false);
  160. client_moveresize(c, &c->geo);
  161. }
  162. }
  163. }
  164. void
  165. ewmh_manage_window_type(struct client *c)
  166. {
  167. Atom *atom, rf;
  168. int f;
  169. unsigned long n, il, i;
  170. unsigned char *data = NULL;
  171. long ldata[5] = { _NET_WM_STATE_ADD };
  172. /* _NET_WM_STATE at window mangement */
  173. if(XGetWindowProperty(W->dpy, c->win, W->net_atom[net_wm_state], 0L, 0x7FFFFFFFL, false,
  174. XA_ATOM, &rf, &f, &n, &il, &data) == Success && n)
  175. {
  176. atom = (Atom*)data;
  177. for(i = 0; i < n; ++i)
  178. {
  179. ldata[1] = atom[i];
  180. ewmh_manage_state(ldata, c);
  181. }
  182. XFree(data);
  183. }
  184. }