Updating to version 0.20.2
[wmaker-crm.git] / WPrefs.app / KeyboardShortcuts.c
blob4f168427aa661867d4f48c8c8cefe6c425bcc41e
1 /* KeyboardShortcuts.c- keyboard shortcut bindings
2 *
3 * WPrefs - Window Maker Preferences Program
4 *
5 * Copyright (c) 1998 Alfredo K. Kojima
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 * USA.
24 #include "WPrefs.h"
25 #include <ctype.h>
27 #include <X11/keysym.h>
30 typedef struct _Panel {
31 WMFrame *frame;
33 char *sectionName;
35 CallbackRec callbacks;
37 WMWindow *win;
39 WMLabel *actL;
40 WMList *actLs;
42 WMFrame *shoF;
43 WMTextField *shoT;
44 WMButton *cleB;
45 WMButton *defB;
47 WMLabel *instructionsL;
49 /**/
50 char capturing;
51 char **shortcuts;
52 int actionCount;
53 } _Panel;
57 #define ICON_FILE "keyshortcuts"
60 /* must be in the same order as the corresponding items in actions list */
61 static char *keyOptions[] = {
62 "RootMenuKey",
63 "WindowListKey",
64 "WindowMenuKey",
65 "HideKey",
66 "MiniaturizeKey",
67 "CloseKey",
68 "MaximizeKey",
69 "VMaximizeKey",
70 "RaiseKey",
71 "LowerKey",
72 "RaiseLowerKey",
73 "ShadeKey",
74 "SelectKey",
75 "FocusNextKey",
76 "FocusPrevKey",
77 "NextWorkspaceKey",
78 "PrevWorkspaceKey",
79 "NextWorkspaceLayerKey",
80 "PrevWorkspaceLayerKey",
81 "Workspace1Key",
82 "Workspace2Key",
83 "Workspace3Key",
84 "Workspace4Key",
85 "Workspace5Key",
86 "Workspace6Key",
87 "Workspace7Key",
88 "Workspace8Key",
89 "Workspace9Key",
90 "Workspace10Key",
91 "ClipRaiseKey",
92 "ClipLowerKey",
93 "ClipRaiseLowerKey"
98 static char*
99 captureShortcut(Display *dpy, _Panel *panel)
101 XEvent ev;
102 KeySym ksym;
103 char buffer[64];
104 char *key = NULL;
106 while (panel->capturing) {
107 XAllowEvents(dpy, AsyncKeyboard, CurrentTime);
108 WMNextEvent(dpy, &ev);
109 if (ev.type==KeyPress && ev.xkey.keycode!=0) {
110 ksym = XKeycodeToKeysym(dpy, ev.xkey.keycode, 0);
111 if (!IsModifierKey(ksym)) {
112 key=XKeysymToString(ksym);
113 panel->capturing = 0;
114 break;
117 WMHandleEvent(&ev);
120 if (!key)
121 return NULL;
123 buffer[0] = 0;
125 if (ev.xkey.state & ControlMask) {
126 strcat(buffer, "Control+");
128 if (ev.xkey.state & ShiftMask) {
129 strcat(buffer, "Shift+");
131 if (ev.xkey.state & Mod1Mask) {
132 strcat(buffer, "Mod1+");
134 if (ev.xkey.state & Mod2Mask) {
135 strcat(buffer, "Mod2+");
137 if (ev.xkey.state & Mod3Mask) {
138 strcat(buffer, "Mod3+");
140 if (ev.xkey.state & Mod4Mask) {
141 strcat(buffer, "Mod4+");
143 if (ev.xkey.state & Mod5Mask) {
144 strcat(buffer, "Mod5+");
146 strcat(buffer, key);
148 return wstrdup(buffer);
152 static void
153 captureClick(WMWidget *w, void *data)
155 _Panel *panel = (_Panel*)data;
156 Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->win));
157 char *shortcut;
159 if (!panel->capturing) {
160 panel->capturing = 1;
161 WMSetButtonText(w, _("Cancel"));
162 WMSetLabelText(panel->instructionsL, _("Press the desired shortcut key(s) or click Cancel to stop capturing."));
163 XGrabKeyboard(dpy, WMWidgetXID(panel->win), True, GrabModeAsync,
164 GrabModeAsync, CurrentTime);
165 shortcut = captureShortcut(dpy, panel);
166 if (shortcut) {
167 int row = WMGetListSelectedItemRow(panel->actLs);
169 WMSetTextFieldText(panel->shoT, shortcut);
170 if (row>=0) {
171 if (panel->shortcuts[row])
172 free(panel->shortcuts[row]);
173 panel->shortcuts[row] = shortcut;
174 } else {
175 free(shortcut);
179 panel->capturing = 0;
180 WMSetButtonText(w, _("Capture"));
181 WMSetLabelText(panel->instructionsL, _("Click Capture to interactively define the shortcut key."));
182 XUngrabKeyboard(dpy, CurrentTime);
187 static void
188 clearShortcut(WMWidget *w, void *data)
190 _Panel *panel = (_Panel*)data;
191 int row = WMGetListSelectedItemRow(panel->actLs);
193 WMSetTextFieldText(panel->shoT, NULL);
195 if (row>=0) {
196 if (panel->shortcuts[row])
197 free(panel->shortcuts[row]);
198 panel->shortcuts[row]=NULL;
204 static void
205 typedKeys(void *observerData, WMNotification *notification)
207 _Panel *panel = (_Panel*)observerData;
208 int row = WMGetListSelectedItemRow(panel->actLs);
210 if (row<0)
211 return;
213 if (panel->shortcuts[row])
214 free(panel->shortcuts[row]);
215 panel->shortcuts[row] = WMGetTextFieldText(panel->shoT);
216 if (strlen(panel->shortcuts[row])==0) {
217 free(panel->shortcuts[row]);
218 panel->shortcuts[row] = NULL;
224 static void
225 listClick(WMWidget *w, void *data)
227 _Panel *panel = (_Panel*)data;
228 int row = WMGetListSelectedItemRow(w);
230 WMSetTextFieldText(panel->shoT, panel->shortcuts[row]);
234 static char*
235 trimstr(char *str)
237 char *p = str;
238 int i;
240 while (isspace(*p)) p++;
241 p = wstrdup(p);
242 i = strlen(p);
243 while (isspace(p[i]) && i>0) {
244 p[i]=0;
245 i--;
248 return p;
252 static void
253 showData(_Panel *panel)
255 char *str;
256 int i;
258 for (i=0; i<panel->actionCount; i++) {
260 str = GetStringForKey(keyOptions[i]);
261 if (panel->shortcuts[i])
262 free(panel->shortcuts[i]);
263 if (str)
264 panel->shortcuts[i] = trimstr(str);
265 else
266 panel->shortcuts[i] = NULL;
268 if (panel->shortcuts[i] &&
269 (strcasecmp(panel->shortcuts[i], "none")==0
270 || strlen(panel->shortcuts[i])==0)) {
271 free(panel->shortcuts[i]);
272 panel->shortcuts[i] = NULL;
278 static void
279 createPanel(Panel *p)
281 _Panel *panel = (_Panel*)p;
282 WMScreen *scr = WMWidgetScreen(panel->win);
283 WMColor *color;
284 WMFont *boldFont;
286 panel->capturing = 0;
288 panel->frame = WMCreateFrame(panel->win);
289 WMResizeWidget(panel->frame, FRAME_WIDTH, FRAME_HEIGHT);
290 WMMoveWidget(panel->frame, FRAME_LEFT, FRAME_TOP);
292 boldFont = WMBoldSystemFontOfSize(scr, 12);
294 /* **************** Actions **************** */
295 panel->actL = WMCreateLabel(panel->frame);
296 WMResizeWidget(panel->actL, 280, 20);
297 WMMoveWidget(panel->actL, 20, 10);
298 WMSetLabelFont(panel->actL, boldFont);
299 WMSetLabelText(panel->actL, _("Actions"));
300 WMSetLabelRelief(panel->actL, WRSunken);
301 WMSetLabelTextAlignment(panel->actL, WACenter);
302 color = WMDarkGrayColor(scr);
303 WMSetWidgetBackgroundColor(panel->actL, color);
304 WMReleaseColor(color);
305 color = WMWhiteColor(scr);
306 WMSetLabelTextColor(panel->actL, color);
307 WMReleaseColor(color);
309 panel->actLs = WMCreateList(panel->frame);
310 WMResizeWidget(panel->actLs, 280, 190);
311 WMMoveWidget(panel->actLs, 20, 32);
313 WMAddListItem(panel->actLs, _("Open applications menu"));
314 WMAddListItem(panel->actLs, _("Open window list menu"));
315 WMAddListItem(panel->actLs, _("Open window commands menu"));
316 WMAddListItem(panel->actLs, _("Hide active application"));
317 WMAddListItem(panel->actLs, _("Miniaturize active window"));
318 WMAddListItem(panel->actLs, _("Close active window"));
319 WMAddListItem(panel->actLs, _("Maximize active window"));
320 WMAddListItem(panel->actLs, _("Maximize active window vertically"));
321 WMAddListItem(panel->actLs, _("Raise active window"));
322 WMAddListItem(panel->actLs, _("Lower active window"));
323 WMAddListItem(panel->actLs, _("Raise/Lower window under mouse pointer"));
324 WMAddListItem(panel->actLs, _("Shade active window"));
325 WMAddListItem(panel->actLs, _("Select active window"));
326 WMAddListItem(panel->actLs, _("Focus next window"));
327 WMAddListItem(panel->actLs, _("Focus previous window"));
328 WMAddListItem(panel->actLs, _("Switch to next workspace"));
329 WMAddListItem(panel->actLs, _("Switch to previous workspace"));
330 WMAddListItem(panel->actLs, _("Switch to next ten workspaces"));
331 WMAddListItem(panel->actLs, _("Switch to previous ten workspaces"));
332 WMAddListItem(panel->actLs, _("Switch to workspace 1"));
333 WMAddListItem(panel->actLs, _("Switch to workspace 2"));
334 WMAddListItem(panel->actLs, _("Switch to workspace 3"));
335 WMAddListItem(panel->actLs, _("Switch to workspace 4"));
336 WMAddListItem(panel->actLs, _("Switch to workspace 5"));
337 WMAddListItem(panel->actLs, _("Switch to workspace 6"));
338 WMAddListItem(panel->actLs, _("Switch to workspace 7"));
339 WMAddListItem(panel->actLs, _("Switch to workspace 8"));
340 WMAddListItem(panel->actLs, _("Switch to workspace 9"));
341 WMAddListItem(panel->actLs, _("Switch to workspace 10"));
342 WMAddListItem(panel->actLs, _("Raise Clip"));
343 WMAddListItem(panel->actLs, _("Lower Clip"));
344 WMAddListItem(panel->actLs, _("Raise/Lower Clip"));
346 WMSetListAction(panel->actLs, listClick, panel);
348 panel->actionCount = WMGetListNumberOfRows(panel->actLs);
349 panel->shortcuts = wmalloc(sizeof(char*)*panel->actionCount);
350 memset(panel->shortcuts, 0, sizeof(char*)*panel->actionCount);
352 /***************** Shortcut ****************/
354 panel->shoF = WMCreateFrame(panel->frame);
355 WMResizeWidget(panel->shoF, 190, 210);
356 WMMoveWidget(panel->shoF, 315, 10);
357 WMSetFrameTitle(panel->shoF, _("Shortcut"));
359 panel->shoT = WMCreateTextField(panel->shoF);
360 WMResizeWidget(panel->shoT, 160, 20);
361 WMMoveWidget(panel->shoT, 15, 65);
362 WMAddNotificationObserver(typedKeys, panel,
363 WMTextDidChangeNotification, panel->shoT);
365 panel->cleB = WMCreateCommandButton(panel->shoF);
366 WMResizeWidget(panel->cleB, 75, 24);
367 WMMoveWidget(panel->cleB, 15, 95);
368 WMSetButtonText(panel->cleB, _("Clear"));
369 WMSetButtonAction(panel->cleB, clearShortcut, panel);
371 panel->defB = WMCreateCommandButton(panel->shoF);
372 WMResizeWidget(panel->defB, 75, 24);
373 WMMoveWidget(panel->defB, 100, 95);
374 WMSetButtonText(panel->defB, _("Capture"));
375 WMSetButtonAction(panel->defB, captureClick, panel);
377 panel->instructionsL = WMCreateLabel(panel->shoF);
378 WMResizeWidget(panel->instructionsL, 160, 55);
379 WMMoveWidget(panel->instructionsL, 15, 140);
380 WMSetLabelTextAlignment(panel->instructionsL, WACenter);
381 WMSetLabelText(panel->instructionsL, _("Click Capture to interactively define the shortcut key."));
383 WMMapSubwidgets(panel->shoF);
385 WMReleaseFont(boldFont);
387 WMRealizeWidget(panel->frame);
388 WMMapSubwidgets(panel->frame);
391 showData(panel);
395 static void
396 storeData(_Panel *panel)
398 int i;
399 char *str;
401 for (i=0; i<panel->actionCount; i++) {
402 str = NULL;
403 if (panel->shortcuts[i]) {
404 str = trimstr(panel->shortcuts[i]);
405 if (strlen(str)==0) {
406 free(str);
407 str = NULL;
410 if (str) {
411 SetStringForKey(str, keyOptions[i]);
412 free(str);
413 } else {
414 SetStringForKey("None", keyOptions[i]);
421 Panel*
422 InitKeyboardShortcuts(WMScreen *scr, WMWindow *win)
424 _Panel *panel;
426 panel = wmalloc(sizeof(_Panel));
427 memset(panel, 0, sizeof(_Panel));
429 panel->sectionName = _("Keyboard Shortcut Preferences");
431 panel->win = win;
433 panel->callbacks.createWidgets = createPanel;
434 panel->callbacks.updateDomain = storeData;
436 AddSection(panel, ICON_FILE);
438 return panel;