PageRenderTime 31ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/matwm2/buttons.c

http://segin-utils.googlecode.com/
C | 214 lines | 204 code | 10 blank | 0 comment | 124 complexity | bcdc71b487c8345c97ea4c0eb3576974 MD5 | raw file
Possible License(s): 0BSD, GPL-2.0
  1. #include "matwm.h"
  2. button *button_current = NULL;
  3. int button_down = 0;
  4. void buttons_create(client *c) {
  5. int i;
  6. p_attr.event_mask = 0;
  7. c->button_parent_left = XCreateWindow(dpy, c->parent, border_spacing, border_spacing, 1, 1, 0,
  8. depth, CopyFromParent, visual,
  9. CWOverrideRedirect | CWBackPixel | CWEventMask, &p_attr);
  10. c->button_parent_right = XCreateWindow(dpy, c->parent, 0, 0, 1, 1, 0,
  11. depth, CopyFromParent, visual,
  12. CWOverrideRedirect | CWBackPixel | CWEventMask, &p_attr);
  13. c->buttons = (void *) _malloc(sizeof(button) * (nbuttons_left + nbuttons_right));
  14. c->nbuttons = 0;
  15. c->buttons_left_width = 0;
  16. c->buttons_right_width = 0;
  17. p_attr.event_mask = ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | ExposureMask;
  18. for(i = 0; i < nbuttons_left; i++) {
  19. if((buttons_left[i] == B_EXPAND || buttons_left[i] == B_MAXIMIZE) && !(c->flags & CAN_MOVE && c->flags & CAN_RESIZE))
  20. continue;
  21. c->buttons[c->nbuttons].w = XCreateWindow(dpy, c->button_parent_left, c->buttons_left_width, 0, button_size, button_size, 0,
  22. depth, CopyFromParent, visual,
  23. CWOverrideRedirect | CWBackPixel | CWEventMask, &p_attr);
  24. XMapWindow(dpy, c->buttons[c->nbuttons].w);
  25. c->buttons[c->nbuttons].action = buttons_left[i];
  26. c->buttons_left_width += button_size + button_spacing;
  27. c->nbuttons++;
  28. }
  29. for(i = 0; i < nbuttons_right; i++) {
  30. if(((buttons_right[i] == B_EXPAND || buttons_right[i] == B_MAXIMIZE) && !(c->flags & CAN_MOVE && c->flags & CAN_RESIZE)))
  31. continue;
  32. c->buttons[c->nbuttons].w = XCreateWindow(dpy, c->button_parent_right, c->buttons_right_width, 0, button_size, button_size, 0,
  33. depth, CopyFromParent, visual,
  34. CWOverrideRedirect | CWBackPixel | CWEventMask, &p_attr);
  35. XMapWindow(dpy, c->buttons[c->nbuttons].w);
  36. c->buttons[c->nbuttons].action = buttons_right[i];
  37. c->buttons_right_width += button_size + button_spacing;
  38. c->nbuttons++;
  39. }
  40. c->buttons_right_width -= button_spacing;
  41. c->buttons_left_width -= button_spacing;
  42. if(c->buttons_left_width)
  43. XResizeWindow(dpy, c->button_parent_left, c->buttons_left_width, button_size);
  44. if(c->buttons_right_width)
  45. XResizeWindow(dpy, c->button_parent_right, c->buttons_right_width, button_size);
  46. buttons_update(c);
  47. }
  48. void buttons_draw(client *c) {
  49. int i;
  50. for(i = 0; i < c->nbuttons; i++)
  51. button_draw(c, &c->buttons[i]);
  52. }
  53. void button_draw(client *c, button *b) {
  54. XClearWindow(dpy, b->w);
  55. if(button_current == b)
  56. XDrawRectangle(dpy, b->w, gc, 0, 0, button_size - 1, button_size - 1);
  57. if(b->action == B_ICONIFY)
  58. XDrawRectangle(dpy, b->w, (c == current) ? gc : igc, (button_size / 2) - 1, (button_size / 2) - 1, 2, 2);
  59. if(b->action == B_EXPAND) {
  60. XDrawLine(dpy, b->w, (c == current) ? gc : igc, button_size / 2, 3, button_size / 2, button_size - 3);
  61. XDrawLine(dpy, b->w, (c == current) ? gc : igc, 3, button_size / 2, button_size - 3, button_size / 2);
  62. }
  63. if(b->action == B_MAXIMIZE) {
  64. if((c->flags & (MAXIMIZED_L | MAXIMIZED_R | MAXIMIZED_T | MAXIMIZED_B)) != (MAXIMIZED_L | MAXIMIZED_R | MAXIMIZED_T | MAXIMIZED_B))
  65. XDrawRectangle(dpy, b->w, (c == current) ? gc : igc, 2, 2, button_size - 5, button_size - 5);
  66. else {
  67. XDrawRectangle(dpy, b->w, (c == current) ? gc : igc, 2, 4, button_size - 7, button_size - 7);
  68. XDrawLine(dpy, b->w, (c == current) ? gc : igc, 4, 4, 4, 2);
  69. XDrawLine(dpy, b->w, (c == current) ? gc : igc, 4, 2, button_size - 3, 2);
  70. XDrawLine(dpy, b->w, (c == current) ? gc : igc, button_size - 3, 2, button_size - 3, button_size - 5);
  71. XDrawLine(dpy, b->w, (c == current) ? gc : igc, button_size - 2, button_size - 5, button_size - 5, button_size - 5);
  72. }
  73. }
  74. if(b->action == B_CLOSE) {
  75. XDrawLine(dpy, b->w, (c == current) ? gc : igc, 2, 2, button_size - 2, button_size - 2);
  76. XDrawLine(dpy, b->w, (c == current) ? gc : igc, 2, button_size - 3, button_size - 2, 1);
  77. }
  78. if(b->action == B_STICKY) {
  79. XDrawArc(dpy, b->w, (c == current) ? gc : igc, 2, 2, button_size - 5, button_size - 5, 0, 360 * 64);
  80. if(c->desktop == STICKY)
  81. XFillArc(dpy, b->w, (c == current) ? gc : igc, 2, 2, button_size - 5, button_size - 5, 0, 360 * 64);
  82. }
  83. if(b->action == B_ONTOP) {
  84. XDrawLine(dpy, b->w, (c == current) ? gc : igc, 2, button_size / 2, button_size / 2, 2);
  85. XDrawLine(dpy, b->w, (c == current) ? gc : igc, button_size - 2, (button_size / 2) + 1, button_size / 2, 2);
  86. if(c->layer == TOP) {
  87. XDrawLine(dpy, b->w, (c == current) ? gc : igc, 2, button_size - 3, button_size / 2, button_size / 2);
  88. XDrawLine(dpy, b->w, (c == current) ? gc : igc, button_size - 2, button_size - 2, button_size / 2, button_size / 2);
  89. }
  90. }
  91. if(b->action == B_BELOW) {
  92. XDrawLine(dpy, b->w, (c == current) ? gc : igc, 2, button_size / 2, (button_size / 2) + 1, button_size - 2);
  93. XDrawLine(dpy, b->w, (c == current) ? gc : igc, button_size - 2, (button_size / 2) - 1, button_size / 2, button_size - 3);
  94. if(c->layer == BOTTOM) {
  95. XDrawLine(dpy, b->w, (c == current) ? gc : igc, 2, 2, (button_size / 2) + 1, (button_size / 2) + 1);
  96. XDrawLine(dpy, b->w, (c == current) ? gc : igc, button_size - 2, 1, button_size / 2, button_size / 2);
  97. }
  98. }
  99. if(b->action == B_FULLSCREEN) {
  100. XDrawLine(dpy, b->w, (c == current) ? gc : igc, 2, 2, button_size - 2, button_size - 2);
  101. XDrawLine(dpy, b->w, (c == current) ? gc : igc, 2, button_size - 3, button_size - 2, 1);
  102. XDrawLine(dpy, b->w, (c == current) ? gc : igc, 2, 2, 2 + (button_size / 4), 2);
  103. XDrawLine(dpy, b->w, (c == current) ? gc : igc, 2, 2, 2, 2 + (button_size / 4));
  104. XDrawLine(dpy, b->w, (c == current) ? gc : igc, 2, button_size - 3, 2, (button_size - 3) - ((button_size / 4) - 1));
  105. XDrawLine(dpy, b->w, (c == current) ? gc : igc, 2, button_size - 3, 2 + (button_size / 4), button_size - 3);
  106. XDrawLine(dpy, b->w, (c == current) ? gc : igc, button_size - 3, button_size - 3, (button_size - 3) - ((button_size / 4) - 1), button_size - 3);
  107. XDrawLine(dpy, b->w, (c == current) ? gc : igc, button_size - 3, button_size - 3, button_size - 3, (button_size - 3) - ((button_size / 4) - 1));
  108. XDrawLine(dpy, b->w, (c == current) ? gc : igc, button_size - 3, 2, button_size - 3, 2 + (button_size / 4));
  109. XDrawLine(dpy, b->w, (c == current) ? gc : igc, button_size - 3, 2, (button_size - 3) - ((button_size / 4) - 1), 2);
  110. }
  111. }
  112. void buttons_update(client *c) { /* maps the buttons if the window has no buttons and schould have buttons and vice versa */
  113. if(c->flags & HAS_BUTTONS && client_width(c) <= (c->buttons_left_width ? c->buttons_left_width + button_spacing : 0) + (c->buttons_right_width ? c->buttons_right_width + button_spacing : 0)) {
  114. c->flags ^= HAS_BUTTONS;
  115. if(c->buttons_left_width)
  116. XUnmapWindow(dpy, c->button_parent_left);
  117. if(c->buttons_right_width)
  118. XUnmapWindow(dpy, c->button_parent_right);
  119. } else if(!(c->flags & HAS_BUTTONS) && client_width(c) > (c->buttons_left_width ? c->buttons_left_width + button_spacing : 0) + (c->buttons_right_width ? c->buttons_right_width + button_spacing : 0)) {
  120. c->flags |= HAS_BUTTONS;
  121. if(c->buttons_left_width)
  122. XMapWindow(dpy, c->button_parent_left);
  123. if(c->buttons_right_width)
  124. XMapWindow(dpy, c->button_parent_right);
  125. }
  126. XMoveWindow(dpy, c->button_parent_right, client_width(c) + border_spacing - c->buttons_right_width, border_spacing);
  127. }
  128. bool button_handle_event(XEvent *ev) {
  129. int i, j;
  130. client *c = NULL;
  131. button *b = NULL;
  132. for(i = 0; i < cn; i++)
  133. for(j = 0; j < clients[i]->nbuttons; j++)
  134. if(clients[i]->buttons[j].w == ev->xany.window) {
  135. c = clients[i];
  136. b = &clients[i]->buttons[j];
  137. }
  138. if(!c || !has_child(c->parent, c->window))
  139. return false;
  140. switch(ev->type) {
  141. case Expose:
  142. button_draw(c, b);
  143. return true;
  144. case EnterNotify:
  145. #ifdef DEBUG_EVENTS
  146. printf(NAME ": button_handle_event(): handling EnterNotify event\n");
  147. #endif
  148. if(button_down) {
  149. button_down = 2;
  150. return true;
  151. }
  152. button_current = b;
  153. button_draw(c, b);
  154. return true;
  155. case LeaveNotify:
  156. #ifdef DEBUG_EVENTS
  157. printf(NAME ": button_handle_event(): handling LeaveNotify event\n");
  158. #endif
  159. if(button_down == 2)
  160. button_down = 1;
  161. button_current = NULL;
  162. button_draw(c, b);
  163. return true;
  164. case ButtonPress:
  165. if(ev->xbutton.button == Button1 || ev->xbutton.button == Button3) {
  166. #ifdef DEBUG_EVENTS
  167. printf(NAME ": button_handle_event(): handling ButtonPress event\n");
  168. #endif
  169. button_down = 1;
  170. }
  171. return true;
  172. case ButtonRelease:
  173. #ifdef DEBUG_EVENTS
  174. printf(NAME ": button_handle_event(): handling ButtonRelease event\n");
  175. #endif
  176. if(ev->xbutton.button == Button1 || ev->xbutton.button == Button3) {
  177. if(button_current == b) {
  178. if(b->action == B_ICONIFY)
  179. client_iconify(c);
  180. if(b->action == B_EXPAND)
  181. client_expand(c, EXPANDED_L | EXPANDED_R | EXPANDED_T | EXPANDED_B, 0);
  182. if(b->action == B_MAXIMIZE)
  183. client_toggle_state(c, MAXIMIZED_L | MAXIMIZED_R | MAXIMIZED_T | MAXIMIZED_B);
  184. if(b->action == B_CLOSE)
  185. delete_window(c);
  186. if(b->action == B_STICKY)
  187. client_to_desktop(c, (c->desktop == STICKY) ? desktop : STICKY);
  188. if(b->action == B_ONTOP)
  189. client_set_layer(c, (c->layer == TOP) ? NORMAL : TOP);
  190. if(b->action == B_BELOW)
  191. client_set_layer(c, (c->layer == BOTTOM) ? NORMAL : BOTTOM);
  192. if(b->action == B_FULLSCREEN)
  193. client_fullscreen(c);
  194. }
  195. if(button_down == 2) {
  196. button_current = b;
  197. button_draw(c, b);
  198. }
  199. button_down = 0;
  200. }
  201. return true;
  202. }
  203. return false;
  204. }