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 along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "config.h" /* for HAVE_XCONVERTCASE */
27 #include <X11/keysym.h>
28 #include <X11/XKBlib.h>
30 typedef struct _Panel
{
37 CallbackRec callbacks
;
49 WMLabel
*instructionsL
;
61 #define ICON_FILE "keyshortcuts"
64 * List of user definable shortcut keys
65 * First parameter is the internal keyword known by WMaker
66 * Second is the text displayed to the user
68 static struct keyOption
{
72 { "RootMenuKey", N_("Open applications menu") },
73 { "WindowListKey", N_("Open window list menu") },
74 { "WindowMenuKey", N_("Open window commands menu") },
75 { "HideKey", N_("Hide active application") },
76 { "HideOthersKey", N_("Hide other applications") },
77 { "MiniaturizeKey", N_("Miniaturize active window") },
78 { "MinimizeAllKey", N_("Miniaturize all windows") },
79 { "CloseKey", N_("Close active window") },
80 { "MaximizeKey", N_("Maximize active window") },
81 { "VMaximizeKey", N_("Maximize active window vertically") },
82 { "HMaximizeKey", N_("Maximize active window horizontally") },
83 { "LHMaximizeKey", N_("Maximize active window left half") },
84 { "RHMaximizeKey", N_("Maximize active window right half") },
85 { "THMaximizeKey", N_("Maximize active window top half") },
86 { "BHMaximizeKey", N_("Maximize active window bottom half") },
87 { "TLCMaximizeKey", N_("Maximize active window top left corner") },
88 { "TRCMaximizeKey", N_("Maximize active window top right corner") },
89 { "BLCMaximizeKey", N_("Maximize active window bottom left corner") },
90 { "BRCMaximizeKey", N_("Maximize active window bottom right corner") },
91 { "MaximusKey", N_("Tile active window") },
92 { "CenterKey", N_("Center active window") },
93 { "KeepOnTopKey", N_("Toggle window on top status") },
94 { "KeepAtBottomKey",N_("Toggle window at bottom status") },
95 { "OmnipresentKey", N_("Toggle window omnipresent status") },
96 { "RaiseKey", N_("Raise active window") },
97 { "LowerKey", N_("Lower active window") },
98 { "RaiseLowerKey", N_("Raise/Lower window under mouse pointer") },
99 { "ShadeKey", N_("Shade active window") },
100 { "MoveResizeKey", N_("Move/Resize active window") },
101 { "SelectKey", N_("Select active window") },
102 { "FocusNextKey", N_("Focus next window") },
103 { "FocusPrevKey", N_("Focus previous window") },
104 { "GroupNextKey", N_("Focus next group window") },
105 { "GroupPrevKey", N_("Focus previous group window") },
107 /* Workspace Related */
108 { "WorkspaceMapKey", N_("Open workspace pager") },
109 { "NextWorkspaceKey", N_("Switch to next workspace") },
110 { "PrevWorkspaceKey", N_("Switch to previous workspace") },
111 { "LastWorkspaceKey", N_("Switch to last used workspace") },
112 { "NextWorkspaceLayerKey", N_("Switch to next ten workspaces") },
113 { "PrevWorkspaceLayerKey", N_("Switch to previous ten workspaces") },
114 { "Workspace1Key", N_("Switch to workspace 1") },
115 { "Workspace2Key", N_("Switch to workspace 2") },
116 { "Workspace3Key", N_("Switch to workspace 3") },
117 { "Workspace4Key", N_("Switch to workspace 4") },
118 { "Workspace5Key", N_("Switch to workspace 5") },
119 { "Workspace6Key", N_("Switch to workspace 6") },
120 { "Workspace7Key", N_("Switch to workspace 7") },
121 { "Workspace8Key", N_("Switch to workspace 8") },
122 { "Workspace9Key", N_("Switch to workspace 9") },
123 { "Workspace10Key", N_("Switch to workspace 10") },
124 { "MoveToNextWorkspaceKey", N_("Move window to next workspace") },
125 { "MoveToPrevWorkspaceKey", N_("Move window to previous workspace") },
126 { "MoveToLastWorkspaceKey", N_("Move window to last used workspace") },
127 { "MoveToNextWorkspaceLayerKey", N_("Move window to next ten workspaces") },
128 { "MoveToPrevWorkspaceLayerKey", N_("Move window to previous ten workspaces") },
129 { "MoveToWorkspace1Key", N_("Move window to workspace 1") },
130 { "MoveToWorkspace2Key", N_("Move window to workspace 2") },
131 { "MoveToWorkspace3Key", N_("Move window to workspace 3") },
132 { "MoveToWorkspace4Key", N_("Move window to workspace 4") },
133 { "MoveToWorkspace5Key", N_("Move window to workspace 5") },
134 { "MoveToWorkspace6Key", N_("Move window to workspace 6") },
135 { "MoveToWorkspace7Key", N_("Move window to workspace 7") },
136 { "MoveToWorkspace8Key", N_("Move window to workspace 8") },
137 { "MoveToWorkspace9Key", N_("Move window to workspace 9") },
138 { "MoveToWorkspace10Key", N_("Move window to workspace 10") },
140 /* Window Selection */
141 { "WindowShortcut1Key", N_("Shortcut for window 1") },
142 { "WindowShortcut2Key", N_("Shortcut for window 2") },
143 { "WindowShortcut3Key", N_("Shortcut for window 3") },
144 { "WindowShortcut4Key", N_("Shortcut for window 4") },
145 { "WindowShortcut5Key", N_("Shortcut for window 5") },
146 { "WindowShortcut6Key", N_("Shortcut for window 6") },
147 { "WindowShortcut7Key", N_("Shortcut for window 7") },
148 { "WindowShortcut8Key", N_("Shortcut for window 8") },
149 { "WindowShortcut9Key", N_("Shortcut for window 9") },
150 { "WindowShortcut10Key", N_("Shortcut for window 10") },
153 { "MoveTo12to6Head", N_("Move to right/bottom/left/top head") },
154 { "MoveTo6to12Head", N_("Move to left/top/right/bottom head") },
157 { "WindowRelaunchKey", N_("Launch new instance of application") },
158 { "ScreenSwitchKey", N_("Switch to next screen/monitor") },
159 { "RunKey", N_("Run application") },
160 { "ExitKey", N_("Exit Window Maker") },
161 { "DockRaiseLowerKey", N_("Raise/Lower Dock") },
162 { "ClipRaiseLowerKey", N_("Raise/Lower Clip") },
163 { "ScreenCaptureKey", N_("Capture the entire screen") },
164 { "WindowCaptureKey", N_("Capture a window") },
165 { "PartialCaptureKey", N_("Capture a portion of the screen") }
167 ,{ "ToggleKbdModeKey", N_("Toggle keyboard language") }
168 #endif /* XKB_MODELOCK */
171 #ifndef HAVE_XCONVERTCASE
174 static void XConvertCase(register KeySym sym
, KeySym
* lower
, KeySym
* upper
)
179 case 0: /* Latin 1 */
180 if ((sym
>= XK_A
) && (sym
<= XK_Z
))
181 *lower
+= (XK_a
- XK_A
);
182 else if ((sym
>= XK_a
) && (sym
<= XK_z
))
183 *upper
-= (XK_a
- XK_A
);
184 else if ((sym
>= XK_Agrave
) && (sym
<= XK_Odiaeresis
))
185 *lower
+= (XK_agrave
- XK_Agrave
);
186 else if ((sym
>= XK_agrave
) && (sym
<= XK_odiaeresis
))
187 *upper
-= (XK_agrave
- XK_Agrave
);
188 else if ((sym
>= XK_Ooblique
) && (sym
<= XK_Thorn
))
189 *lower
+= (XK_oslash
- XK_Ooblique
);
190 else if ((sym
>= XK_oslash
) && (sym
<= XK_thorn
))
191 *upper
-= (XK_oslash
- XK_Ooblique
);
193 case 1: /* Latin 2 */
194 /* Assume the KeySym is a legal value (ignore discontinuities) */
195 if (sym
== XK_Aogonek
)
197 else if (sym
>= XK_Lstroke
&& sym
<= XK_Sacute
)
198 *lower
+= (XK_lstroke
- XK_Lstroke
);
199 else if (sym
>= XK_Scaron
&& sym
<= XK_Zacute
)
200 *lower
+= (XK_scaron
- XK_Scaron
);
201 else if (sym
>= XK_Zcaron
&& sym
<= XK_Zabovedot
)
202 *lower
+= (XK_zcaron
- XK_Zcaron
);
203 else if (sym
== XK_aogonek
)
205 else if (sym
>= XK_lstroke
&& sym
<= XK_sacute
)
206 *upper
-= (XK_lstroke
- XK_Lstroke
);
207 else if (sym
>= XK_scaron
&& sym
<= XK_zacute
)
208 *upper
-= (XK_scaron
- XK_Scaron
);
209 else if (sym
>= XK_zcaron
&& sym
<= XK_zabovedot
)
210 *upper
-= (XK_zcaron
- XK_Zcaron
);
211 else if (sym
>= XK_Racute
&& sym
<= XK_Tcedilla
)
212 *lower
+= (XK_racute
- XK_Racute
);
213 else if (sym
>= XK_racute
&& sym
<= XK_tcedilla
)
214 *upper
-= (XK_racute
- XK_Racute
);
216 case 2: /* Latin 3 */
217 /* Assume the KeySym is a legal value (ignore discontinuities) */
218 if (sym
>= XK_Hstroke
&& sym
<= XK_Hcircumflex
)
219 *lower
+= (XK_hstroke
- XK_Hstroke
);
220 else if (sym
>= XK_Gbreve
&& sym
<= XK_Jcircumflex
)
221 *lower
+= (XK_gbreve
- XK_Gbreve
);
222 else if (sym
>= XK_hstroke
&& sym
<= XK_hcircumflex
)
223 *upper
-= (XK_hstroke
- XK_Hstroke
);
224 else if (sym
>= XK_gbreve
&& sym
<= XK_jcircumflex
)
225 *upper
-= (XK_gbreve
- XK_Gbreve
);
226 else if (sym
>= XK_Cabovedot
&& sym
<= XK_Scircumflex
)
227 *lower
+= (XK_cabovedot
- XK_Cabovedot
);
228 else if (sym
>= XK_cabovedot
&& sym
<= XK_scircumflex
)
229 *upper
-= (XK_cabovedot
- XK_Cabovedot
);
231 case 3: /* Latin 4 */
232 /* Assume the KeySym is a legal value (ignore discontinuities) */
233 if (sym
>= XK_Rcedilla
&& sym
<= XK_Tslash
)
234 *lower
+= (XK_rcedilla
- XK_Rcedilla
);
235 else if (sym
>= XK_rcedilla
&& sym
<= XK_tslash
)
236 *upper
-= (XK_rcedilla
- XK_Rcedilla
);
237 else if (sym
== XK_ENG
)
239 else if (sym
== XK_eng
)
241 else if (sym
>= XK_Amacron
&& sym
<= XK_Umacron
)
242 *lower
+= (XK_amacron
- XK_Amacron
);
243 else if (sym
>= XK_amacron
&& sym
<= XK_umacron
)
244 *upper
-= (XK_amacron
- XK_Amacron
);
246 case 6: /* Cyrillic */
247 /* Assume the KeySym is a legal value (ignore discontinuities) */
248 if (sym
>= XK_Serbian_DJE
&& sym
<= XK_Serbian_DZE
)
249 *lower
-= (XK_Serbian_DJE
- XK_Serbian_dje
);
250 else if (sym
>= XK_Serbian_dje
&& sym
<= XK_Serbian_dze
)
251 *upper
+= (XK_Serbian_DJE
- XK_Serbian_dje
);
252 else if (sym
>= XK_Cyrillic_YU
&& sym
<= XK_Cyrillic_HARDSIGN
)
253 *lower
-= (XK_Cyrillic_YU
- XK_Cyrillic_yu
);
254 else if (sym
>= XK_Cyrillic_yu
&& sym
<= XK_Cyrillic_hardsign
)
255 *upper
+= (XK_Cyrillic_YU
- XK_Cyrillic_yu
);
258 /* Assume the KeySym is a legal value (ignore discontinuities) */
259 if (sym
>= XK_Greek_ALPHAaccent
&& sym
<= XK_Greek_OMEGAaccent
)
260 *lower
+= (XK_Greek_alphaaccent
- XK_Greek_ALPHAaccent
);
261 else if (sym
>= XK_Greek_alphaaccent
&& sym
<= XK_Greek_omegaaccent
&&
262 sym
!= XK_Greek_iotaaccentdieresis
&& sym
!= XK_Greek_upsilonaccentdieresis
)
263 *upper
-= (XK_Greek_alphaaccent
- XK_Greek_ALPHAaccent
);
264 else if (sym
>= XK_Greek_ALPHA
&& sym
<= XK_Greek_OMEGA
)
265 *lower
+= (XK_Greek_alpha
- XK_Greek_ALPHA
);
266 else if (sym
>= XK_Greek_alpha
&& sym
<= XK_Greek_omega
&& sym
!= XK_Greek_finalsmallsigma
)
267 *upper
-= (XK_Greek_alpha
- XK_Greek_ALPHA
);
269 case 0x14: /* Armenian */
270 if (sym
>= XK_Armenian_AYB
&& sym
<= XK_Armenian_fe
) {
279 static int NumLockMask(Display
*dpy
)
282 XModifierKeymap
*map
;
283 static int mask_table
[8] = {
284 ShiftMask
, LockMask
, ControlMask
, Mod1Mask
,
285 Mod2Mask
, Mod3Mask
, Mod4Mask
, Mod5Mask
287 KeyCode numlock_keycode
= XKeysymToKeycode(dpy
, XK_Num_Lock
);
289 if (numlock_keycode
== NoSymbol
)
292 map
= XGetModifierMapping(dpy
);
297 for (i
= 0; i
< 8 * map
->max_keypermod
; i
++) {
298 if (map
->modifiermap
[i
] == numlock_keycode
&& mask
== 0) {
299 mask
= mask_table
[i
/map
->max_keypermod
];
305 XFreeModifiermap(map
);
310 char *capture_shortcut(Display
*dpy
, Bool
*capturing
, Bool convert_case
)
313 KeySym ksym
, lksym
, uksym
;
316 unsigned int numlock_mask
;
319 XAllowEvents(dpy
, AsyncKeyboard
, CurrentTime
);
320 WMNextEvent(dpy
, &ev
);
321 if (ev
.type
== KeyPress
&& ev
.xkey
.keycode
!= 0) {
322 numlock_mask
= NumLockMask(dpy
);
324 /* conditional mask check to get numeric keypad keys */
325 ksym
= W_KeycodeToKeysym(dpy
, ev
.xkey
.keycode
, ev
.xkey
.state
& numlock_mask
?1:0);
327 if (!IsModifierKey(ksym
)) {
329 XConvertCase(ksym
, &lksym
, &uksym
);
330 key
= XKeysymToString(uksym
);
332 key
= XKeysymToString(ksym
);
347 if (ev
.xkey
.state
& ControlMask
)
348 strcat(buffer
, "Control+");
350 if (ev
.xkey
.state
& ShiftMask
)
351 strcat(buffer
, "Shift+");
353 if ((numlock_mask
!= Mod1Mask
) && (ev
.xkey
.state
& Mod1Mask
))
354 strcat(buffer
, "Mod1+");
356 if ((numlock_mask
!= Mod2Mask
) && (ev
.xkey
.state
& Mod2Mask
))
357 strcat(buffer
, "Mod2+");
359 if ((numlock_mask
!= Mod3Mask
) && (ev
.xkey
.state
& Mod3Mask
))
360 strcat(buffer
, "Mod3+");
362 if ((numlock_mask
!= Mod4Mask
) && (ev
.xkey
.state
& Mod4Mask
))
363 strcat(buffer
, "Mod4+");
365 if ((numlock_mask
!= Mod5Mask
) && (ev
.xkey
.state
& Mod5Mask
))
366 strcat(buffer
, "Mod5+");
368 wstrlcat(buffer
, key
, sizeof(buffer
));
370 return wstrdup(buffer
);
374 * check if the keystr entered is already set to another action
375 * if found it returns the position in the keyOptions
377 static int isKeySet(_Panel
*panel
, char *keystr
)
382 for (i
= 0; i
< panel
->actionCount
; i
++) {
384 if (panel
->shortcuts
[i
]) {
385 str
= wtrimspace(panel
->shortcuts
[i
]);
386 if (strlen(str
) == 0) {
392 if (strcmp(keystr
, str
) == 0) {
403 static void captureClick(WMWidget
* w
, void *data
)
405 _Panel
*panel
= (_Panel
*) data
;
406 Display
*dpy
= WMScreenDisplay(WMWidgetScreen(panel
->parent
));
409 if (!panel
->capturing
) {
410 panel
->capturing
= 1;
411 WMSetButtonText(w
, _("Cancel"));
412 WMSetLabelText(panel
->instructionsL
,
413 _("Press the desired shortcut key(s) or click Cancel to stop capturing."));
414 XGrabKeyboard(dpy
, WMWidgetXID(panel
->parent
), True
, GrabModeAsync
, GrabModeAsync
, CurrentTime
);
415 shortcut
= capture_shortcut(dpy
, &panel
->capturing
, 1);
418 int row
= WMGetListSelectedItemRow(panel
->actLs
);
420 key_idx
= isKeySet(panel
, shortcut
);
421 if (key_idx
>= 0 && (key_idx
!= row
)) {
424 msg
= wstrconcat(_("Key shortcut already in use by the "), _(keyOptions
[key_idx
].title
));
425 WMRunAlertPanel(WMWidgetScreen(w
), GetWindow(),
428 _("OK"), NULL
, NULL
);
432 WMSetTextFieldText(panel
->shoT
, shortcut
);
434 if (panel
->shortcuts
[row
])
435 wfree(panel
->shortcuts
[row
]);
436 panel
->shortcuts
[row
] = shortcut
;
438 WMRedisplayWidget(panel
->actLs
);
445 panel
->capturing
= 0;
446 WMSetButtonText(w
, _("Capture"));
447 WMSetLabelText(panel
->instructionsL
, _("Click on Capture to interactively define the shortcut key."));
448 XUngrabKeyboard(dpy
, CurrentTime
);
451 static void clearShortcut(WMWidget
* w
, void *data
)
453 _Panel
*panel
= (_Panel
*) data
;
454 int row
= WMGetListSelectedItemRow(panel
->actLs
);
456 /* Parameter not used, but tell the compiler that it is ok */
459 WMSetTextFieldText(panel
->shoT
, NULL
);
462 if (panel
->shortcuts
[row
])
463 wfree(panel
->shortcuts
[row
]);
464 panel
->shortcuts
[row
] = NULL
;
465 WMRedisplayWidget(panel
->actLs
);
469 static void typedKeys(void *observerData
, WMNotification
* notification
)
471 _Panel
*panel
= (_Panel
*) observerData
;
472 int row
= WMGetListSelectedItemRow(panel
->actLs
);
474 /* Parameter not used, but tell the compiler that it is ok */
480 if (panel
->shortcuts
[row
])
481 wfree(panel
->shortcuts
[row
]);
482 panel
->shortcuts
[row
] = WMGetTextFieldText(panel
->shoT
);
483 if (strlen(panel
->shortcuts
[row
]) == 0) {
484 wfree(panel
->shortcuts
[row
]);
485 panel
->shortcuts
[row
] = NULL
;
487 WMRedisplayWidget(panel
->actLs
);
490 static void listClick(WMWidget
* w
, void *data
)
492 _Panel
*panel
= (_Panel
*) data
;
493 int row
= WMGetListSelectedItemRow(w
);
495 WMSetTextFieldText(panel
->shoT
, panel
->shortcuts
[row
]);
498 static void showData(_Panel
* panel
)
503 for (i
= 0; i
< panel
->actionCount
; i
++) {
505 str
= GetStringForKey(keyOptions
[i
].key
);
506 if (panel
->shortcuts
[i
])
507 wfree(panel
->shortcuts
[i
]);
509 panel
->shortcuts
[i
] = wtrimspace(str
);
511 panel
->shortcuts
[i
] = NULL
;
513 if (panel
->shortcuts
[i
] &&
514 (strcasecmp(panel
->shortcuts
[i
], "none") == 0 || strlen(panel
->shortcuts
[i
]) == 0)) {
515 wfree(panel
->shortcuts
[i
]);
516 panel
->shortcuts
[i
] = NULL
;
519 WMRedisplayWidget(panel
->actLs
);
522 static void paintItem(WMList
* lPtr
, int index
, Drawable d
, char *text
, int state
, WMRect
* rect
)
524 int width
, height
, x
, y
;
525 _Panel
*panel
= (_Panel
*) WMGetHangedData(lPtr
);
526 WMScreen
*scr
= WMWidgetScreen(lPtr
);
527 Display
*dpy
= WMScreenDisplay(scr
);
528 WMColor
*backColor
= (state
& WLDSSelected
) ? panel
->white
: panel
->gray
;
530 width
= rect
->size
.width
;
531 height
= rect
->size
.height
;
535 XFillRectangle(dpy
, d
, WMColorGC(backColor
), x
, y
, width
, height
);
537 if (panel
->shortcuts
[index
]) {
538 WMPixmap
*pix
= WMGetSystemPixmap(scr
, WSICheckMark
);
539 WMSize size
= WMGetPixmapSize(pix
);
541 WMDrawPixmap(pix
, d
, x
+ (20 - size
.width
) / 2, (height
- size
.height
) / 2 + y
);
542 WMReleasePixmap(pix
);
545 WMDrawString(scr
, d
, panel
->black
, panel
->font
, x
+ 20, y
, text
, strlen(text
));
548 static int cmpKeyOptions(const void *v1
, const void *v2
)
551 const struct keyOption
*opt1
= (struct keyOption
*)v1
;
552 const struct keyOption
*opt2
= (struct keyOption
*)v2
;
554 if ((rc
= strncmp(opt1
->title
, opt2
->title
, 20)) < 0)
562 static void createPanel(Panel
* p
)
564 _Panel
*panel
= (_Panel
*) p
;
565 WMScreen
*scr
= WMWidgetScreen(panel
->parent
);
570 panel
->capturing
= 0;
572 panel
->white
= WMWhiteColor(scr
);
573 panel
->black
= WMBlackColor(scr
);
574 panel
->gray
= WMGrayColor(scr
);
575 panel
->font
= WMSystemFontOfSize(scr
, 12);
577 panel
->box
= WMCreateBox(panel
->parent
);
578 WMSetViewExpandsToParent(WMWidgetView(panel
->box
), 2, 2, 2, 2);
580 boldFont
= WMBoldSystemFontOfSize(scr
, 12);
582 /* **************** Actions **************** */
583 panel
->actL
= WMCreateLabel(panel
->box
);
584 WMResizeWidget(panel
->actL
, 314, 20);
585 WMMoveWidget(panel
->actL
, 9, 9);
586 WMSetLabelFont(panel
->actL
, boldFont
);
587 WMSetLabelText(panel
->actL
, _("Actions"));
588 WMSetLabelRelief(panel
->actL
, WRSunken
);
589 WMSetLabelTextAlignment(panel
->actL
, WACenter
);
590 color
= WMDarkGrayColor(scr
);
591 WMSetWidgetBackgroundColor(panel
->actL
, color
);
592 WMReleaseColor(color
);
593 WMSetLabelTextColor(panel
->actL
, panel
->white
);
595 panel
->actLs
= WMCreateList(panel
->box
);
596 WMResizeWidget(panel
->actLs
, 314, 191);
597 WMMoveWidget(panel
->actLs
, 9, 31);
598 WMSetListUserDrawProc(panel
->actLs
, paintItem
);
599 WMHangData(panel
->actLs
, panel
);
601 qsort(keyOptions
, wlengthof(keyOptions
), sizeof(keyOptions
[0]), cmpKeyOptions
);
602 for (i
= 0; i
< wlengthof(keyOptions
); i
++) {
603 WMAddListItem(panel
->actLs
, _(keyOptions
[i
].title
));
605 WMSetListAction(panel
->actLs
, listClick
, panel
);
607 panel
->actionCount
= WMGetListNumberOfRows(panel
->actLs
);
608 panel
->shortcuts
= wmalloc(sizeof(char *) * panel
->actionCount
);
610 /***************** Shortcut ****************/
612 panel
->shoF
= WMCreateFrame(panel
->box
);
613 WMResizeWidget(panel
->shoF
, 178, 214);
614 WMMoveWidget(panel
->shoF
, 333, 8);
615 WMSetFrameTitle(panel
->shoF
, _("Shortcut"));
617 panel
->shoT
= WMCreateTextField(panel
->shoF
);
618 WMResizeWidget(panel
->shoT
, 160, 20);
619 WMMoveWidget(panel
->shoT
, 9, 65);
620 WMAddNotificationObserver(typedKeys
, panel
, WMTextDidChangeNotification
, panel
->shoT
);
622 panel
->cleB
= WMCreateCommandButton(panel
->shoF
);
623 WMResizeWidget(panel
->cleB
, 75, 24);
624 WMMoveWidget(panel
->cleB
, 9, 95);
625 WMSetButtonText(panel
->cleB
, _("Clear"));
626 WMSetButtonAction(panel
->cleB
, clearShortcut
, panel
);
628 panel
->defB
= WMCreateCommandButton(panel
->shoF
);
629 WMResizeWidget(panel
->defB
, 75, 24);
630 WMMoveWidget(panel
->defB
, 94, 95);
631 WMSetButtonText(panel
->defB
, _("Capture"));
632 WMSetButtonAction(panel
->defB
, captureClick
, panel
);
634 panel
->instructionsL
= WMCreateLabel(panel
->shoF
);
635 WMResizeWidget(panel
->instructionsL
, 160, 55);
636 WMMoveWidget(panel
->instructionsL
, 9, 140);
637 WMSetLabelTextAlignment(panel
->instructionsL
, WACenter
);
638 WMSetLabelWraps(panel
->instructionsL
, True
);
639 WMSetLabelText(panel
->instructionsL
, _("Click on Capture to interactively define the shortcut key."));
641 WMMapSubwidgets(panel
->shoF
);
643 WMReleaseFont(boldFont
);
645 WMRealizeWidget(panel
->box
);
646 WMMapSubwidgets(panel
->box
);
651 static void storeData(_Panel
* panel
)
656 for (i
= 0; i
< panel
->actionCount
; i
++) {
658 if (panel
->shortcuts
[i
]) {
659 str
= wtrimspace(panel
->shortcuts
[i
]);
660 if (strlen(str
) == 0) {
666 SetStringForKey(str
, keyOptions
[i
].key
);
669 SetStringForKey("None", keyOptions
[i
].key
);
674 Panel
*InitKeyboardShortcuts(WMWidget
*parent
)
678 panel
= wmalloc(sizeof(_Panel
));
680 panel
->sectionName
= _("Keyboard Shortcut Preferences");
682 panel
->description
= _("Change the keyboard shortcuts for actions such\n"
683 "as changing workspaces and opening menus.");
685 panel
->parent
= parent
;
687 panel
->callbacks
.createWidgets
= createPanel
;
688 panel
->callbacks
.updateDomain
= storeData
;
690 AddSection(panel
, ICON_FILE
);