- Check whether libXft is at least version 2.1.2 else refuse to compile.
[wmaker-crm.git] / WPrefs.app / KeyboardShortcuts.c
blobfadee5dad7276cfc4375a27663dfcbbf3a99680f
1 /* KeyboardShortcuts.c- keyboard shortcut bindings
2 *
3 * WPrefs - Window Maker Preferences Program
4 *
5 * Copyright (c) 1998-2003 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 "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(sym, lower, upper)
138 register KeySym sym;
139 KeySym *lower;
140 KeySym *upper;
142 *lower = sym;
143 *upper = sym;
144 switch(sym >> 8) {
145 case 0: /* Latin 1 */
146 if ((sym >= XK_A) && (sym <= XK_Z))
147 *lower += (XK_a - XK_A);
148 else if ((sym >= XK_a) && (sym <= XK_z))
149 *upper -= (XK_a - XK_A);
150 else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
151 *lower += (XK_agrave - XK_Agrave);
152 else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
153 *upper -= (XK_agrave - XK_Agrave);
154 else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
155 *lower += (XK_oslash - XK_Ooblique);
156 else if ((sym >= XK_oslash) && (sym <= XK_thorn))
157 *upper -= (XK_oslash - XK_Ooblique);
158 break;
159 case 1: /* Latin 2 */
160 /* Assume the KeySym is a legal value (ignore discontinuities) */
161 if (sym == XK_Aogonek)
162 *lower = XK_aogonek;
163 else if (sym >= XK_Lstroke && sym <= XK_Sacute)
164 *lower += (XK_lstroke - XK_Lstroke);
165 else if (sym >= XK_Scaron && sym <= XK_Zacute)
166 *lower += (XK_scaron - XK_Scaron);
167 else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
168 *lower += (XK_zcaron - XK_Zcaron);
169 else if (sym == XK_aogonek)
170 *upper = XK_Aogonek;
171 else if (sym >= XK_lstroke && sym <= XK_sacute)
172 *upper -= (XK_lstroke - XK_Lstroke);
173 else if (sym >= XK_scaron && sym <= XK_zacute)
174 *upper -= (XK_scaron - XK_Scaron);
175 else if (sym >= XK_zcaron && sym <= XK_zabovedot)
176 *upper -= (XK_zcaron - XK_Zcaron);
177 else if (sym >= XK_Racute && sym <= XK_Tcedilla)
178 *lower += (XK_racute - XK_Racute);
179 else if (sym >= XK_racute && sym <= XK_tcedilla)
180 *upper -= (XK_racute - XK_Racute);
181 break;
182 case 2: /* Latin 3 */
183 /* Assume the KeySym is a legal value (ignore discontinuities) */
184 if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
185 *lower += (XK_hstroke - XK_Hstroke);
186 else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
187 *lower += (XK_gbreve - XK_Gbreve);
188 else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
189 *upper -= (XK_hstroke - XK_Hstroke);
190 else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
191 *upper -= (XK_gbreve - XK_Gbreve);
192 else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
193 *lower += (XK_cabovedot - XK_Cabovedot);
194 else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
195 *upper -= (XK_cabovedot - XK_Cabovedot);
196 break;
197 case 3: /* Latin 4 */
198 /* Assume the KeySym is a legal value (ignore discontinuities) */
199 if (sym >= XK_Rcedilla && sym <= XK_Tslash)
200 *lower += (XK_rcedilla - XK_Rcedilla);
201 else if (sym >= XK_rcedilla && sym <= XK_tslash)
202 *upper -= (XK_rcedilla - XK_Rcedilla);
203 else if (sym == XK_ENG)
204 *lower = XK_eng;
205 else if (sym == XK_eng)
206 *upper = XK_ENG;
207 else if (sym >= XK_Amacron && sym <= XK_Umacron)
208 *lower += (XK_amacron - XK_Amacron);
209 else if (sym >= XK_amacron && sym <= XK_umacron)
210 *upper -= (XK_amacron - XK_Amacron);
211 break;
212 case 6: /* Cyrillic */
213 /* Assume the KeySym is a legal value (ignore discontinuities) */
214 if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
215 *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
216 else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
217 *upper += (XK_Serbian_DJE - XK_Serbian_dje);
218 else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
219 *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
220 else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
221 *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
222 break;
223 case 7: /* Greek */
224 /* Assume the KeySym is a legal value (ignore discontinuities) */
225 if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
226 *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
227 else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
228 sym != XK_Greek_iotaaccentdieresis &&
229 sym != XK_Greek_upsilonaccentdieresis)
230 *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
231 else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
232 *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
233 else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
234 sym != XK_Greek_finalsmallsigma)
235 *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
236 break;
237 case 0x14: /* Armenian */
238 if (sym >= XK_Armenian_AYB && sym <= XK_Armenian_fe) {
239 *lower = sym | 1;
240 *upper = sym & ~1;
242 break;
245 #endif
248 static char*
249 captureShortcut(Display *dpy, _Panel *panel)
251 XEvent ev;
252 KeySym ksym, lksym, uksym;
253 char buffer[64];
254 char *key = NULL;
256 while (panel->capturing) {
257 XAllowEvents(dpy, AsyncKeyboard, CurrentTime);
258 WMNextEvent(dpy, &ev);
259 if (ev.type==KeyPress && ev.xkey.keycode!=0) {
260 ksym = XKeycodeToKeysym(dpy, ev.xkey.keycode, 0);
261 if (!IsModifierKey(ksym)) {
262 XConvertCase(ksym, &lksym, &uksym);
263 key=XKeysymToString(uksym);
265 panel->capturing = 0;
266 break;
269 WMHandleEvent(&ev);
272 if (!key)
273 return NULL;
275 buffer[0] = 0;
277 if (ev.xkey.state & ControlMask) {
278 strcat(buffer, "Control+");
280 if (ev.xkey.state & ShiftMask) {
281 strcat(buffer, "Shift+");
283 if (ev.xkey.state & Mod1Mask) {
284 strcat(buffer, "Mod1+");
286 if (ev.xkey.state & Mod2Mask) {
287 strcat(buffer, "Mod2+");
289 if (ev.xkey.state & Mod3Mask) {
290 strcat(buffer, "Mod3+");
292 if (ev.xkey.state & Mod4Mask) {
293 strcat(buffer, "Mod4+");
295 if (ev.xkey.state & Mod5Mask) {
296 strcat(buffer, "Mod5+");
298 strcat(buffer, key);
300 return wstrdup(buffer);
304 static void
305 captureClick(WMWidget *w, void *data)
307 _Panel *panel = (_Panel*)data;
308 Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->parent));
309 char *shortcut;
311 if (!panel->capturing) {
312 panel->capturing = 1;
313 WMSetButtonText(w, _("Cancel"));
314 WMSetLabelText(panel->instructionsL, _("Press the desired shortcut key(s) or click Cancel to stop capturing."));
315 XGrabKeyboard(dpy, WMWidgetXID(panel->parent), True, GrabModeAsync,
316 GrabModeAsync, CurrentTime);
317 shortcut = captureShortcut(dpy, panel);
318 if (shortcut) {
319 int row = WMGetListSelectedItemRow(panel->actLs);
321 WMSetTextFieldText(panel->shoT, shortcut);
322 if (row>=0) {
323 if (panel->shortcuts[row])
324 wfree(panel->shortcuts[row]);
325 panel->shortcuts[row] = shortcut;
327 WMRedisplayWidget(panel->actLs);
328 } else {
329 wfree(shortcut);
333 panel->capturing = 0;
334 WMSetButtonText(w, _("Capture"));
335 WMSetLabelText(panel->instructionsL, _("Click on Capture to interactively define the shortcut key."));
336 XUngrabKeyboard(dpy, CurrentTime);
341 static void
342 clearShortcut(WMWidget *w, void *data)
344 _Panel *panel = (_Panel*)data;
345 int row = WMGetListSelectedItemRow(panel->actLs);
347 WMSetTextFieldText(panel->shoT, NULL);
349 if (row>=0) {
350 if (panel->shortcuts[row])
351 wfree(panel->shortcuts[row]);
352 panel->shortcuts[row]=NULL;
353 WMRedisplayWidget(panel->actLs);
359 static void
360 typedKeys(void *observerData, WMNotification *notification)
362 _Panel *panel = (_Panel*)observerData;
363 int row = WMGetListSelectedItemRow(panel->actLs);
365 if (row<0)
366 return;
368 if (panel->shortcuts[row])
369 wfree(panel->shortcuts[row]);
370 panel->shortcuts[row] = WMGetTextFieldText(panel->shoT);
371 if (strlen(panel->shortcuts[row])==0) {
372 wfree(panel->shortcuts[row]);
373 panel->shortcuts[row] = NULL;
375 WMRedisplayWidget(panel->actLs);
380 static void
381 listClick(WMWidget *w, void *data)
383 _Panel *panel = (_Panel*)data;
384 int row = WMGetListSelectedItemRow(w);
386 WMSetTextFieldText(panel->shoT, panel->shortcuts[row]);
390 static char*
391 trimstr(char *str)
393 char *p = str;
394 int i;
396 while (isspace(*p)) p++;
397 p = wstrdup(p);
398 i = strlen(p);
399 while (isspace(p[i]) && i>0) {
400 p[i]=0;
401 i--;
404 return p;
408 static void
409 showData(_Panel *panel)
411 char *str;
412 int i;
414 for (i=0; i<panel->actionCount; i++) {
416 str = GetStringForKey(keyOptions[i]);
417 if (panel->shortcuts[i])
418 wfree(panel->shortcuts[i]);
419 if (str)
420 panel->shortcuts[i] = trimstr(str);
421 else
422 panel->shortcuts[i] = NULL;
424 if (panel->shortcuts[i] &&
425 (strcasecmp(panel->shortcuts[i], "none")==0
426 || strlen(panel->shortcuts[i])==0)) {
427 wfree(panel->shortcuts[i]);
428 panel->shortcuts[i] = NULL;
431 WMRedisplayWidget(panel->actLs);
435 static void
436 paintItem(WMList *lPtr, int index, Drawable d, char *text, int state,
437 WMRect *rect)
439 int width, height, x, y;
440 _Panel *panel = (_Panel*)WMGetHangedData(lPtr);
441 WMScreen *scr = WMWidgetScreen(lPtr);
442 Display *dpy = WMScreenDisplay(scr);
443 WMColor *backColor = (state & WLDSSelected) ? panel->white : panel->gray;
445 width = rect->size.width;
446 height = rect->size.height;
447 x = rect->pos.x;
448 y = rect->pos.y;
450 XFillRectangle(dpy, d, WMColorGC(backColor), x, y, width, height);
452 if (panel->shortcuts[index]) {
453 WMPixmap *pix = WMGetSystemPixmap(scr, WSICheckMark);
454 WMSize size = WMGetPixmapSize(pix);
456 WMDrawPixmap(pix, d, x+(20-size.width)/2, (height-size.height)/2+y);
457 WMReleasePixmap(pix);
460 WMDrawString(scr, d, panel->black, panel->font, x+20, y, text, strlen(text));
464 static void
465 createPanel(Panel *p)
467 _Panel *panel = (_Panel*)p;
468 WMScreen *scr = WMWidgetScreen(panel->parent);
469 WMColor *color;
470 WMFont *boldFont;
472 panel->capturing = 0;
474 panel->white = WMWhiteColor(scr);
475 panel->black = WMBlackColor(scr);
476 panel->gray = WMGrayColor(scr);
477 panel->font = WMSystemFontOfSize(scr, 12);
479 panel->box = WMCreateBox(panel->parent);
480 WMSetViewExpandsToParent(WMWidgetView(panel->box), 2, 2, 2, 2);
482 boldFont = WMBoldSystemFontOfSize(scr, 12);
484 /* **************** Actions **************** */
485 panel->actL = WMCreateLabel(panel->box);
486 WMResizeWidget(panel->actL, 280, 20);
487 WMMoveWidget(panel->actL, 20, 10);
488 WMSetLabelFont(panel->actL, boldFont);
489 WMSetLabelText(panel->actL, _("Actions"));
490 WMSetLabelRelief(panel->actL, WRSunken);
491 WMSetLabelTextAlignment(panel->actL, WACenter);
492 color = WMDarkGrayColor(scr);
493 WMSetWidgetBackgroundColor(panel->actL, color);
494 WMReleaseColor(color);
495 WMSetLabelTextColor(panel->actL, panel->white);
497 panel->actLs = WMCreateList(panel->box);
498 WMResizeWidget(panel->actLs, 280, 190);
499 WMMoveWidget(panel->actLs, 20, 32);
500 WMSetListUserDrawProc(panel->actLs, paintItem);
501 WMHangData(panel->actLs, panel);
503 WMAddListItem(panel->actLs, _("Open applications menu"));
504 WMAddListItem(panel->actLs, _("Open window list menu"));
505 WMAddListItem(panel->actLs, _("Open window commands menu"));
506 WMAddListItem(panel->actLs, _("Hide active application"));
507 WMAddListItem(panel->actLs, _("Hide other applications"));
508 WMAddListItem(panel->actLs, _("Miniaturize active window"));
509 WMAddListItem(panel->actLs, _("Close active window"));
510 WMAddListItem(panel->actLs, _("Maximize active window"));
511 WMAddListItem(panel->actLs, _("Maximize active window vertically"));
512 WMAddListItem(panel->actLs, _("Maximize active window horizontally"));
513 WMAddListItem(panel->actLs, _("Raise active window"));
514 WMAddListItem(panel->actLs, _("Lower active window"));
515 WMAddListItem(panel->actLs, _("Raise/Lower window under mouse pointer"));
516 WMAddListItem(panel->actLs, _("Shade active window"));
517 WMAddListItem(panel->actLs, _("Move/Resize active window"));
518 WMAddListItem(panel->actLs, _("Select active window"));
519 WMAddListItem(panel->actLs, _("Focus next window"));
520 WMAddListItem(panel->actLs, _("Focus previous window"));
521 WMAddListItem(panel->actLs, _("Switch to next workspace"));
522 WMAddListItem(panel->actLs, _("Switch to previous workspace"));
523 WMAddListItem(panel->actLs, _("Switch to next ten workspaces"));
524 WMAddListItem(panel->actLs, _("Switch to previous ten workspaces"));
525 WMAddListItem(panel->actLs, _("Switch to workspace 1"));
526 WMAddListItem(panel->actLs, _("Switch to workspace 2"));
527 WMAddListItem(panel->actLs, _("Switch to workspace 3"));
528 WMAddListItem(panel->actLs, _("Switch to workspace 4"));
529 WMAddListItem(panel->actLs, _("Switch to workspace 5"));
530 WMAddListItem(panel->actLs, _("Switch to workspace 6"));
531 WMAddListItem(panel->actLs, _("Switch to workspace 7"));
532 WMAddListItem(panel->actLs, _("Switch to workspace 8"));
533 WMAddListItem(panel->actLs, _("Switch to workspace 9"));
534 WMAddListItem(panel->actLs, _("Switch to workspace 10"));
535 WMAddListItem(panel->actLs, _("Shortcut for window 1"));
536 WMAddListItem(panel->actLs, _("Shortcut for window 2"));
537 WMAddListItem(panel->actLs, _("Shortcut for window 3"));
538 WMAddListItem(panel->actLs, _("Shortcut for window 4"));
539 WMAddListItem(panel->actLs, _("Shortcut for window 5"));
540 WMAddListItem(panel->actLs, _("Shortcut for window 6"));
541 WMAddListItem(panel->actLs, _("Shortcut for window 7"));
542 WMAddListItem(panel->actLs, _("Shortcut for window 8"));
543 WMAddListItem(panel->actLs, _("Shortcut for window 9"));
544 WMAddListItem(panel->actLs, _("Shortcut for window 10"));
545 WMAddListItem(panel->actLs, _("Switch to Next Screen/Monitor"));
546 #ifdef VIRTUAL_DESKTOP
547 WMAddListItem(panel->actLs, _("Move VirtualDesktop to next left edge"));
548 WMAddListItem(panel->actLs, _("Move VirtualDesktop to next right edge"));
549 WMAddListItem(panel->actLs, _("Move VirtualDesktop to next top edge"));
550 WMAddListItem(panel->actLs, _("Move VirtualDesktop to next bottom edge"));
551 #endif
552 WMAddListItem(panel->actLs, _("Raise Clip"));
553 WMAddListItem(panel->actLs, _("Lower Clip"));
554 WMAddListItem(panel->actLs, _("Raise/Lower Clip"));
555 #ifdef XKB_MODELOCK
556 WMAddListItem(panel->actLs, _("Toggle keyboard language"));
557 #endif /* XKB_MODELOCK */
559 WMSetListAction(panel->actLs, listClick, panel);
561 panel->actionCount = WMGetListNumberOfRows(panel->actLs);
562 panel->shortcuts = wmalloc(sizeof(char*)*panel->actionCount);
563 memset(panel->shortcuts, 0, sizeof(char*)*panel->actionCount);
565 /***************** Shortcut ****************/
567 panel->shoF = WMCreateFrame(panel->box);
568 WMResizeWidget(panel->shoF, 190, 210);
569 WMMoveWidget(panel->shoF, 315, 10);
570 WMSetFrameTitle(panel->shoF, _("Shortcut"));
572 panel->shoT = WMCreateTextField(panel->shoF);
573 WMResizeWidget(panel->shoT, 160, 20);
574 WMMoveWidget(panel->shoT, 15, 65);
575 WMAddNotificationObserver(typedKeys, panel,
576 WMTextDidChangeNotification, panel->shoT);
578 panel->cleB = WMCreateCommandButton(panel->shoF);
579 WMResizeWidget(panel->cleB, 75, 24);
580 WMMoveWidget(panel->cleB, 15, 95);
581 WMSetButtonText(panel->cleB, _("Clear"));
582 WMSetButtonAction(panel->cleB, clearShortcut, panel);
584 panel->defB = WMCreateCommandButton(panel->shoF);
585 WMResizeWidget(panel->defB, 75, 24);
586 WMMoveWidget(panel->defB, 100, 95);
587 WMSetButtonText(panel->defB, _("Capture"));
588 WMSetButtonAction(panel->defB, captureClick, panel);
590 panel->instructionsL = WMCreateLabel(panel->shoF);
591 WMResizeWidget(panel->instructionsL, 160, 55);
592 WMMoveWidget(panel->instructionsL, 15, 140);
593 WMSetLabelTextAlignment(panel->instructionsL, WACenter);
594 WMSetLabelWraps(panel->instructionsL, True);
595 WMSetLabelText(panel->instructionsL, _("Click on Capture to interactively define the shortcut key."));
597 WMMapSubwidgets(panel->shoF);
599 WMReleaseFont(boldFont);
601 WMRealizeWidget(panel->box);
602 WMMapSubwidgets(panel->box);
605 showData(panel);
609 static void
610 storeData(_Panel *panel)
612 int i;
613 char *str;
615 for (i=0; i<panel->actionCount; i++) {
616 str = NULL;
617 if (panel->shortcuts[i]) {
618 str = trimstr(panel->shortcuts[i]);
619 if (strlen(str)==0) {
620 wfree(str);
621 str = NULL;
624 if (str) {
625 SetStringForKey(str, keyOptions[i]);
626 wfree(str);
627 } else {
628 SetStringForKey("None", keyOptions[i]);
635 Panel*
636 InitKeyboardShortcuts(WMScreen *scr, WMWidget *parent)
638 _Panel *panel;
640 panel = wmalloc(sizeof(_Panel));
641 memset(panel, 0, sizeof(_Panel));
643 panel->sectionName = _("Keyboard Shortcut Preferences");
645 panel->description = _("Change the keyboard shortcuts for actions such\n"
646 "as changing workspaces and opening menus.");
648 panel->parent = parent;
650 panel->callbacks.createWidgets = createPanel;
651 panel->callbacks.updateDomain = storeData;
653 AddSection(panel, ICON_FILE);
655 return panel;