Added "Hide Others" to the window menu
[wmaker-crm.git] / WPrefs.app / KeyboardShortcuts.c
blobeae3c21f4407929442b4434377dfe21e1e1a8ee2
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 WMBox *box;
33 char *sectionName;
35 char *description;
37 CallbackRec callbacks;
39 WMWidget *parent;
41 WMLabel *actL;
42 WMList *actLs;
44 WMFrame *shoF;
45 WMTextField *shoT;
46 WMButton *cleB;
47 WMButton *defB;
49 WMLabel *instructionsL;
51 WMColor *white;
52 WMColor *black;
53 WMFont *font;
55 /**/
56 char capturing;
57 char **shortcuts;
58 int actionCount;
59 } _Panel;
63 #define ICON_FILE "keyshortcuts"
66 /* must be in the same order as the corresponding items in actions list */
67 static char *keyOptions[] = {
68 "RootMenuKey",
69 "WindowListKey",
70 "WindowMenuKey",
71 "HideKey",
72 "HideOthersKey",
73 "MiniaturizeKey",
74 "CloseKey",
75 "MaximizeKey",
76 "VMaximizeKey",
77 "HMaximizeKey",
78 "RaiseKey",
79 "LowerKey",
80 "RaiseLowerKey",
81 "ShadeKey",
82 "MoveResizeKey",
83 "SelectKey",
84 "FocusNextKey",
85 "FocusPrevKey",
86 "NextWorkspaceKey",
87 "PrevWorkspaceKey",
88 "NextWorkspaceLayerKey",
89 "PrevWorkspaceLayerKey",
90 "Workspace1Key",
91 "Workspace2Key",
92 "Workspace3Key",
93 "Workspace4Key",
94 "Workspace5Key",
95 "Workspace6Key",
96 "Workspace7Key",
97 "Workspace8Key",
98 "Workspace9Key",
99 "Workspace10Key",
100 "WindowShortcut1Key",
101 "WindowShortcut2Key",
102 "WindowShortcut3Key",
103 "WindowShortcut4Key",
104 "WindowShortcut5Key",
105 "WindowShortcut6Key",
106 "WindowShortcut7Key",
107 "WindowShortcut8Key",
108 "WindowShortcut9Key",
109 "WindowShortcut10Key",
110 "ScreenSwitchKey",
111 "ClipRaiseKey",
112 "ClipLowerKey",
113 #ifndef XKB_MODELOCK
114 "ClipRaiseLowerKey"
115 #else
116 "ClipRaiseLowerKey",
117 "ToggleKbdModeKey"
118 #endif /* XKB_MODELOCK */
123 static char*
124 captureShortcut(Display *dpy, _Panel *panel)
126 XEvent ev;
127 KeySym ksym, lksym, uksym;
128 char buffer[64];
129 char *key = NULL;
131 while (panel->capturing) {
132 XAllowEvents(dpy, AsyncKeyboard, CurrentTime);
133 WMNextEvent(dpy, &ev);
134 if (ev.type==KeyPress && ev.xkey.keycode!=0) {
135 ksym = XKeycodeToKeysym(dpy, ev.xkey.keycode, 0);
136 if (!IsModifierKey(ksym)) {
137 XConvertCase(ksym, &lksym, &uksym);
138 key=XKeysymToString(uksym);
139 panel->capturing = 0;
140 break;
143 WMHandleEvent(&ev);
146 if (!key)
147 return NULL;
149 buffer[0] = 0;
151 if (ev.xkey.state & ControlMask) {
152 strcat(buffer, "Control+");
154 if (ev.xkey.state & ShiftMask) {
155 strcat(buffer, "Shift+");
157 if (ev.xkey.state & Mod1Mask) {
158 strcat(buffer, "Mod1+");
160 if (ev.xkey.state & Mod2Mask) {
161 strcat(buffer, "Mod2+");
163 if (ev.xkey.state & Mod3Mask) {
164 strcat(buffer, "Mod3+");
166 if (ev.xkey.state & Mod4Mask) {
167 strcat(buffer, "Mod4+");
169 if (ev.xkey.state & Mod5Mask) {
170 strcat(buffer, "Mod5+");
172 strcat(buffer, key);
174 return wstrdup(buffer);
178 static void
179 captureClick(WMWidget *w, void *data)
181 _Panel *panel = (_Panel*)data;
182 Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->parent));
183 char *shortcut;
185 if (!panel->capturing) {
186 panel->capturing = 1;
187 WMSetButtonText(w, _("Cancel"));
188 WMSetLabelText(panel->instructionsL, _("Press the desired shortcut key(s) or click Cancel to stop capturing."));
189 XGrabKeyboard(dpy, WMWidgetXID(panel->parent), True, GrabModeAsync,
190 GrabModeAsync, CurrentTime);
191 shortcut = captureShortcut(dpy, panel);
192 if (shortcut) {
193 int row = WMGetListSelectedItemRow(panel->actLs);
195 WMSetTextFieldText(panel->shoT, shortcut);
196 if (row>=0) {
197 if (panel->shortcuts[row])
198 wfree(panel->shortcuts[row]);
199 panel->shortcuts[row] = shortcut;
201 WMRedisplayWidget(panel->actLs);
202 } else {
203 wfree(shortcut);
207 panel->capturing = 0;
208 WMSetButtonText(w, _("Capture"));
209 WMSetLabelText(panel->instructionsL, _("Click Capture to interactively define the shortcut key."));
210 XUngrabKeyboard(dpy, CurrentTime);
215 static void
216 clearShortcut(WMWidget *w, void *data)
218 _Panel *panel = (_Panel*)data;
219 int row = WMGetListSelectedItemRow(panel->actLs);
221 WMSetTextFieldText(panel->shoT, NULL);
223 if (row>=0) {
224 if (panel->shortcuts[row])
225 wfree(panel->shortcuts[row]);
226 panel->shortcuts[row]=NULL;
227 WMRedisplayWidget(panel->actLs);
233 static void
234 typedKeys(void *observerData, WMNotification *notification)
236 _Panel *panel = (_Panel*)observerData;
237 int row = WMGetListSelectedItemRow(panel->actLs);
239 if (row<0)
240 return;
242 if (panel->shortcuts[row])
243 wfree(panel->shortcuts[row]);
244 panel->shortcuts[row] = WMGetTextFieldText(panel->shoT);
245 if (strlen(panel->shortcuts[row])==0) {
246 wfree(panel->shortcuts[row]);
247 panel->shortcuts[row] = NULL;
249 WMRedisplayWidget(panel->actLs);
254 static void
255 listClick(WMWidget *w, void *data)
257 _Panel *panel = (_Panel*)data;
258 int row = WMGetListSelectedItemRow(w);
260 WMSetTextFieldText(panel->shoT, panel->shortcuts[row]);
264 static char*
265 trimstr(char *str)
267 char *p = str;
268 int i;
270 while (isspace(*p)) p++;
271 p = wstrdup(p);
272 i = strlen(p);
273 while (isspace(p[i]) && i>0) {
274 p[i]=0;
275 i--;
278 return p;
282 static void
283 showData(_Panel *panel)
285 char *str;
286 int i;
288 for (i=0; i<panel->actionCount; i++) {
290 str = GetStringForKey(keyOptions[i]);
291 if (panel->shortcuts[i])
292 wfree(panel->shortcuts[i]);
293 if (str)
294 panel->shortcuts[i] = trimstr(str);
295 else
296 panel->shortcuts[i] = NULL;
298 if (panel->shortcuts[i] &&
299 (strcasecmp(panel->shortcuts[i], "none")==0
300 || strlen(panel->shortcuts[i])==0)) {
301 wfree(panel->shortcuts[i]);
302 panel->shortcuts[i] = NULL;
305 WMRedisplayWidget(panel->actLs);
309 static void
310 paintItem(WMList *lPtr, int index, Drawable d, char *text, int state,
311 WMRect *rect)
313 int width, height, x, y;
314 _Panel *panel = (_Panel*)WMGetHangedData(lPtr);
315 WMScreen *scr = WMWidgetScreen(lPtr);
316 Display *dpy = WMScreenDisplay(scr);
318 width = rect->size.width;
319 height = rect->size.height;
320 x = rect->pos.x;
321 y = rect->pos.y;
323 if (state & WLDSSelected)
324 XFillRectangle(dpy, d, WMColorGC(panel->white), x, y, width,
325 height);
326 else
327 XClearArea(dpy, d, x, y, width, height, False);
329 if (panel->shortcuts[index]) {
330 WMPixmap *pix = WMGetSystemPixmap(scr, WSICheckMark);
331 WMSize size = WMGetPixmapSize(pix);
333 WMDrawPixmap(pix, d, x+(20-size.width)/2, (height-size.height)/2+y);
334 WMReleasePixmap(pix);
337 WMDrawString(scr, d, WMColorGC(panel->black), panel->font, x+20, y,
338 text, strlen(text));
342 static void
343 createPanel(Panel *p)
345 _Panel *panel = (_Panel*)p;
346 WMScreen *scr = WMWidgetScreen(panel->parent);
347 WMColor *color;
348 WMFont *boldFont;
350 panel->capturing = 0;
354 panel->box = WMCreateBox(panel->parent);
355 WMSetViewExpandsToParent(WMWidgetView(panel->box), 2, 2, 2, 2);
357 boldFont = WMBoldSystemFontOfSize(scr, 12);
359 /* **************** Actions **************** */
360 panel->actL = WMCreateLabel(panel->box);
361 WMResizeWidget(panel->actL, 280, 20);
362 WMMoveWidget(panel->actL, 20, 10);
363 WMSetLabelFont(panel->actL, boldFont);
364 WMSetLabelText(panel->actL, _("Actions"));
365 WMSetLabelRelief(panel->actL, WRSunken);
366 WMSetLabelTextAlignment(panel->actL, WACenter);
367 color = WMDarkGrayColor(scr);
368 WMSetWidgetBackgroundColor(panel->actL, color);
369 WMReleaseColor(color);
370 color = WMWhiteColor(scr);
371 WMSetLabelTextColor(panel->actL, color);
372 WMReleaseColor(color);
374 panel->actLs = WMCreateList(panel->box);
375 WMResizeWidget(panel->actLs, 280, 190);
376 WMMoveWidget(panel->actLs, 20, 32);
377 WMSetListUserDrawProc(panel->actLs, paintItem);
378 WMHangData(panel->actLs, panel);
380 WMAddListItem(panel->actLs, _("Open applications menu"));
381 WMAddListItem(panel->actLs, _("Open window list menu"));
382 WMAddListItem(panel->actLs, _("Open window commands menu"));
383 WMAddListItem(panel->actLs, _("Hide active application"));
384 WMAddListItem(panel->actLs, _("Hide other applications"));
385 WMAddListItem(panel->actLs, _("Miniaturize active window"));
386 WMAddListItem(panel->actLs, _("Close active window"));
387 WMAddListItem(panel->actLs, _("Maximize active window"));
388 WMAddListItem(panel->actLs, _("Maximize active window vertically"));
389 WMAddListItem(panel->actLs, _("Maximize active window horizontally"));
390 WMAddListItem(panel->actLs, _("Raise active window"));
391 WMAddListItem(panel->actLs, _("Lower active window"));
392 WMAddListItem(panel->actLs, _("Raise/Lower window under mouse pointer"));
393 WMAddListItem(panel->actLs, _("Shade active window"));
394 WMAddListItem(panel->actLs, _("Move/Resize active window"));
395 WMAddListItem(panel->actLs, _("Select active window"));
396 WMAddListItem(panel->actLs, _("Focus next window"));
397 WMAddListItem(panel->actLs, _("Focus previous window"));
398 WMAddListItem(panel->actLs, _("Switch to next workspace"));
399 WMAddListItem(panel->actLs, _("Switch to previous workspace"));
400 WMAddListItem(panel->actLs, _("Switch to next ten workspaces"));
401 WMAddListItem(panel->actLs, _("Switch to previous ten workspaces"));
402 WMAddListItem(panel->actLs, _("Switch to workspace 1"));
403 WMAddListItem(panel->actLs, _("Switch to workspace 2"));
404 WMAddListItem(panel->actLs, _("Switch to workspace 3"));
405 WMAddListItem(panel->actLs, _("Switch to workspace 4"));
406 WMAddListItem(panel->actLs, _("Switch to workspace 5"));
407 WMAddListItem(panel->actLs, _("Switch to workspace 6"));
408 WMAddListItem(panel->actLs, _("Switch to workspace 7"));
409 WMAddListItem(panel->actLs, _("Switch to workspace 8"));
410 WMAddListItem(panel->actLs, _("Switch to workspace 9"));
411 WMAddListItem(panel->actLs, _("Switch to workspace 10"));
412 WMAddListItem(panel->actLs, _("Shortcut for window 1"));
413 WMAddListItem(panel->actLs, _("Shortcut for window 2"));
414 WMAddListItem(panel->actLs, _("Shortcut for window 3"));
415 WMAddListItem(panel->actLs, _("Shortcut for window 4"));
416 WMAddListItem(panel->actLs, _("Shortcut for window 5"));
417 WMAddListItem(panel->actLs, _("Shortcut for window 6"));
418 WMAddListItem(panel->actLs, _("Shortcut for window 7"));
419 WMAddListItem(panel->actLs, _("Shortcut for window 8"));
420 WMAddListItem(panel->actLs, _("Shortcut for window 9"));
421 WMAddListItem(panel->actLs, _("Shortcut for window 10"));
422 WMAddListItem(panel->actLs, _("Switch to Next Screen/Monitor"));
423 WMAddListItem(panel->actLs, _("Raise Clip"));
424 WMAddListItem(panel->actLs, _("Lower Clip"));
425 WMAddListItem(panel->actLs, _("Raise/Lower Clip"));
426 #ifdef XKB_MODELOCK
427 WMAddListItem(panel->actLs, _("Toggle keyboard language"));
428 #endif /* XKB_MODELOCK */
430 WMSetListAction(panel->actLs, listClick, panel);
432 panel->actionCount = WMGetListNumberOfRows(panel->actLs);
433 panel->shortcuts = wmalloc(sizeof(char*)*panel->actionCount);
434 memset(panel->shortcuts, 0, sizeof(char*)*panel->actionCount);
436 /***************** Shortcut ****************/
438 panel->shoF = WMCreateFrame(panel->box);
439 WMResizeWidget(panel->shoF, 190, 210);
440 WMMoveWidget(panel->shoF, 315, 10);
441 WMSetFrameTitle(panel->shoF, _("Shortcut"));
443 panel->shoT = WMCreateTextField(panel->shoF);
444 WMResizeWidget(panel->shoT, 160, 20);
445 WMMoveWidget(panel->shoT, 15, 65);
446 WMAddNotificationObserver(typedKeys, panel,
447 WMTextDidChangeNotification, panel->shoT);
449 panel->cleB = WMCreateCommandButton(panel->shoF);
450 WMResizeWidget(panel->cleB, 75, 24);
451 WMMoveWidget(panel->cleB, 15, 95);
452 WMSetButtonText(panel->cleB, _("Clear"));
453 WMSetButtonAction(panel->cleB, clearShortcut, panel);
455 panel->defB = WMCreateCommandButton(panel->shoF);
456 WMResizeWidget(panel->defB, 75, 24);
457 WMMoveWidget(panel->defB, 100, 95);
458 WMSetButtonText(panel->defB, _("Capture"));
459 WMSetButtonAction(panel->defB, captureClick, panel);
461 panel->instructionsL = WMCreateLabel(panel->shoF);
462 WMResizeWidget(panel->instructionsL, 160, 55);
463 WMMoveWidget(panel->instructionsL, 15, 140);
464 WMSetLabelTextAlignment(panel->instructionsL, WACenter);
465 WMSetLabelWraps(panel->instructionsL, True);
466 WMSetLabelText(panel->instructionsL, _("Click Capture to interactively define the shortcut key."));
468 WMMapSubwidgets(panel->shoF);
470 WMReleaseFont(boldFont);
472 WMRealizeWidget(panel->box);
473 WMMapSubwidgets(panel->box);
476 showData(panel);
480 static void
481 storeData(_Panel *panel)
483 int i;
484 char *str;
486 for (i=0; i<panel->actionCount; i++) {
487 str = NULL;
488 if (panel->shortcuts[i]) {
489 str = trimstr(panel->shortcuts[i]);
490 if (strlen(str)==0) {
491 wfree(str);
492 str = NULL;
495 if (str) {
496 SetStringForKey(str, keyOptions[i]);
497 wfree(str);
498 } else {
499 SetStringForKey("None", keyOptions[i]);
506 Panel*
507 InitKeyboardShortcuts(WMScreen *scr, WMWidget *parent)
509 _Panel *panel;
511 panel = wmalloc(sizeof(_Panel));
512 memset(panel, 0, sizeof(_Panel));
514 panel->sectionName = _("Keyboard Shortcut Preferences");
516 panel->description = _("Change the keyboard shortcuts for actions such\n"
517 "as changing workspaces and opening menus.");
519 panel->parent = parent;
521 panel->callbacks.createWidgets = createPanel;
522 panel->callbacks.updateDomain = storeData;
524 panel->white = WMWhiteColor(scr);
525 panel->black = WMBlackColor(scr);
526 panel->font = WMSystemFontOfSize(scr, 12);
528 AddSection(panel, ICON_FILE);
530 return panel;