JWM Source Documentation
action.c
Go to the documentation of this file.
1 
8 #include "jwm.h"
9 #include "action.h"
10 #include "tray.h"
11 #include "root.h"
12 #include "screen.h"
13 #include "misc.h"
14 #include "error.h"
15 #include "cursor.h"
16 #include "command.h"
17 #include "desktop.h"
18 #include "menu.h"
19 
20 typedef struct ActionType {
21  char *action;
22  struct ActionType *next;
23  int mask;
24 } ActionType;
25 
27 void AddAction(ActionType **actions, const char *action, int mask)
28 {
29  ActionType *ap;
30 
31  /* Make sure we actually have an action. */
32  if(action == NULL || action[0] == 0 || mask == 0) {
33  /* Valid (root menu 1). */
34  } else if(!strncmp(action, "exec:", 5)) {
35  /* Valid. */
36  } else if(!strncmp(action, "root:", 5)) {
37  /* Valid. However, the specified root menu may not exist.
38  * This case is handled in ValidateTrayButtons.
39  */
40  } else if(!strcmp(action, "showdesktop")) {
41  /* Valid. */
42  } else {
43  /* Invalid; don't add the action. */
44  Warning(_("invalid action: \"%s\""), action);
45  return;
46  }
47 
48  ap = (ActionType*)Allocate(sizeof(ActionType));
49  ap->action = CopyString(action);
50  ap->mask = mask;
51  ap->next = *actions;
52  *actions = ap;
53 }
54 
56 void DestroyActions(ActionType *actions)
57 {
58  while(actions) {
59  ActionType *next = actions->next;
60  Release(actions->action);
61  Release(actions);
62  actions = next;
63  }
64 }
65 
67 void ProcessActionPress(struct ActionType *actions,
68  struct TrayComponentType *cp,
69  int x, int y, int button)
70 {
71  const ScreenType *sp;
72  const ActionType *ap;
73  const int mask = 1 << button;
74  int mwidth, mheight;
75  int menu;
76 
77  if(JUNLIKELY(menuShown)) {
78  return;
79  }
80  if (x < -1 || x > cp->width) {
81  return;
82  }
83  if (y < -1 || y > cp->height) {
84  return;
85  }
86 
87  menu = -1;
88  for(ap = actions; ap; ap = ap->next) {
89  if(ap->mask & mask) {
90  if(ap->action && ap->action[0]) {
91  if(strncmp(ap->action, "root:", 5) != 0) {
92  if(button == Button4 || button == Button5) {
93 
94  /* Don't wait for a release if the scroll wheel is used. */
95  if(!strncmp(ap->action, "exec:", 5)) {
96  RunCommand(ap->action + 5);
97  } else if(!strcmp(ap->action, "showdesktop")) {
98  ShowDesktop();
99  }
100 
101  } else {
102 
103  if(!GrabMouse(cp->tray->window)) {
104  return;
105  }
106 
107  /* Show the button being pressed. */
108  cp->grabbed = 1;
109  if(cp->Redraw) {
110  (cp->Redraw)(cp);
111  UpdateSpecificTray(cp->tray, cp);
112  }
113  }
114  return;
115 
116  } else {
117  menu = GetRootMenuIndexFromString(&ap->action[5]);
118  }
119  } else {
120  menu = 1;
121  }
122  break;
123  }
124  }
125  if(menu < 0) {
126  return;
127  }
128 
129  GetRootMenuSize(menu, &mwidth, &mheight);
130  sp = GetCurrentScreen(cp->screenx, cp->screeny);
131  if(cp->tray->layout == LAYOUT_HORIZONTAL) {
132  x = cp->screenx - 1;
133  if(cp->screeny + cp->height / 2 < sp->y + sp->height / 2) {
134  y = cp->screeny + cp->height;
135  } else {
136  y = cp->screeny - mheight;
137  }
138  } else {
139  y = cp->screeny - 1;
140  if(cp->screenx + cp->width / 2 < sp->x + sp->width / 2) {
141  x = cp->screenx + cp->width;
142  } else {
143  x = cp->screenx - mwidth;
144  }
145  }
146 
147  cp->grabbed = 1;
148  if(cp->Redraw) {
149  (cp->Redraw)(cp);
150  UpdateSpecificTray(cp->tray, cp);
151  }
152  if(ShowRootMenu(menu, x, y, 0)) {
153  cp->grabbed = 0;
154  if(cp->Redraw) {
155  (cp->Redraw)(cp);
156  UpdateSpecificTray(cp->tray, cp);
157  }
158  }
159 }
160 
162 void ProcessActionRelease(struct ActionType *actions,
163  struct TrayComponentType *cp,
164  int x, int y, int button)
165 {
166  const ActionType *ap;
167  const int mask = 1 << button;
168 
169  if(JUNLIKELY(menuShown)) {
170  return;
171  }
172 
173  cp->grabbed = 0;
174  if(cp->Redraw) {
175  (cp->Redraw)(cp);
176  UpdateSpecificTray(cp->tray, cp);
177  }
178 
179  /* Since we grab the mouse, make sure the mouse is actually over
180  * the button. */
181  if(x < -1 || x > cp->width) {
182  return;
183  }
184  if(y < -1 || y > cp->height) {
185  return;
186  }
187 
188  /* Run the action (if any). */
189  for(ap = actions; ap; ap = ap->next) {
190  if(ap->mask & mask) {
191  if(ap->action && strlen(ap->action) > 0) {
192  if(!strncmp(ap->action, "exec:", 5)) {
193  RunCommand(ap->action + 5);
194  } else if(!strcmp(ap->action, "showdesktop")) {
195  ShowDesktop();
196  }
197  }
198  return;
199  }
200  }
201 }
202 
204 void ValidateActions(const ActionType *actions)
205 {
206  const ActionType *ap;
207  for(ap = actions; ap; ap = ap->next) {
208  if(ap->action && !strncmp(ap->action, "root:", 5)) {
209  const int bindex = GetRootMenuIndexFromString(&ap->action[5]);
210  if(JUNLIKELY(!IsRootMenuDefined(bindex))) {
211  Warning(_("action: root menu \"%s\" not defined"),
212  &ap->action[5]);
213  }
214  }
215  }
216 }

joewing.net / Projects / JWM