Mirror of Awesome WM window manager
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

stack.c 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * stack.c - client stack management
  3. *
  4. * Copyright © 2008-2009 Julien Danjou <julien@danjou.info>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. */
  21. #include "stack.h"
  22. #include "ewmh.h"
  23. #include "objects/client.h"
  24. #include "objects/drawin.h"
  25. void
  26. stack_client_remove(client_t *c)
  27. {
  28. foreach(client, globalconf.stack)
  29. if(*client == c)
  30. {
  31. client_array_remove(&globalconf.stack, client);
  32. break;
  33. }
  34. ewmh_update_net_client_list_stacking();
  35. stack_windows();
  36. }
  37. /** Push the client at the beginning of the client stack.
  38. * \param c The client to push.
  39. */
  40. void
  41. stack_client_push(client_t *c)
  42. {
  43. stack_client_remove(c);
  44. client_array_push(&globalconf.stack, c);
  45. ewmh_update_net_client_list_stacking();
  46. stack_windows();
  47. }
  48. /** Push the client at the end of the client stack.
  49. * \param c The client to push.
  50. */
  51. void
  52. stack_client_append(client_t *c)
  53. {
  54. stack_client_remove(c);
  55. client_array_append(&globalconf.stack, c);
  56. ewmh_update_net_client_list_stacking();
  57. stack_windows();
  58. }
  59. static bool need_stack_refresh = false;
  60. void
  61. stack_windows(void)
  62. {
  63. need_stack_refresh = true;
  64. }
  65. /** Stack a window above another window, without causing errors.
  66. * \param w The window.
  67. * \param previous The window which should be below this window.
  68. */
  69. static void
  70. stack_window_above(xcb_window_t w, xcb_window_t previous)
  71. {
  72. if (previous == XCB_NONE)
  73. /* This would cause an error from the X server. Also, if we really
  74. * changed the stacking order of all windows, they'd all have to redraw
  75. * themselves. Doing it like this is better. */
  76. return;
  77. xcb_configure_window(globalconf.connection, w,
  78. XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE,
  79. (uint32_t[]) { previous, XCB_STACK_MODE_ABOVE });
  80. }
  81. /** Stack a client above.
  82. * \param c The client.
  83. * \param previous The previous client on the stack.
  84. * \return The next-previous!
  85. */
  86. static xcb_window_t
  87. stack_client_above(client_t *c, xcb_window_t previous)
  88. {
  89. stack_window_above(c->frame_window, previous);
  90. previous = c->frame_window;
  91. /* stack transient window on top of their parents */
  92. foreach(node, globalconf.stack)
  93. if((*node)->transient_for == c)
  94. previous = stack_client_above(*node, previous);
  95. return previous;
  96. }
  97. /** Stacking layout layers */
  98. typedef enum
  99. {
  100. /** This one is a special layer */
  101. WINDOW_LAYER_IGNORE,
  102. WINDOW_LAYER_DESKTOP,
  103. WINDOW_LAYER_BELOW,
  104. WINDOW_LAYER_NORMAL,
  105. WINDOW_LAYER_ABOVE,
  106. WINDOW_LAYER_FULLSCREEN,
  107. WINDOW_LAYER_ONTOP,
  108. /** This one only used for counting and is not a real layer */
  109. WINDOW_LAYER_COUNT
  110. } window_layer_t;
  111. /** Get the real layer of a client according to its attribute (fullscreen, …)
  112. * \param c The client.
  113. * \return The real layer.
  114. */
  115. static window_layer_t
  116. client_layer_translator(client_t *c)
  117. {
  118. /* first deal with user set attributes */
  119. if(c->ontop)
  120. return WINDOW_LAYER_ONTOP;
  121. /* Fullscreen windows only get their own layer when they have the focus */
  122. else if(c->fullscreen && globalconf.focus.client == c)
  123. return WINDOW_LAYER_FULLSCREEN;
  124. else if(c->above)
  125. return WINDOW_LAYER_ABOVE;
  126. else if(c->below)
  127. return WINDOW_LAYER_BELOW;
  128. /* check for transient attr */
  129. else if(c->transient_for)
  130. return WINDOW_LAYER_IGNORE;
  131. /* then deal with windows type */
  132. switch(c->type)
  133. {
  134. case WINDOW_TYPE_DESKTOP:
  135. return WINDOW_LAYER_DESKTOP;
  136. default:
  137. break;
  138. }
  139. return WINDOW_LAYER_NORMAL;
  140. }
  141. /** Restack clients.
  142. * \todo It might be worth stopping to restack everyone and only stack `c'
  143. * relatively to the first matching in the list.
  144. */
  145. void
  146. stack_refresh()
  147. {
  148. if(!need_stack_refresh)
  149. return;
  150. xcb_window_t next = XCB_NONE;
  151. /* stack desktop windows */
  152. for(window_layer_t layer = WINDOW_LAYER_DESKTOP; layer < WINDOW_LAYER_BELOW; layer++)
  153. foreach(node, globalconf.stack)
  154. if(client_layer_translator(*node) == layer)
  155. next = stack_client_above(*node, next);
  156. /* first stack not ontop drawin window */
  157. foreach(drawin, globalconf.drawins)
  158. if(!(*drawin)->ontop)
  159. {
  160. stack_window_above((*drawin)->window, next);
  161. next = (*drawin)->window;
  162. }
  163. /* then stack clients */
  164. for(window_layer_t layer = WINDOW_LAYER_BELOW; layer < WINDOW_LAYER_COUNT; layer++)
  165. foreach(node, globalconf.stack)
  166. if(client_layer_translator(*node) == layer)
  167. next = stack_client_above(*node, next);
  168. /* then stack ontop drawin window */
  169. foreach(drawin, globalconf.drawins)
  170. if((*drawin)->ontop)
  171. {
  172. stack_window_above((*drawin)->window, next);
  173. next = (*drawin)->window;
  174. }
  175. need_stack_refresh = false;
  176. }
  177. // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80