JWM Source Documentation
winmenu.c
Go to the documentation of this file.
1 
10 #include "jwm.h"
11 #include "winmenu.h"
12 #include "client.h"
13 #include "desktop.h"
14 #include "move.h"
15 #include "resize.h"
16 #include "event.h"
17 #include "cursor.h"
18 #include "misc.h"
19 #include "root.h"
20 #include "settings.h"
21 
22 static void CreateWindowLayerMenu(Menu *menu, ClientNode *np);
23 static void CreateWindowSendToMenu(Menu *menu, ClientNode *np);
24 static void AddWindowMenuItem(Menu *menu, const char *name,
25  MenuActionType type,
26  ClientNode *np, int value);
27 
29 void ShowWindowMenu(ClientNode *np, int x, int y, char keyboard)
30 {
31  Menu *menu = CreateWindowMenu(np);
32  InitializeMenu(menu);
33  ShowMenu(menu, RunWindowCommand, x, y, keyboard);
34  DestroyMenu(menu);
35 }
36 
39 {
40 
41  Menu *menu;
42 
43  menu = CreateMenu();
44 
45  /* Note that items are added in reverse order of display. */
46 
47  if(!(np->state.status & STAT_WMDIALOG)) {
48  AddWindowMenuItem(menu, _("Close"), MA_CLOSE, np, 0);
49  AddWindowMenuItem(menu, _("Kill"), MA_KILL, np, 0);
50  AddWindowMenuItem(menu, NULL, MA_NONE, np, 0);
51  }
52 
54  || np->state.maxFlags)) {
55  if(np->state.status & (STAT_MAPPED | STAT_SHADED)) {
56  if(np->state.border & BORDER_RESIZE) {
57  AddWindowMenuItem(menu, _("Resize"), MA_RESIZE, np, 0);
58  }
59  if(np->state.border & BORDER_MOVE) {
60  AddWindowMenuItem(menu, _("Move"), MA_MOVE, np, 0);
61  }
62  }
63  }
64 
65  if((np->state.border & BORDER_MIN) && !(np->state.status & STAT_MINIMIZED)) {
66  AddWindowMenuItem(menu, _("Minimize"), MA_MINIMIZE, np, 0);
67  }
68 
69  if(!(np->state.status & STAT_FULLSCREEN)) {
70  if(!(np->state.status & STAT_MINIMIZED)) {
71  if(np->state.status & STAT_SHADED) {
72  AddWindowMenuItem(menu, _("Unshade"), MA_SHADE, np, 0);
73  } else if(np->state.border & BORDER_SHADE) {
74  AddWindowMenuItem(menu, _("Shade"), MA_SHADE, np, 0);
75  }
76  }
77  if(np->state.border & BORDER_MAX) {
78  if(np->state.status & STAT_MINIMIZED
79  || !(np->state.maxFlags & MAX_VERT)
80  || np->state.maxFlags & MAX_HORIZ) {
81  AddWindowMenuItem(menu, _("Maximize-y"), MA_MAXIMIZE_V, np, 0);
82  }
83  if(np->state.status & STAT_MINIMIZED
84  || !(np->state.maxFlags & MAX_HORIZ)
85  || np->state.maxFlags & MAX_VERT) {
86  AddWindowMenuItem(menu, _("Maximize-x"), MA_MAXIMIZE_H, np, 0);
87  }
88  if(np->state.status & STAT_MINIMIZED
89  || !(np->state.maxFlags & (MAX_VERT | MAX_HORIZ))) {
90  AddWindowMenuItem(menu, _("Maximize"), MA_MAXIMIZE, np, 0);
91  }
92  if(!(np->state.status & STAT_MINIMIZED)) {
93  if((np->state.maxFlags & MAX_HORIZ)
94  && (np->state.maxFlags & MAX_VERT)) {
95  AddWindowMenuItem(menu, _("Restore"), MA_MAXIMIZE, np, 0);
96  } else if(np->state.maxFlags & MAX_VERT) {
97  AddWindowMenuItem(menu, _("Restore"), MA_MAXIMIZE_V, np, 0);
98  } else if(np->state.maxFlags & MAX_HORIZ) {
99  AddWindowMenuItem(menu, _("Restore"), MA_MAXIMIZE_H, np, 0);
100  }
101  }
102  }
103  }
104 
105  if(np->state.status & STAT_MINIMIZED) {
106  AddWindowMenuItem(menu, _("Restore"), MA_RESTORE, np, 0);
107  }
108 
109  if(!(np->state.status & STAT_WMDIALOG)) {
110  if(settings.desktopCount > 1) {
111  if(np->state.status & STAT_STICKY) {
112  AddWindowMenuItem(menu, _("Unstick"), MA_STICK, np, 0);
113  } else {
114  AddWindowMenuItem(menu, _("Stick"), MA_STICK, np, 0);
115  }
116  }
117 
118  CreateWindowLayerMenu(menu, np);
119 
120  if(settings.desktopCount > 1) {
121  if(!(np->state.status & STAT_STICKY)) {
122  CreateWindowSendToMenu(menu, np);
123  }
124  }
125 
126  }
127 
128  return menu;
129 }
130 
133 {
134 
135  Menu *submenu;
136  MenuItem *item;
137 
139  item->name = CopyString(_("Layer"));
140  item->action.type = MA_NONE;
141  item->next = menu->items;
142  menu->items = item;
143 
144  submenu = CreateMenu();
145  item->submenu = submenu;
146 
147  if(np->state.layer == LAYER_ABOVE) {
148  AddWindowMenuItem(submenu, _("[Above]"), MA_LAYER, np, LAYER_ABOVE);
149  } else {
150  AddWindowMenuItem(submenu, _("Above"), MA_LAYER, np, LAYER_ABOVE);
151  }
152  if(np->state.layer == LAYER_NORMAL) {
153  AddWindowMenuItem(submenu, _("[Normal]"), MA_LAYER, np, LAYER_NORMAL);
154  } else {
155  AddWindowMenuItem(submenu, _("Normal"), MA_LAYER, np, LAYER_NORMAL);
156  }
157  if(np->state.layer == LAYER_BELOW) {
158  AddWindowMenuItem(submenu, _("[Below]"), MA_LAYER, np, LAYER_BELOW);
159  } else {
160  AddWindowMenuItem(submenu, _("Below"), MA_LAYER, np, LAYER_BELOW);
161  }
162 
163 }
164 
167 {
168 
169  unsigned int mask;
170  unsigned int x;
171 
172  mask = 0;
173  for(x = 0; x < settings.desktopCount; x++) {
174  if(np->state.desktop == x || (np->state.status & STAT_STICKY)) {
175  mask |= 1 << x;
176  }
177  }
178 
179  AddWindowMenuItem(menu, _("Send To"), MA_NONE, np, 0);
180 
181  /* Now the first item in the menu is for the desktop list. */
182  menu->items->submenu = CreateDesktopMenu(mask, np);
183 
184 }
185 
187 void AddWindowMenuItem(Menu *menu, const char *name, MenuActionType type,
188  ClientNode *np, int value)
189 {
190 
191  MenuItem *item;
192 
194  item->name = CopyString(name);
195  item->action.type = type;
196  item->action.context = np;
197  item->action.value = value;
198  item->next = menu->items;
199  menu->items = item;
200 
201 }
202 
205 {
206 
207  XEvent event;
208  ClientNode *np;
209 
210  if(!GrabMouseForChoose()) {
211  return;
212  }
213 
214  for(;;) {
215 
216  WaitForEvent(&event);
217 
218  if(event.type == ButtonPress) {
219  if(event.xbutton.button == Button1) {
220  np = FindClient(event.xbutton.subwindow);
221  if(np) {
222  action->context = np;
223  RunWindowCommand(action, event.xbutton.button);
224  }
225  }
226  break;
227  } else if(event.type == KeyPress) {
228  break;
229  }
230 
231  }
232 
233  JXUngrabPointer(display, CurrentTime);
234 
235 }
236 
238 void RunWindowCommand(MenuAction *action, unsigned button)
239 {
240  ClientNode *client = action->context;
241  switch(action->type) {
242  case MA_STICK:
243  if(client->state.status & STAT_STICKY) {
244  SetClientSticky(client, 0);
245  } else {
246  SetClientSticky(client, 1);
247  }
248  break;
249  case MA_MAXIMIZE:
250  if((client->state.maxFlags & MAX_HORIZ)
251  && (client->state.maxFlags & MAX_VERT)
252  && !(client->state.status & STAT_MINIMIZED)) {
253  MaximizeClient(client, MAX_NONE);
254  } else {
255  MaximizeClient(client, MAX_VERT | MAX_HORIZ);
256  }
257  break;
258  case MA_MAXIMIZE_H:
259  if((client->state.maxFlags & MAX_HORIZ)
260  && !(client->state.maxFlags & MAX_VERT)
261  && !(client->state.status & STAT_MINIMIZED)) {
262  MaximizeClient(client, MAX_NONE);
263  } else {
264  MaximizeClient(client, MAX_HORIZ);
265  }
266  break;
267  case MA_MAXIMIZE_V:
268  if((client->state.maxFlags & MAX_VERT)
269  && !(client->state.maxFlags & MAX_HORIZ)
270  && !(client->state.status & STAT_MINIMIZED)) {
271  MaximizeClient(client, MAX_NONE);
272  } else {
273  MaximizeClient(client, MAX_VERT);
274  }
275  break;
276  case MA_MINIMIZE:
277  MinimizeClient(client, 1);
278  break;
279  case MA_RESTORE:
280  RestoreClient(client, 1);
281  break;
282  case MA_CLOSE:
283  DeleteClient(client);
284  break;
285  case MA_SENDTO:
286  case MA_DESKTOP:
287  SetClientDesktop(client, action->value);
288  break;
289  case MA_SHADE:
290  if(client->state.status & STAT_SHADED) {
291  UnshadeClient(client);
292  } else {
293  ShadeClient(client);
294  }
295  break;
296  case MA_MOVE:
297  MoveClientKeyboard(client);
298  break;
299  case MA_RESIZE:
300  ResizeClientKeyboard(client);
301  break;
302  case MA_KILL:
303  KillClient(client);
304  break;
305  case MA_LAYER:
306  SetClientLayer(client, action->value);
307  break;
308  default:
309  break;
310  }
311 
312 }

joewing.net / Projects / JWM