Remove unused StartLogShell function.
[wmaker-crm.git] / WPrefs.app / KeyboardShortcuts.c
blob38d9a4dc61cd8b0682572e32046c1e67a81a9ee7
1 /* KeyboardShortcuts.c- keyboard shortcut bindings
3 * WPrefs - Window Maker Preferences Program
5 * Copyright (c) 1998-2003 Alfredo K. Kojima
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 "config.h" /* for HAVE_XCONVERTCASE */
27 #include "WPrefs.h"
28 #include <ctype.h>
30 #include <X11/keysym.h>
33 typedef struct _Panel {
34 WMBox *box;
36 char *sectionName;
38 char *description;
40 CallbackRec callbacks;
42 WMWidget *parent;
44 WMLabel *actL;
45 WMList *actLs;
47 WMFrame *shoF;
48 WMTextField *shoT;
49 WMButton *cleB;
50 WMButton *defB;
52 WMLabel *instructionsL;
54 WMColor *white;
55 WMColor *black;
56 WMColor *gray;
57 WMFont *font;
59 /**/
60 char capturing;
61 char **shortcuts;
62 int actionCount;
63 } _Panel;
67 #define ICON_FILE "keyshortcuts"
70 /* must be in the same order as the corresponding items in actions list */
71 static char *keyOptions[] = {
72 "RootMenuKey",
73 "WindowListKey",
74 "WindowMenuKey",
75 "HideKey",
76 "HideOthersKey",
77 "MiniaturizeKey",
78 "CloseKey",
79 "MaximizeKey",
80 "VMaximizeKey",
81 "HMaximizeKey",
82 "RaiseKey",
83 "LowerKey",
84 "RaiseLowerKey",
85 "ShadeKey",
86 "MoveResizeKey",
87 "SelectKey",
88 "FocusNextKey",
89 "FocusPrevKey",
90 "NextWorkspaceKey",
91 "PrevWorkspaceKey",
92 "NextWorkspaceLayerKey",
93 "PrevWorkspaceLayerKey",
94 "Workspace1Key",
95 "Workspace2Key",
96 "Workspace3Key",
97 "Workspace4Key",
98 "Workspace5Key",
99 "Workspace6Key",
100 "Workspace7Key",
101 "Workspace8Key",
102 "Workspace9Key",
103 "Workspace10Key",
104 "WindowShortcut1Key",
105 "WindowShortcut2Key",
106 "WindowShortcut3Key",
107 "WindowShortcut4Key",
108 "WindowShortcut5Key",
109 "WindowShortcut6Key",
110 "WindowShortcut7Key",
111 "WindowShortcut8Key",
112 "WindowShortcut9Key",
113 "WindowShortcut10Key",
114 "ScreenSwitchKey",
115 #ifdef VIRTUAL_DESKTOP
116 "VirtualEdgeLeftKey",
117 "VirtualEdgeRightKey",
118 "VirtualEdgeUpKey",
119 "VirtualEdgeDownKey",
120 #endif
121 "ClipRaiseKey",
122 "ClipLowerKey",
123 #ifndef XKB_MODELOCK
124 "ClipRaiseLowerKey"
125 #else
126 "ClipRaiseLowerKey",
127 "ToggleKbdModeKey"
128 #endif /* XKB_MODELOCK */
133 #ifndef HAVE_XCONVERTCASE
134 /* from Xlib */
136 static void
137 XConvertCase(register KeySym sym, KeySym *lower, KeySym *upper)
139 *lower = sym;
140 *upper = sym;
141 switch(sym >> 8) {
142 case 0: /* Latin 1 */
143 if ((sym >= XK_A) && (sym <= XK_Z))
144 *lower += (XK_a - XK_A);
145 else if ((sym >= XK_a) && (sym <= XK_z))
146 *upper -= (XK_a - XK_A);
147 else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
148 *lower += (XK_agrave - XK_Agrave);
149 else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
150 *upper -= (XK_agrave - XK_Agrave);
151 else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
152 *lower += (XK_oslash - XK_Ooblique);
153 else if ((sym >= XK_oslash) && (sym <= XK_thorn))
154 *upper -= (XK_oslash - XK_Ooblique);
155 break;
156 case 1: /* Latin 2 */
157 /* Assume the KeySym is a legal value (ignore discontinuities) */
158 if (sym == XK_Aogonek)
159 *lower = XK_aogonek;
160 else if (sym >= XK_Lstroke && sym <= XK_Sacute)
161 *lower += (XK_lstroke - XK_Lstroke);
162 else if (sym >= XK_Scaron && sym <= XK_Zacute)
163 *lower += (XK_scaron - XK_Scaron);
164 else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
165 *lower += (XK_zcaron - XK_Zcaron);
166 else if (sym == XK_aogonek)
167 *upper = XK_Aogonek;
168 else if (sym >= XK_lstroke && sym <= XK_sacute)
169 *upper -= (XK_lstroke - XK_Lstroke);
170 else if (sym >= XK_scaron && sym <= XK_zacute)
171 *upper -= (XK_scaron - XK_Scaron);
172 else if (sym >= XK_zcaron && sym <= XK_zabovedot)
173 *upper -= (XK_zcaron - XK_Zcaron);
174 else if (sym >= XK_Racute && sym <= XK_Tcedilla)
175 *lower += (XK_racute - XK_Racute);
176 else if (sym >= XK_racute && sym <= XK_tcedilla)
177 *upper -= (XK_racute - XK_Racute);
178 break;
179 case 2: /* Latin 3 */
180 /* Assume the KeySym is a legal value (ignore discontinuities) */
181 if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
182 *lower += (XK_hstroke - XK_Hstroke);
183 else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
184 *lower += (XK_gbreve - XK_Gbreve);
185 else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
186 *upper -= (XK_hstroke - XK_Hstroke);
187 else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
188 *upper -= (XK_gbreve - XK_Gbreve);
189 else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
190 *lower += (XK_cabovedot - XK_Cabovedot);
191 else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
192 *upper -= (XK_cabovedot - XK_Cabovedot);
193 break;
194 case 3: /* Latin 4 */
195 /* Assume the KeySym is a legal value (ignore discontinuities) */
196 if (sym >= XK_Rcedilla && sym <= XK_Tslash)
197 *lower += (XK_rcedilla - XK_Rcedilla);
198 else if (sym >= XK_rcedilla && sym <= XK_tslash)
199 *upper -= (XK_rcedilla - XK_Rcedilla);
200 else if (sym == XK_ENG)
201 *lower = XK_eng;
202 else if (sym == XK_eng)
203 *upper = XK_ENG;
204 else if (sym >= XK_Amacron && sym <= XK_Umacron)
205 *lower += (XK_amacron - XK_Amacron);
206 else if (sym >= XK_amacron && sym <= XK_umacron)
207 *upper -= (XK_amacron - XK_Amacron);
208 break;
209 case 6: /* Cyrillic */
210 /* Assume the KeySym is a legal value (ignore discontinuities) */
211 if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
212 *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
213 else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
214 *upper += (XK_Serbian_DJE - XK_Serbian_dje);
215 else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
216 *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
217 else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
218 *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
219 break;
220 case 7: /* Greek */
221 /* Assume the KeySym is a legal value (ignore discontinuities) */
222 if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
223 *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
224 else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
225 sym != XK_Greek_iotaaccentdieresis &&
226 sym != XK_Greek_upsilonaccentdieresis)
227 *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
228 else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
229 *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
230 else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
231 sym != XK_Greek_finalsmallsigma)
232 *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
233 break;
234 case 0x14: /* Armenian */
235 if (sym >= XK_Armenian_AYB && sym <= XK_Armenian_fe) {
236 *lower = sym | 1;
237 *upper = sym & ~1;
239 break;
242 #endif
245 static char*
246 captureShortcut(Display *dpy, _Panel *panel)
248 XEvent ev;
249 KeySym ksym, lksym, uksym;
250 char buffer[64];
251 char *key = NULL;
253 while (panel->capturing) {
254 XAllowEvents(dpy, AsyncKeyboard, CurrentTime);
255 WMNextEvent(dpy, &ev);
256 if (ev.type==KeyPress && ev.xkey.keycode!=0) {
257 ksym = XKeycodeToKeysym(dpy, ev.xkey.keycode, 0);
258 if (!IsModifierKey(ksym)) {
259 XConvertCase(ksym, &lksym, &uksym);
260 key=XKeysymToString(uksym);
262 panel->capturing = 0;
263 break;
266 WMHandleEvent(&ev);
269 if (!key)
270 return NULL;
272 buffer[0] = 0;
274 if (ev.xkey.state & ControlMask) {
275 strcat(buffer, "Control+");
277 if (ev.xkey.state & ShiftMask) {
278 strcat(buffer, "Shift+");
280 if (ev.xkey.state & Mod1Mask) {
281 strcat(buffer, "Mod1+");
283 if (ev.xkey.state & Mod2Mask) {
284 strcat(buffer, "Mod2+");
286 if (ev.xkey.state & Mod3Mask) {
287 strcat(buffer, "Mod3+");
289 if (ev.xkey.state & Mod4Mask) {
290 strcat(buffer, "Mod4+");
292 if (ev.xkey.state & Mod5Mask) {
293 strcat(buffer, "Mod5+");
295 strcat(buffer, key);
297 return wstrdup(buffer);
301 static void
302 captureClick(WMWidget *w, void *data)
304 _Panel *panel = (_Panel*)data;
305 Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->parent));
306 char *shortcut;
308 if (!panel->capturing) {
309 panel->capturing = 1;
310 WMSetButtonText(w, _("Cancel"));
311 WMSetLabelText(panel->instructionsL, _("Press the desired shortcut key(s) or click Cancel to stop capturing."));
312 XGrabKeyboard(dpy, WMWidgetXID(panel->parent), True, GrabModeAsync,
313 GrabModeAsync, CurrentTime);
314 shortcut = captureShortcut(dpy, panel);
315 if (shortcut) {
316 int row = WMGetListSelectedItemRow(panel->actLs);
318 WMSetTextFieldText(panel->shoT, shortcut);
319 if (row>=0) {
320 if (panel->shortcuts[row])
321 wfree(panel->shortcuts[row]);
322 panel->shortcuts[row] = shortcut;
324 WMRedisplayWidget(panel->actLs);
325 } else {
326 wfree(shortcut);
330 panel->capturing = 0;
331 WMSetButtonText(w, _("Capture"));
332 WMSetLabelText(panel->instructionsL, _("Click on Capture to interactively define the shortcut key."));
333 XUngrabKeyboard(dpy, CurrentTime);
338 static void
339 clearShortcut(WMWidget *w, void *data)
341 _Panel *panel = (_Panel*)data;
342 int row = WMGetListSelectedItemRow(panel->actLs);
344 WMSetTextFieldText(panel->shoT, NULL);
346 if (row>=0) {
347 if (panel->shortcuts[row])
348 wfree(panel->shortcuts[row]);
349 panel->shortcuts[row]=NULL;
350 WMRedisplayWidget(panel->actLs);
356 static void
357 typedKeys(void *observerData, WMNotification *notification)
359 _Panel *panel = (_Panel*)observerData;
360 int row = WMGetListSelectedItemRow(panel->actLs);
362 if (row<0)
363 return;
365 if (panel->shortcuts[row])
366 wfree(panel->shortcuts[row]);
367 panel->shortcuts[row] = WMGetTextFieldText(panel->shoT);
368 if (strlen(panel->shortcuts[row])==0) {
369 wfree(panel->shortcuts[row]);
370 panel->shortcuts[row] = NULL;
372 WMRedisplayWidget(panel->actLs);
377 static void
378 listClick(WMWidget *w, void *data)
380 _Panel *panel = (_Panel*)data;
381 int row = WMGetListSelectedItemRow(w);
383 WMSetTextFieldText(panel->shoT, panel->shortcuts[row]);
387 static char*
388 trimstr(char *str)
390 char *p = str;
391 int i;
393 while (isspace(*p)) p++;
394 p = wstrdup(p);
395 i = strlen(p);
396 while (isspace(p[i]) && i>0) {
397 p[i]=0;
398 i--;
401 return p;
405 static void
406 showData(_Panel *panel)
408 char *str;
409 int i;
411 for (i=0; i<panel->actionCount; i++) {
413 str = GetStringForKey(keyOptions[i]);
414 if (panel->shortcuts[i])
415 wfree(panel->shortcuts[i]);
416 if (str)
417 panel->shortcuts[i] = trimstr(str);
418 else
419 panel->shortcuts[i] = NULL;
421 if (panel->shortcuts[i] &&
422 (strcasecmp(panel->shortcuts[i], "none")==0
423 || strlen(panel->shortcuts[i])==0)) {
424 wfree(panel->shortcuts[i]);
425 panel->shortcuts[i] = NULL;
428 WMRedisplayWidget(panel->actLs);
432 static void
433 paintItem(WMList *lPtr, int index, Drawable d, char *text, int state,
434 WMRect *rect)
436 int width, height, x, y;
437 _Panel *panel = (_Panel*)WMGetHangedData(lPtr);
438 WMScreen *scr = WMWidgetScreen(lPtr);
439 Display *dpy = WMScreenDisplay(scr);
440 WMColor *backColor = (state & WLDSSelected) ? panel->white : panel->gray;
442 width = rect->size.width;
443 height = rect->size.height;
444 x = rect->pos.x;
445 y = rect->pos.y;
447 XFillRectangle(dpy, d, WMColorGC(backColor), x, y, width, height);
449 if (panel->shortcuts[index]) {
450 WMPixmap *pix = WMGetSystemPixmap(scr, WSICheckMark);
451 WMSize size = WMGetPixmapSize(pix);
453 WMDrawPixmap(pix, d, x+(20-size.width)/2, (height-size.height)/2+y);
454 WMReleasePixmap(pix);
457 WMDrawString(scr, d, panel->black, panel->font, x+20, y, text, strlen(text));
461 static void
462 createPanel(Panel *p)
464 _Panel *panel = (_Panel*)p;
465 WMScreen *scr = WMWidgetScreen(panel->parent);
466 WMColor *color;
467 WMFont *boldFont;
469 panel->capturing = 0;
471 panel->white = WMWhiteColor(scr);
472 panel->black = WMBlackColor(scr);
473 panel->gray = WMGrayColor(scr);
474 panel->font = WMSystemFontOfSize(scr, 12);
476 panel->box = WMCreateBox(panel->parent);
477 WMSetViewExpandsToParent(WMWidgetView(panel->box), 2, 2, 2, 2);
479 boldFont = WMBoldSystemFontOfSize(scr, 12);
481 /* **************** Actions **************** */
482 panel->actL = WMCreateLabel(panel->box);
483 WMResizeWidget(panel->actL, 280, 20);
484 WMMoveWidget(panel->actL, 20, 10);
485 WMSetLabelFont(panel->actL, boldFont);
486 WMSetLabelText(panel->actL, _("Actions"));
487 WMSetLabelRelief(panel->actL, WRSunken);
488 WMSetLabelTextAlignment(panel->actL, WACenter);
489 color = WMDarkGrayColor(scr);
490 WMSetWidgetBackgroundColor(panel->actL, color);
491 WMReleaseColor(color);
492 WMSetLabelTextColor(panel->actL, panel->white);
494 panel->actLs = WMCreateList(panel->box);
495 WMResizeWidget(panel->actLs, 280, 190);
496 WMMoveWidget(panel->actLs, 20, 32);
497 WMSetListUserDrawProc(panel->actLs, paintItem);
498 WMHangData(panel->actLs, panel);
500 WMAddListItem(panel->actLs, _("Open applications menu"));
501 WMAddListItem(panel->actLs, _("Open window list menu"));
502 WMAddListItem(panel->actLs, _("Open window commands menu"));
503 WMAddListItem(panel->actLs, _("Hide active application"));
504 WMAddListItem(panel->actLs, _("Hide other applications"));
505 WMAddListItem(panel->actLs, _("Miniaturize active window"));
506 WMAddListItem(panel->actLs, _("Close active window"));
507 WMAddListItem(panel->actLs, _("Maximize active window"));
508 WMAddListItem(panel->actLs, _("Maximize active window vertically"));
509 WMAddListItem(panel->actLs, _("Maximize active window horizontally"));
510 WMAddListItem(panel->actLs, _("Raise active window"));
511 WMAddListItem(panel->actLs, _("Lower active window"));
512 WMAddListItem(panel->actLs, _("Raise/Lower window under mouse pointer"));
513 WMAddListItem(panel->actLs, _("Shade active window"));
514 WMAddListItem(panel->actLs, _("Move/Resize active window"));
515 WMAddListItem(panel->actLs, _("Select active window"));
516 WMAddListItem(panel->actLs, _("Focus next window"));
517 WMAddListItem(panel->actLs, _("Focus previous window"));
518 WMAddListItem(panel->actLs, _("Switch to next workspace"));
519 WMAddListItem(panel->actLs, _("Switch to previous workspace"));
520 WMAddListItem(panel->actLs, _("Switch to next ten workspaces"));
521 WMAddListItem(panel->actLs, _("Switch to previous ten workspaces"));
522 WMAddListItem(panel->actLs, _("Switch to workspace 1"));
523 WMAddListItem(panel->actLs, _("Switch to workspace 2"));
524 WMAddListItem(panel->actLs, _("Switch to workspace 3"));
525 WMAddListItem(panel->actLs, _("Switch to workspace 4"));
526 WMAddListItem(panel->actLs, _("Switch to workspace 5"));
527 WMAddListItem(panel->actLs, _("Switch to workspace 6"));
528 WMAddListItem(panel->actLs, _("Switch to workspace 7"));
529 WMAddListItem(panel->actLs, _("Switch to workspace 8"));
530 WMAddListItem(panel->actLs, _("Switch to workspace 9"));
531 WMAddListItem(panel->actLs, _("Switch to workspace 10"));
532 WMAddListItem(panel->actLs, _("Shortcut for window 1"));
533 WMAddListItem(panel->actLs, _("Shortcut for window 2"));
534 WMAddListItem(panel->actLs, _("Shortcut for window 3"));
535 WMAddListItem(panel->actLs, _("Shortcut for window 4"));
536 WMAddListItem(panel->actLs, _("Shortcut for window 5"));
537 WMAddListItem(panel->actLs, _("Shortcut for window 6"));
538 WMAddListItem(panel->actLs, _("Shortcut for window 7"));
539 WMAddListItem(panel->actLs, _("Shortcut for window 8"));
540 WMAddListItem(panel->actLs, _("Shortcut for window 9"));
541 WMAddListItem(panel->actLs, _("Shortcut for window 10"));
542 WMAddListItem(panel->actLs, _("Switch to Next Screen/Monitor"));
543 #ifdef VIRTUAL_DESKTOP
544 WMAddListItem(panel->actLs, _("Move VirtualDesktop to next left edge"));
545 WMAddListItem(panel->actLs, _("Move VirtualDesktop to next right edge"));
546 WMAddListItem(panel->actLs, _("Move VirtualDesktop to next top edge"));
547 WMAddListItem(panel->actLs, _("Move VirtualDesktop to next bottom edge"));
548 #endif
549 WMAddListItem(panel->actLs, _("Raise Clip"));
550 WMAddListItem(panel->actLs, _("Lower Clip"));
551 WMAddListItem(panel->actLs, _("Raise/Lower Clip"));
552 #ifdef XKB_MODELOCK
553 WMAddListItem(panel->actLs, _("Toggle keyboard language"));
554 #endif /* XKB_MODELOCK */
556 WMSetListAction(panel->actLs, listClick, panel);
558 panel->actionCount = WMGetListNumberOfRows(panel->actLs);
559 panel->shortcuts = wmalloc(sizeof(char*)*panel->actionCount);
560 memset(panel->shortcuts, 0, sizeof(char*)*panel->actionCount);
562 /***************** Shortcut ****************/
564 panel->shoF = WMCreateFrame(panel->box);
565 WMResizeWidget(panel->shoF, 190, 210);
566 WMMoveWidget(panel->shoF, 315, 10);
567 WMSetFrameTitle(panel->shoF, _("Shortcut"));
569 panel->shoT = WMCreateTextField(panel->shoF);
570 WMResizeWidget(panel->shoT, 160, 20);
571 WMMoveWidget(panel->shoT, 15, 65);
572 WMAddNotificationObserver(typedKeys, panel,
573 WMTextDidChangeNotification, panel->shoT);
575 panel->cleB = WMCreateCommandButton(panel->shoF);
576 WMResizeWidget(panel->cleB, 75, 24);
577 WMMoveWidget(panel->cleB, 15, 95);
578 WMSetButtonText(panel->cleB, _("Clear"));
579 WMSetButtonAction(panel->cleB, clearShortcut, panel);
581 panel->defB = WMCreateCommandButton(panel->shoF);
582 WMResizeWidget(panel->defB, 75, 24);
583 WMMoveWidget(panel->defB, 100, 95);
584 WMSetButtonText(panel->defB, _("Capture"));
585 WMSetButtonAction(panel->defB, captureClick, panel);
587 panel->instructionsL = WMCreateLabel(panel->shoF);
588 WMResizeWidget(panel->instructionsL, 160, 55);
589 WMMoveWidget(panel->instructionsL, 15, 140);
590 WMSetLabelTextAlignment(panel->instructionsL, WACenter);
591 WMSetLabelWraps(panel->instructionsL, True);
592 WMSetLabelText(panel->instructionsL, _("Click on Capture to interactively define the shortcut key."));
594 WMMapSubwidgets(panel->shoF);
596 WMReleaseFont(boldFont);
598 WMRealizeWidget(panel->box);
599 WMMapSubwidgets(panel->box);
602 showData(panel);
606 static void
607 storeData(_Panel *panel)
609 int i;
610 char *str;
612 for (i=0; i<panel->actionCount; i++) {
613 str = NULL;
614 if (panel->shortcuts[i]) {
615 str = trimstr(panel->shortcuts[i]);
616 if (strlen(str)==0) {
617 wfree(str);
618 str = NULL;
621 if (str) {
622 SetStringForKey(str, keyOptions[i]);
623 wfree(str);
624 } else {
625 SetStringForKey("None", keyOptions[i]);
632 Panel*
633 InitKeyboardShortcuts(WMScreen *scr, WMWidget *parent)
635 _Panel *panel;
637 panel = wmalloc(sizeof(_Panel));
638 memset(panel, 0, sizeof(_Panel));
640 panel->sectionName = _("Keyboard Shortcut Preferences");
642 panel->description = _("Change the keyboard shortcuts for actions such\n"
643 "as changing workspaces and opening menus.");
645 panel->parent = parent;
647 panel->callbacks.createWidgets = createPanel;
648 panel->callbacks.updateDomain = storeData;
650 AddSection(panel, ICON_FILE);
652 return panel;