Code update for Window Maker version 0.50.0
[wmaker-crm.git] / WPrefs.app / KeyboardShortcuts.c
blob78b90fe864803a589215670aa95965fe5f851425
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 WMColor *white;
50 WMColor *black;
51 WMFont *font;
53 /**/
54 char capturing;
55 char **shortcuts;
56 int actionCount;
57 } _Panel;
61 #define ICON_FILE "keyshortcuts"
64 /* must be in the same order as the corresponding items in actions list */
65 static char *keyOptions[] = {
66 "RootMenuKey",
67 "WindowListKey",
68 "WindowMenuKey",
69 "HideKey",
70 "MiniaturizeKey",
71 "CloseKey",
72 "MaximizeKey",
73 "VMaximizeKey",
74 "RaiseKey",
75 "LowerKey",
76 "RaiseLowerKey",
77 "ShadeKey",
78 "MoveResizeKey",
79 "SelectKey",
80 "FocusNextKey",
81 "FocusPrevKey",
82 "NextWorkspaceKey",
83 "PrevWorkspaceKey",
84 "NextWorkspaceLayerKey",
85 "PrevWorkspaceLayerKey",
86 "Workspace1Key",
87 "Workspace2Key",
88 "Workspace3Key",
89 "Workspace4Key",
90 "Workspace5Key",
91 "Workspace6Key",
92 "Workspace7Key",
93 "Workspace8Key",
94 "Workspace9Key",
95 "Workspace10Key",
96 "WindowShortcut1Key",
97 "WindowShortcut2Key",
98 "WindowShortcut3Key",
99 "WindowShortcut4Key",
100 #ifdef EXTEND_WINDOWSHORTCUT
101 "WindowShortcut5Key",
102 "WindowShortcut6Key",
103 "WindowShortcut7Key",
104 "WindowShortcut8Key",
105 "WindowShortcut9Key",
106 "WindowShortcut10Key",
107 #endif
108 "ClipRaiseKey",
109 "ClipLowerKey",
110 #ifndef XKB_MODELOCK
111 "ClipRaiseLowerKey"
112 #else
113 "ClipRaiseLowerKey",
114 "ToggleKbdModeKey"
115 #endif /* XKB_MODELOCK */
120 static char*
121 captureShortcut(Display *dpy, _Panel *panel)
123 XEvent ev;
124 KeySym ksym;
125 char buffer[64];
126 char *key = NULL;
128 while (panel->capturing) {
129 XAllowEvents(dpy, AsyncKeyboard, CurrentTime);
130 WMNextEvent(dpy, &ev);
131 if (ev.type==KeyPress && ev.xkey.keycode!=0) {
132 ksym = XKeycodeToKeysym(dpy, ev.xkey.keycode, 0);
133 if (!IsModifierKey(ksym)) {
134 key=XKeysymToString(ksym);
135 panel->capturing = 0;
136 break;
139 WMHandleEvent(&ev);
142 if (!key)
143 return NULL;
145 buffer[0] = 0;
147 if (ev.xkey.state & ControlMask) {
148 strcat(buffer, "Control+");
150 if (ev.xkey.state & ShiftMask) {
151 strcat(buffer, "Shift+");
153 if (ev.xkey.state & Mod1Mask) {
154 strcat(buffer, "Mod1+");
156 if (ev.xkey.state & Mod2Mask) {
157 strcat(buffer, "Mod2+");
159 if (ev.xkey.state & Mod3Mask) {
160 strcat(buffer, "Mod3+");
162 if (ev.xkey.state & Mod4Mask) {
163 strcat(buffer, "Mod4+");
165 if (ev.xkey.state & Mod5Mask) {
166 strcat(buffer, "Mod5+");
168 strcat(buffer, key);
170 return wstrdup(buffer);
174 static void
175 captureClick(WMWidget *w, void *data)
177 _Panel *panel = (_Panel*)data;
178 Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->win));
179 char *shortcut;
181 if (!panel->capturing) {
182 panel->capturing = 1;
183 WMSetButtonText(w, _("Cancel"));
184 WMSetLabelText(panel->instructionsL, _("Press the desired shortcut key(s) or click Cancel to stop capturing."));
185 XGrabKeyboard(dpy, WMWidgetXID(panel->win), True, GrabModeAsync,
186 GrabModeAsync, CurrentTime);
187 shortcut = captureShortcut(dpy, panel);
188 if (shortcut) {
189 int row = WMGetListSelectedItemRow(panel->actLs);
191 WMSetTextFieldText(panel->shoT, shortcut);
192 if (row>=0) {
193 if (panel->shortcuts[row])
194 free(panel->shortcuts[row]);
195 panel->shortcuts[row] = shortcut;
197 WMRedisplayWidget(panel->actLs);
198 } else {
199 free(shortcut);
203 panel->capturing = 0;
204 WMSetButtonText(w, _("Capture"));
205 WMSetLabelText(panel->instructionsL, _("Click Capture to interactively define the shortcut key."));
206 XUngrabKeyboard(dpy, CurrentTime);
211 static void
212 clearShortcut(WMWidget *w, void *data)
214 _Panel *panel = (_Panel*)data;
215 int row = WMGetListSelectedItemRow(panel->actLs);
217 WMSetTextFieldText(panel->shoT, NULL);
219 if (row>=0) {
220 if (panel->shortcuts[row])
221 free(panel->shortcuts[row]);
222 panel->shortcuts[row]=NULL;
223 WMRedisplayWidget(panel->actLs);
229 static void
230 typedKeys(void *observerData, WMNotification *notification)
232 _Panel *panel = (_Panel*)observerData;
233 int row = WMGetListSelectedItemRow(panel->actLs);
235 if (row<0)
236 return;
238 if (panel->shortcuts[row])
239 free(panel->shortcuts[row]);
240 panel->shortcuts[row] = WMGetTextFieldText(panel->shoT);
241 if (strlen(panel->shortcuts[row])==0) {
242 free(panel->shortcuts[row]);
243 panel->shortcuts[row] = NULL;
245 WMRedisplayWidget(panel->actLs);
250 static void
251 listClick(WMWidget *w, void *data)
253 _Panel *panel = (_Panel*)data;
254 int row = WMGetListSelectedItemRow(w);
256 WMSetTextFieldText(panel->shoT, panel->shortcuts[row]);
260 static char*
261 trimstr(char *str)
263 char *p = str;
264 int i;
266 while (isspace(*p)) p++;
267 p = wstrdup(p);
268 i = strlen(p);
269 while (isspace(p[i]) && i>0) {
270 p[i]=0;
271 i--;
274 return p;
278 static void
279 showData(_Panel *panel)
281 char *str;
282 int i;
284 for (i=0; i<panel->actionCount; i++) {
286 str = GetStringForKey(keyOptions[i]);
287 if (panel->shortcuts[i])
288 free(panel->shortcuts[i]);
289 if (str)
290 panel->shortcuts[i] = trimstr(str);
291 else
292 panel->shortcuts[i] = NULL;
294 if (panel->shortcuts[i] &&
295 (strcasecmp(panel->shortcuts[i], "none")==0
296 || strlen(panel->shortcuts[i])==0)) {
297 free(panel->shortcuts[i]);
298 panel->shortcuts[i] = NULL;
301 WMRedisplayWidget(panel->actLs);
305 static void
306 paintItem(WMList *lPtr, int index, Drawable d, char *text, int state,
307 WMRect *rect)
309 int width, height, x, y;
310 _Panel *panel = (_Panel*)WMGetHangedData(lPtr);
311 WMScreen *scr = WMWidgetScreen(lPtr);
312 Display *dpy = WMScreenDisplay(scr);
314 width = rect->size.width;
315 height = rect->size.height;
316 x = rect->pos.x;
317 y = rect->pos.y;
319 if (state & WLDSSelected)
320 XFillRectangle(dpy, d, WMColorGC(panel->white), x, y, width,
321 height);
322 else
323 XClearArea(dpy, d, x, y, width, height, False);
325 if (panel->shortcuts[index]) {
326 WMPixmap *pix = WMGetSystemPixmap(scr, WSICheckMark);
327 WMSize size = WMGetPixmapSize(pix);
329 WMDrawPixmap(pix, d, x+(20-size.width)/2, (height-size.height)/2+y);
330 WMReleasePixmap(pix);
333 WMDrawString(scr, d, WMColorGC(panel->black), panel->font, x+20, y,
334 text, strlen(text));
338 static void
339 createPanel(Panel *p)
341 _Panel *panel = (_Panel*)p;
342 WMScreen *scr = WMWidgetScreen(panel->win);
343 WMColor *color;
344 WMFont *boldFont;
346 panel->capturing = 0;
348 panel->frame = WMCreateFrame(panel->win);
349 WMResizeWidget(panel->frame, FRAME_WIDTH, FRAME_HEIGHT);
350 WMMoveWidget(panel->frame, FRAME_LEFT, FRAME_TOP);
352 boldFont = WMBoldSystemFontOfSize(scr, 12);
354 /* **************** Actions **************** */
355 panel->actL = WMCreateLabel(panel->frame);
356 WMResizeWidget(panel->actL, 280, 20);
357 WMMoveWidget(panel->actL, 20, 10);
358 WMSetLabelFont(panel->actL, boldFont);
359 WMSetLabelText(panel->actL, _("Actions"));
360 WMSetLabelRelief(panel->actL, WRSunken);
361 WMSetLabelTextAlignment(panel->actL, WACenter);
362 color = WMDarkGrayColor(scr);
363 WMSetWidgetBackgroundColor(panel->actL, color);
364 WMReleaseColor(color);
365 color = WMWhiteColor(scr);
366 WMSetLabelTextColor(panel->actL, color);
367 WMReleaseColor(color);
369 panel->actLs = WMCreateList(panel->frame);
370 WMResizeWidget(panel->actLs, 280, 190);
371 WMMoveWidget(panel->actLs, 20, 32);
372 WMSetListUserDrawProc(panel->actLs, paintItem);
373 WMHangData(panel->actLs, panel);
375 WMAddListItem(panel->actLs, _("Open applications menu"));
376 WMAddListItem(panel->actLs, _("Open window list menu"));
377 WMAddListItem(panel->actLs, _("Open window commands menu"));
378 WMAddListItem(panel->actLs, _("Hide active application"));
379 WMAddListItem(panel->actLs, _("Miniaturize active window"));
380 WMAddListItem(panel->actLs, _("Close active window"));
381 WMAddListItem(panel->actLs, _("Maximize active window"));
382 WMAddListItem(panel->actLs, _("Maximize active window vertically"));
383 WMAddListItem(panel->actLs, _("Raise active window"));
384 WMAddListItem(panel->actLs, _("Lower active window"));
385 WMAddListItem(panel->actLs, _("Raise/Lower window under mouse pointer"));
386 WMAddListItem(panel->actLs, _("Shade active window"));
387 WMAddListItem(panel->actLs, _("Select active window"));
388 WMAddListItem(panel->actLs, _("Move/Resize active window"));
389 WMAddListItem(panel->actLs, _("Focus next window"));
390 WMAddListItem(panel->actLs, _("Focus previous window"));
391 WMAddListItem(panel->actLs, _("Switch to next workspace"));
392 WMAddListItem(panel->actLs, _("Switch to previous workspace"));
393 WMAddListItem(panel->actLs, _("Switch to next ten workspaces"));
394 WMAddListItem(panel->actLs, _("Switch to previous ten workspaces"));
395 WMAddListItem(panel->actLs, _("Switch to workspace 1"));
396 WMAddListItem(panel->actLs, _("Switch to workspace 2"));
397 WMAddListItem(panel->actLs, _("Switch to workspace 3"));
398 WMAddListItem(panel->actLs, _("Switch to workspace 4"));
399 WMAddListItem(panel->actLs, _("Switch to workspace 5"));
400 WMAddListItem(panel->actLs, _("Switch to workspace 6"));
401 WMAddListItem(panel->actLs, _("Switch to workspace 7"));
402 WMAddListItem(panel->actLs, _("Switch to workspace 8"));
403 WMAddListItem(panel->actLs, _("Switch to workspace 9"));
404 WMAddListItem(panel->actLs, _("Switch to workspace 10"));
405 WMAddListItem(panel->actLs, _("Shortcut for window 1"));
406 WMAddListItem(panel->actLs, _("Shortcut for window 2"));
407 WMAddListItem(panel->actLs, _("Shortcut for window 3"));
408 WMAddListItem(panel->actLs, _("Shortcut for window 4"));
409 WMAddListItem(panel->actLs, _("Raise Clip"));
410 WMAddListItem(panel->actLs, _("Lower Clip"));
411 WMAddListItem(panel->actLs, _("Raise/Lower Clip"));
412 #ifdef XKB_MODELOCK
413 WMAddListItem(panel->actLs, _("Toggle keyboard language"));
414 #endif /* XKB_MODELOCK */
416 WMSetListAction(panel->actLs, listClick, panel);
418 panel->actionCount = WMGetListNumberOfRows(panel->actLs);
419 panel->shortcuts = wmalloc(sizeof(char*)*panel->actionCount);
420 memset(panel->shortcuts, 0, sizeof(char*)*panel->actionCount);
422 /***************** Shortcut ****************/
424 panel->shoF = WMCreateFrame(panel->frame);
425 WMResizeWidget(panel->shoF, 190, 210);
426 WMMoveWidget(panel->shoF, 315, 10);
427 WMSetFrameTitle(panel->shoF, _("Shortcut"));
429 panel->shoT = WMCreateTextField(panel->shoF);
430 WMResizeWidget(panel->shoT, 160, 20);
431 WMMoveWidget(panel->shoT, 15, 65);
432 WMAddNotificationObserver(typedKeys, panel,
433 WMTextDidChangeNotification, panel->shoT);
435 panel->cleB = WMCreateCommandButton(panel->shoF);
436 WMResizeWidget(panel->cleB, 75, 24);
437 WMMoveWidget(panel->cleB, 15, 95);
438 WMSetButtonText(panel->cleB, _("Clear"));
439 WMSetButtonAction(panel->cleB, clearShortcut, panel);
441 panel->defB = WMCreateCommandButton(panel->shoF);
442 WMResizeWidget(panel->defB, 75, 24);
443 WMMoveWidget(panel->defB, 100, 95);
444 WMSetButtonText(panel->defB, _("Capture"));
445 WMSetButtonAction(panel->defB, captureClick, panel);
447 panel->instructionsL = WMCreateLabel(panel->shoF);
448 WMResizeWidget(panel->instructionsL, 160, 55);
449 WMMoveWidget(panel->instructionsL, 15, 140);
450 WMSetLabelTextAlignment(panel->instructionsL, WACenter);
451 WMSetLabelText(panel->instructionsL, _("Click Capture to interactively define the shortcut key."));
453 WMMapSubwidgets(panel->shoF);
455 WMReleaseFont(boldFont);
457 WMRealizeWidget(panel->frame);
458 WMMapSubwidgets(panel->frame);
461 showData(panel);
465 static void
466 storeData(_Panel *panel)
468 int i;
469 char *str;
471 for (i=0; i<panel->actionCount; i++) {
472 str = NULL;
473 if (panel->shortcuts[i]) {
474 str = trimstr(panel->shortcuts[i]);
475 if (strlen(str)==0) {
476 free(str);
477 str = NULL;
480 if (str) {
481 SetStringForKey(str, keyOptions[i]);
482 free(str);
483 } else {
484 SetStringForKey("None", keyOptions[i]);
491 Panel*
492 InitKeyboardShortcuts(WMScreen *scr, WMWindow *win)
494 _Panel *panel;
496 panel = wmalloc(sizeof(_Panel));
497 memset(panel, 0, sizeof(_Panel));
499 panel->sectionName = _("Keyboard Shortcut Preferences");
501 panel->win = win;
503 panel->callbacks.createWidgets = createPanel;
504 panel->callbacks.updateDomain = storeData;
506 panel->white = WMWhiteColor(scr);
507 panel->black = WMBlackColor(scr);
508 panel->font = WMSystemFontOfSize(scr, 12);
510 AddSection(panel, ICON_FILE);
512 return panel;