added balloon help
[wmaker-crm.git] / WPrefs.app / KeyboardShortcuts.c
blobebea640e71bea7ec3103bada9a6b56c9c984f4d2
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 char *description;
37 CallbackRec callbacks;
39 WMWindow *win;
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 "MiniaturizeKey",
73 "CloseKey",
74 "MaximizeKey",
75 "VMaximizeKey",
76 "RaiseKey",
77 "LowerKey",
78 "RaiseLowerKey",
79 "ShadeKey",
80 "MoveResizeKey",
81 "SelectKey",
82 "FocusNextKey",
83 "FocusPrevKey",
84 "NextWorkspaceKey",
85 "PrevWorkspaceKey",
86 "NextWorkspaceLayerKey",
87 "PrevWorkspaceLayerKey",
88 "Workspace1Key",
89 "Workspace2Key",
90 "Workspace3Key",
91 "Workspace4Key",
92 "Workspace5Key",
93 "Workspace6Key",
94 "Workspace7Key",
95 "Workspace8Key",
96 "Workspace9Key",
97 "Workspace10Key",
98 "WindowShortcut1Key",
99 "WindowShortcut2Key",
100 "WindowShortcut3Key",
101 "WindowShortcut4Key",
102 #ifdef EXTEND_WINDOWSHORTCUT
103 "WindowShortcut5Key",
104 "WindowShortcut6Key",
105 "WindowShortcut7Key",
106 "WindowShortcut8Key",
107 "WindowShortcut9Key",
108 "WindowShortcut10Key",
109 #endif
110 "ClipRaiseKey",
111 "ClipLowerKey",
112 #ifndef XKB_MODELOCK
113 "ClipRaiseLowerKey"
114 #else
115 "ClipRaiseLowerKey",
116 "ToggleKbdModeKey"
117 #endif /* XKB_MODELOCK */
122 static char*
123 captureShortcut(Display *dpy, _Panel *panel)
125 XEvent ev;
126 KeySym ksym;
127 char buffer[64];
128 char *key = NULL;
130 while (panel->capturing) {
131 XAllowEvents(dpy, AsyncKeyboard, CurrentTime);
132 WMNextEvent(dpy, &ev);
133 if (ev.type==KeyPress && ev.xkey.keycode!=0) {
134 ksym = XKeycodeToKeysym(dpy, ev.xkey.keycode, 0);
135 if (!IsModifierKey(ksym)) {
136 key=XKeysymToString(ksym);
137 panel->capturing = 0;
138 break;
141 WMHandleEvent(&ev);
144 if (!key)
145 return NULL;
147 buffer[0] = 0;
149 if (ev.xkey.state & ControlMask) {
150 strcat(buffer, "Control+");
152 if (ev.xkey.state & ShiftMask) {
153 strcat(buffer, "Shift+");
155 if (ev.xkey.state & Mod1Mask) {
156 strcat(buffer, "Mod1+");
158 if (ev.xkey.state & Mod2Mask) {
159 strcat(buffer, "Mod2+");
161 if (ev.xkey.state & Mod3Mask) {
162 strcat(buffer, "Mod3+");
164 if (ev.xkey.state & Mod4Mask) {
165 strcat(buffer, "Mod4+");
167 if (ev.xkey.state & Mod5Mask) {
168 strcat(buffer, "Mod5+");
170 strcat(buffer, key);
172 return wstrdup(buffer);
176 static void
177 captureClick(WMWidget *w, void *data)
179 _Panel *panel = (_Panel*)data;
180 Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->win));
181 char *shortcut;
183 if (!panel->capturing) {
184 panel->capturing = 1;
185 WMSetButtonText(w, _("Cancel"));
186 WMSetLabelText(panel->instructionsL, _("Press the desired shortcut key(s) or click Cancel to stop capturing."));
187 XGrabKeyboard(dpy, WMWidgetXID(panel->win), True, GrabModeAsync,
188 GrabModeAsync, CurrentTime);
189 shortcut = captureShortcut(dpy, panel);
190 if (shortcut) {
191 int row = WMGetListSelectedItemRow(panel->actLs);
193 WMSetTextFieldText(panel->shoT, shortcut);
194 if (row>=0) {
195 if (panel->shortcuts[row])
196 free(panel->shortcuts[row]);
197 panel->shortcuts[row] = shortcut;
199 WMRedisplayWidget(panel->actLs);
200 } else {
201 free(shortcut);
205 panel->capturing = 0;
206 WMSetButtonText(w, _("Capture"));
207 WMSetLabelText(panel->instructionsL, _("Click Capture to interactively define the shortcut key."));
208 XUngrabKeyboard(dpy, CurrentTime);
213 static void
214 clearShortcut(WMWidget *w, void *data)
216 _Panel *panel = (_Panel*)data;
217 int row = WMGetListSelectedItemRow(panel->actLs);
219 WMSetTextFieldText(panel->shoT, NULL);
221 if (row>=0) {
222 if (panel->shortcuts[row])
223 free(panel->shortcuts[row]);
224 panel->shortcuts[row]=NULL;
225 WMRedisplayWidget(panel->actLs);
231 static void
232 typedKeys(void *observerData, WMNotification *notification)
234 _Panel *panel = (_Panel*)observerData;
235 int row = WMGetListSelectedItemRow(panel->actLs);
237 if (row<0)
238 return;
240 if (panel->shortcuts[row])
241 free(panel->shortcuts[row]);
242 panel->shortcuts[row] = WMGetTextFieldText(panel->shoT);
243 if (strlen(panel->shortcuts[row])==0) {
244 free(panel->shortcuts[row]);
245 panel->shortcuts[row] = NULL;
247 WMRedisplayWidget(panel->actLs);
252 static void
253 listClick(WMWidget *w, void *data)
255 _Panel *panel = (_Panel*)data;
256 int row = WMGetListSelectedItemRow(w);
258 WMSetTextFieldText(panel->shoT, panel->shortcuts[row]);
262 static char*
263 trimstr(char *str)
265 char *p = str;
266 int i;
268 while (isspace(*p)) p++;
269 p = wstrdup(p);
270 i = strlen(p);
271 while (isspace(p[i]) && i>0) {
272 p[i]=0;
273 i--;
276 return p;
280 static void
281 showData(_Panel *panel)
283 char *str;
284 int i;
286 for (i=0; i<panel->actionCount; i++) {
288 str = GetStringForKey(keyOptions[i]);
289 if (panel->shortcuts[i])
290 free(panel->shortcuts[i]);
291 if (str)
292 panel->shortcuts[i] = trimstr(str);
293 else
294 panel->shortcuts[i] = NULL;
296 if (panel->shortcuts[i] &&
297 (strcasecmp(panel->shortcuts[i], "none")==0
298 || strlen(panel->shortcuts[i])==0)) {
299 free(panel->shortcuts[i]);
300 panel->shortcuts[i] = NULL;
303 WMRedisplayWidget(panel->actLs);
307 static void
308 paintItem(WMList *lPtr, int index, Drawable d, char *text, int state,
309 WMRect *rect)
311 int width, height, x, y;
312 _Panel *panel = (_Panel*)WMGetHangedData(lPtr);
313 WMScreen *scr = WMWidgetScreen(lPtr);
314 Display *dpy = WMScreenDisplay(scr);
316 width = rect->size.width;
317 height = rect->size.height;
318 x = rect->pos.x;
319 y = rect->pos.y;
321 if (state & WLDSSelected)
322 XFillRectangle(dpy, d, WMColorGC(panel->white), x, y, width,
323 height);
324 else
325 XClearArea(dpy, d, x, y, width, height, False);
327 if (panel->shortcuts[index]) {
328 WMPixmap *pix = WMGetSystemPixmap(scr, WSICheckMark);
329 WMSize size = WMGetPixmapSize(pix);
331 WMDrawPixmap(pix, d, x+(20-size.width)/2, (height-size.height)/2+y);
332 WMReleasePixmap(pix);
335 WMDrawString(scr, d, WMColorGC(panel->black), panel->font, x+20, y,
336 text, strlen(text));
340 static void
341 createPanel(Panel *p)
343 _Panel *panel = (_Panel*)p;
344 WMScreen *scr = WMWidgetScreen(panel->win);
345 WMColor *color;
346 WMFont *boldFont;
348 panel->capturing = 0;
350 panel->frame = WMCreateFrame(panel->win);
351 WMResizeWidget(panel->frame, FRAME_WIDTH, FRAME_HEIGHT);
352 WMMoveWidget(panel->frame, FRAME_LEFT, FRAME_TOP);
354 boldFont = WMBoldSystemFontOfSize(scr, 12);
356 /* **************** Actions **************** */
357 panel->actL = WMCreateLabel(panel->frame);
358 WMResizeWidget(panel->actL, 280, 20);
359 WMMoveWidget(panel->actL, 20, 10);
360 WMSetLabelFont(panel->actL, boldFont);
361 WMSetLabelText(panel->actL, _("Actions"));
362 WMSetLabelRelief(panel->actL, WRSunken);
363 WMSetLabelTextAlignment(panel->actL, WACenter);
364 color = WMDarkGrayColor(scr);
365 WMSetWidgetBackgroundColor(panel->actL, color);
366 WMReleaseColor(color);
367 color = WMWhiteColor(scr);
368 WMSetLabelTextColor(panel->actL, color);
369 WMReleaseColor(color);
371 panel->actLs = WMCreateList(panel->frame);
372 WMResizeWidget(panel->actLs, 280, 190);
373 WMMoveWidget(panel->actLs, 20, 32);
374 WMSetListUserDrawProc(panel->actLs, paintItem);
375 WMHangData(panel->actLs, panel);
377 WMAddListItem(panel->actLs, _("Open applications menu"));
378 WMAddListItem(panel->actLs, _("Open window list menu"));
379 WMAddListItem(panel->actLs, _("Open window commands menu"));
380 WMAddListItem(panel->actLs, _("Hide active application"));
381 WMAddListItem(panel->actLs, _("Miniaturize active window"));
382 WMAddListItem(panel->actLs, _("Close active window"));
383 WMAddListItem(panel->actLs, _("Maximize active window"));
384 WMAddListItem(panel->actLs, _("Maximize active window vertically"));
385 WMAddListItem(panel->actLs, _("Raise active window"));
386 WMAddListItem(panel->actLs, _("Lower active window"));
387 WMAddListItem(panel->actLs, _("Raise/Lower window under mouse pointer"));
388 WMAddListItem(panel->actLs, _("Shade active window"));
389 WMAddListItem(panel->actLs, _("Move/Resize active window"));
390 WMAddListItem(panel->actLs, _("Select active window"));
391 WMAddListItem(panel->actLs, _("Focus next window"));
392 WMAddListItem(panel->actLs, _("Focus previous window"));
393 WMAddListItem(panel->actLs, _("Switch to next workspace"));
394 WMAddListItem(panel->actLs, _("Switch to previous workspace"));
395 WMAddListItem(panel->actLs, _("Switch to next ten workspaces"));
396 WMAddListItem(panel->actLs, _("Switch to previous ten workspaces"));
397 WMAddListItem(panel->actLs, _("Switch to workspace 1"));
398 WMAddListItem(panel->actLs, _("Switch to workspace 2"));
399 WMAddListItem(panel->actLs, _("Switch to workspace 3"));
400 WMAddListItem(panel->actLs, _("Switch to workspace 4"));
401 WMAddListItem(panel->actLs, _("Switch to workspace 5"));
402 WMAddListItem(panel->actLs, _("Switch to workspace 6"));
403 WMAddListItem(panel->actLs, _("Switch to workspace 7"));
404 WMAddListItem(panel->actLs, _("Switch to workspace 8"));
405 WMAddListItem(panel->actLs, _("Switch to workspace 9"));
406 WMAddListItem(panel->actLs, _("Switch to workspace 10"));
407 WMAddListItem(panel->actLs, _("Shortcut for window 1"));
408 WMAddListItem(panel->actLs, _("Shortcut for window 2"));
409 WMAddListItem(panel->actLs, _("Shortcut for window 3"));
410 WMAddListItem(panel->actLs, _("Shortcut for window 4"));
411 WMAddListItem(panel->actLs, _("Raise Clip"));
412 WMAddListItem(panel->actLs, _("Lower Clip"));
413 WMAddListItem(panel->actLs, _("Raise/Lower Clip"));
414 #ifdef XKB_MODELOCK
415 WMAddListItem(panel->actLs, _("Toggle keyboard language"));
416 #endif /* XKB_MODELOCK */
418 WMSetListAction(panel->actLs, listClick, panel);
420 panel->actionCount = WMGetListNumberOfRows(panel->actLs);
421 panel->shortcuts = wmalloc(sizeof(char*)*panel->actionCount);
422 memset(panel->shortcuts, 0, sizeof(char*)*panel->actionCount);
424 /***************** Shortcut ****************/
426 panel->shoF = WMCreateFrame(panel->frame);
427 WMResizeWidget(panel->shoF, 190, 210);
428 WMMoveWidget(panel->shoF, 315, 10);
429 WMSetFrameTitle(panel->shoF, _("Shortcut"));
431 panel->shoT = WMCreateTextField(panel->shoF);
432 WMResizeWidget(panel->shoT, 160, 20);
433 WMMoveWidget(panel->shoT, 15, 65);
434 WMAddNotificationObserver(typedKeys, panel,
435 WMTextDidChangeNotification, panel->shoT);
437 panel->cleB = WMCreateCommandButton(panel->shoF);
438 WMResizeWidget(panel->cleB, 75, 24);
439 WMMoveWidget(panel->cleB, 15, 95);
440 WMSetButtonText(panel->cleB, _("Clear"));
441 WMSetButtonAction(panel->cleB, clearShortcut, panel);
443 panel->defB = WMCreateCommandButton(panel->shoF);
444 WMResizeWidget(panel->defB, 75, 24);
445 WMMoveWidget(panel->defB, 100, 95);
446 WMSetButtonText(panel->defB, _("Capture"));
447 WMSetButtonAction(panel->defB, captureClick, panel);
449 panel->instructionsL = WMCreateLabel(panel->shoF);
450 WMResizeWidget(panel->instructionsL, 160, 55);
451 WMMoveWidget(panel->instructionsL, 15, 140);
452 WMSetLabelTextAlignment(panel->instructionsL, WACenter);
453 WMSetLabelText(panel->instructionsL, _("Click Capture to interactively define the shortcut key."));
455 WMMapSubwidgets(panel->shoF);
457 WMReleaseFont(boldFont);
459 WMRealizeWidget(panel->frame);
460 WMMapSubwidgets(panel->frame);
463 showData(panel);
467 static void
468 storeData(_Panel *panel)
470 int i;
471 char *str;
473 for (i=0; i<panel->actionCount; i++) {
474 str = NULL;
475 if (panel->shortcuts[i]) {
476 str = trimstr(panel->shortcuts[i]);
477 if (strlen(str)==0) {
478 free(str);
479 str = NULL;
482 if (str) {
483 SetStringForKey(str, keyOptions[i]);
484 free(str);
485 } else {
486 SetStringForKey("None", keyOptions[i]);
493 Panel*
494 InitKeyboardShortcuts(WMScreen *scr, WMWindow *win)
496 _Panel *panel;
498 panel = wmalloc(sizeof(_Panel));
499 memset(panel, 0, sizeof(_Panel));
501 panel->sectionName = _("Keyboard Shortcut Preferences");
503 panel->description = _("Change the keyboard shortcuts for actions such\n"
504 "as changing workspaces and opening menus.");
506 panel->win = win;
508 panel->callbacks.createWidgets = createPanel;
509 panel->callbacks.updateDomain = storeData;
511 panel->white = WMWhiteColor(scr);
512 panel->black = WMBlackColor(scr);
513 panel->font = WMSystemFontOfSize(scr, 12);
515 AddSection(panel, ICON_FILE);
517 return panel;