1 /*
2 * Copyright (C) 2000-2019 the xine project
3 *
4 * This file is part of xine, a unix video player.
5 *
6 * xine is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * xine is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 *
20 */
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <stdio.h>
26 #include <X11/Xlib.h>
27 #include <X11/Xutil.h>
28 #include <X11/keysym.h>
29
30 #include "common.h"
31 #include "kbindings_common.h"
32
33
34 #undef TRACE_KBINDINGS
35
36 #define KBEDIT_NOOP 0
37 #define KBEDIT_ALIASING 1
38 #define KBEDIT_EDITING 2
39
40 typedef struct {
41 kbinding_t *kbt;
42
43 xitk_window_t *xwin;
44 xitk_widget_list_t *widget_list;
45 int running;
46 int visible;
47
48 xitk_widget_t *browser;
49 kbinding_entry_t *ksel;
50
51 xitk_widget_t *alias;
52 xitk_widget_t *edit;
53 xitk_widget_t *delete;
54 xitk_widget_t *save;
55 xitk_widget_t *done;
56 xitk_widget_t *grab;
57
58 xitk_widget_t *comment;
59 xitk_widget_t *key;
60
61 xitk_widget_t *ctrl;
62 xitk_widget_t *meta;
63 xitk_widget_t *mod3;
64 xitk_widget_t *mod4;
65 xitk_widget_t *mod5;
66
67 int num_entries;
68 char **entries;
69 char **shortcuts;
70
71 int grabbing;
72 int action_wanted; /* See KBEDIT_ defines */
73
74 xitk_register_key_t kreg;
75 } _kbedit_t;
76
77 static _kbedit_t *kbedit = NULL;
78
79 #define WINDOW_WIDTH 530
80 #define WINDOW_HEIGHT 456
81 #define MAX_DISP_ENTRIES 11
82
83 #define DEFAULT_DISPLAY_MODE 1
84 #define LIRC_DISPLAY_MODE 2
85
86 /*
87 Remap file entries syntax are:
88 ...
89 WindowReduce {
90 key = less
91 modifier = none
92 }
93
94 Alias {
95 entry = WindowReduce
96 key = w
97 modifier = control
98 }
99 ...
100 WindowReduce action key is <less>, with no modifier usage.
101 There is an alias: C-w (control w> keystroke will have same
102 action than WindowReduce.
103
104 modifier entry is optional.
105 modifier key can be multiple:
106 ...
107 WindowReduce {
108 key = less
109 modifier = control, meta
110 }
111 ...
112 Here, WindowReduce action keystroke will be CM-<
113
114 Key modifier name are:
115 none, control, ctrl, meta, alt, mod3, mod4, mod5.
116
117 shift,lock and numlock modifier are voluntary not handled.
118
119 */
120
121
_kbindings_display_kbindings_to_stream(kbinding_t * kbt,int mode,FILE * stream)122 static void _kbindings_display_kbindings_to_stream(kbinding_t *kbt, int mode, FILE *stream) {
123 char buf[256];
124 kbinding_entry_t **k;
125 int i;
126
127 if(kbt == NULL) {
128 xine_error(_("OOCH: key binding table is NULL.\n"));
129 return;
130 }
131
132 switch(mode) {
133 case LIRC_DISPLAY_MODE:
134 fprintf(stream, "##\n# xine key bindings.\n"
135 "# Automatically generated by %s version %s.\n##\n\n", PACKAGE, VERSION);
136
137 for(k = kbt->entry, i = 0; k[i]->action != NULL; i++) {
138 if(!k[i]->is_alias) {
139 snprintf(buf, sizeof(buf), "# %s\n", k[i]->comment);
140 strlcat(buf, "begin\n"
141 "\tremote = xxxxx\n"
142 "\tbutton = xxxxx\n"
143 "\tprog = xine\n"
144 "\trepeat = 0\n", sizeof(buf));
145 snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "\tconfig = %s\n", k[i]->action);
146 strlcat(buf, "end\n\n", sizeof(buf));
147 fputs(buf, stream);
148 }
149 }
150 fprintf(stream, "##\n# End of xine key bindings.\n##\n");
151 break;
152
153 case DEFAULT_DISPLAY_MODE:
154 default:
155 fprintf(stream, "##\n# xine key bindings.\n"
156 "# Automatically generated by %s version %s.\n##\n\n", PACKAGE, VERSION);
157
158 for(k = kbt->entry, i = 0; k[i]->action != NULL; i++) {
159 snprintf(buf, sizeof(buf), "# %s\n", k[i]->comment);
160
161 if(k[i]->is_alias) {
162 sprintf(buf+strlen(buf), "Alias {\n\tentry = %s\n", k[i]->action);
163 }
164 else
165 sprintf(buf+strlen(buf), "%s {\n", k[i]->action);
166
167 sprintf(buf+strlen(buf), "\tkey = %s\n\tmodifier = ", k[i]->key);
168 if(k[i]->modifier == KEYMOD_NOMOD)
169 strlcat(buf, "none, ", sizeof(buf));
170 if(k[i]->modifier & KEYMOD_CONTROL)
171 strlcat(buf, "control, ", sizeof(buf));
172 if(k[i]->modifier & KEYMOD_META)
173 strlcat(buf, "meta, ", sizeof(buf));
174 if(k[i]->modifier & KEYMOD_MOD3)
175 strlcat(buf, "mod3, ", sizeof(buf));
176 if(k[i]->modifier & KEYMOD_MOD4)
177 strlcat(buf, "mod4, ", sizeof(buf));
178 if(k[i]->modifier & KEYMOD_MOD5)
179 strlcat(buf, "mod5, ", sizeof(buf));
180 buf[strlen(buf) - 2] = '\n';
181 buf[strlen(buf) - 1] = '\0';
182 strlcat(buf, "}\n\n", sizeof(buf));
183 fputs(buf, stream);
184 }
185 fprintf(stream, "##\n# End of xine key bindings.\n##\n");
186 break;
187 }
188
189 }
190 /*
191 * Display all key bindings from kbt key binding table.
192 */
_kbindings_display_kbindings(kbinding_t * kbt,int mode)193 static void _kbindings_display_kbindings(kbinding_t *kbt, int mode) {
194 _kbindings_display_kbindings_to_stream(kbt, mode, stdout);
195 }
196
197 /*
198 * Convert a modifier to key binding modifier style.
199 */
kbindings_convert_modifier(int mod,int * modifier)200 static void kbindings_convert_modifier(int mod, int *modifier) {
201
202 ABORT_IF_NULL(modifier);
203
204 *modifier = KEYMOD_NOMOD;
205
206 if(mod & MODIFIER_CTRL)
207 *modifier |= KEYMOD_CONTROL;
208 if(mod & MODIFIER_META)
209 *modifier |= KEYMOD_META;
210 if(mod & MODIFIER_MOD3)
211 *modifier |= KEYMOD_MOD3;
212 if(mod & MODIFIER_MOD4)
213 *modifier |= KEYMOD_MOD4;
214 if(mod & MODIFIER_MOD5)
215 *modifier |= KEYMOD_MOD5;
216 }
217
218 /*
219 * Save current key binding table to keymap file.
220 */
kbindings_save_kbinding(kbinding_t * kbt)221 void kbindings_save_kbinding(kbinding_t *kbt) {
222 gGui_t *gui = gGui;
223 FILE *f;
224
225 if((f = fopen(gui->keymap_file, "w+")) == NULL) {
226 return;
227 }
228 else {
229 _kbindings_display_kbindings_to_stream(kbt, DEFAULT_DISPLAY_MODE, f);
230 fclose(f);
231 }
232 }
233
234 /*
235 * Return a duplicated table from kbt.
236 */
_kbindings_duplicate_kbindings(kbinding_t * kbt)237 static kbinding_t *_kbindings_duplicate_kbindings(kbinding_t *kbt) {
238 int i;
239 kbinding_t *k;
240
241 ABORT_IF_NULL(kbt);
242
243 k = (kbinding_t *) calloc(1, sizeof(kbinding_t));
244
245 for(i = 0; kbt->entry[i]->action != NULL; i++) {
246 k->entry[i] = (kbinding_entry_t *) calloc(1, sizeof(kbinding_entry_t));
247 k->entry[i]->comment = strdup(kbt->entry[i]->comment);
248 k->entry[i]->action = strdup(kbt->entry[i]->action);
249 k->entry[i]->action_id = kbt->entry[i]->action_id;
250 k->entry[i]->key = strdup(kbt->entry[i]->key);
251 k->entry[i]->modifier = kbt->entry[i]->modifier;
252 k->entry[i]->is_alias = kbt->entry[i]->is_alias;
253 k->entry[i]->is_gui = kbt->entry[i]->is_gui;
254 }
255
256 k->entry[i] = (kbinding_entry_t *) calloc(1, sizeof(kbinding_entry_t));
257 k->entry[i]->comment = NULL;
258 k->entry[i]->action = NULL;
259 k->entry[i]->action_id = 0;
260 k->entry[i]->key = NULL;
261 k->entry[i]->modifier = 0;
262 k->entry[i]->is_alias = 0;
263 k->entry[i]->is_gui = 0;
264 k->num_entries = i + 1;
265
266 return k;
267 }
268
269 /*
270 * Free key binding table kbt, then set it to default table.
271 */
kbindings_reset_kbinding(kbinding_t * kbt)272 void kbindings_reset_kbinding(kbinding_t *kbt) {
273
274 ABORT_IF_NULL(kbt);
275
276 _kbindings_free_bindings_no_kbt(kbt);
277 _kbindings_init_to_default_no_kbt(kbt);
278 }
279
280 /*
281 * This could be used to create a default key binding file
282 * with 'xine --keymap > $HOME/.xine_keymap'
283 */
kbindings_display_default_bindings(void)284 void kbindings_display_default_bindings(void) {
285 kbinding_t *kbt = NULL;
286
287 kbt = _kbindings_init_to_default();
288
289 _kbindings_display_kbindings(kbt, DEFAULT_DISPLAY_MODE);
290 _kbindings_free_bindings(kbt);
291 }
292
293 /*
294 * This could be used to create a default key binding file
295 * with 'xine --keymap=lirc > $HOME/.lircrc'
296 */
kbindings_display_default_lirc_bindings(void)297 void kbindings_display_default_lirc_bindings(void) {
298 kbinding_t *kbt = NULL;
299
300 kbt = _kbindings_init_to_default();
301
302 _kbindings_display_kbindings(kbt, LIRC_DISPLAY_MODE);
303 _kbindings_free_bindings(kbt);
304 }
305
306 /*
307 * This could be used to create a key binding file from key binding
308 * object k, with 'xine --keymap > $HOME/.xine_keymap'
309 */
kbindings_display_current_bindings(kbinding_t * kbt)310 void kbindings_display_current_bindings(kbinding_t *kbt) {
311
312 ABORT_IF_NULL(kbt);
313
314 _kbindings_display_kbindings(kbt, DEFAULT_DISPLAY_MODE);
315 }
316
317 /*
318 * Return action id from key binding kbt entry.
319 */
kbindings_get_action_id(kbinding_entry_t * kbt)320 action_id_t kbindings_get_action_id(kbinding_entry_t *kbt) {
321
322 if(kbt == NULL)
323 return ACTID_NOKEY;
324
325 return kbt->action_id;
326 }
327
_kbindings_get_shortcut_from_kbe(kbinding_entry_t * kbe)328 static const char *_kbindings_get_shortcut_from_kbe(kbinding_entry_t *kbe) {
329 gGui_t *gui = gGui;
330 static char shortcut[32];
331
332 if(kbe) {
333 shortcut[0] = 0;
334
335 if(gui->shortcut_style == 0) {
336 if(kbe->modifier & KEYMOD_CONTROL)
337 snprintf(shortcut+strlen(shortcut), sizeof(shortcut)-strlen(shortcut), "%s+", _("Ctrl"));
338 if(kbe->modifier & KEYMOD_META)
339 snprintf(shortcut+strlen(shortcut), sizeof(shortcut)-strlen(shortcut), "%s+", _("Alt"));
340 if(kbe->modifier & KEYMOD_MOD3)
341 strlcat(shortcut, "M3+", sizeof(shortcut));
342 if(kbe->modifier & KEYMOD_MOD4)
343 strlcat(shortcut, "M4+", sizeof(shortcut));
344 if(kbe->modifier & KEYMOD_MOD5)
345 strlcat(shortcut, "M5+", sizeof(shortcut));
346 }
347 else {
348 if(kbe->modifier & KEYMOD_CONTROL)
349 strlcat(shortcut, "C-", sizeof(shortcut));
350 if(kbe->modifier & KEYMOD_META)
351 strlcat(shortcut, "M-", sizeof(shortcut));
352 if(kbe->modifier & KEYMOD_MOD3)
353 strlcat(shortcut, "M3-", sizeof(shortcut));
354 if(kbe->modifier & KEYMOD_MOD4)
355 strlcat(shortcut, "M4-", sizeof(shortcut));
356 if(kbe->modifier & KEYMOD_MOD5)
357 strlcat(shortcut, "M5-", sizeof(shortcut));
358 }
359
360 strlcat(shortcut, kbe->key, sizeof(shortcut));
361
362 return shortcut;
363 }
364 return NULL;
365 }
366
kbindings_get_shortcut(kbinding_t * kbt,char * action)367 char *kbindings_get_shortcut(kbinding_t *kbt, char *action) {
368 kbinding_entry_t *k;
369 static char shortcut[32];
370
371 if(kbt) {
372 if(action && (k = kbindings_lookup_action(kbt, action))) {
373 if(strcmp(k->key, "VOID")) {
374 snprintf(shortcut, sizeof(shortcut), "%c%s%c", '[', _kbindings_get_shortcut_from_kbe(k), ']');
375 return shortcut;
376 }
377 }
378 }
379 return NULL;
380 }
381
382 /*
383 * Try to find and entry in key binding table matching with key and modifier value.
384 */
kbindings_lookup_binding(kbinding_t * kbt,const char * key,int modifier)385 static kbinding_entry_t *kbindings_lookup_binding(kbinding_t *kbt, const char *key, int modifier) {
386 kbinding_entry_t *kret = NULL, *k;
387 int i;
388
389 if((key == NULL) || (kbt == NULL))
390 return NULL;
391
392 #ifdef TRACE_KBINDINGS
393 printf("Looking for: '%s' [", key);
394 if(modifier == KEYMOD_NOMOD)
395 printf("none, ");
396 if(modifier & KEYMOD_CONTROL)
397 printf("control, ");
398 if(modifier & KEYMOD_META)
399 printf("meta, ");
400 if(modifier & KEYMOD_MOD3)
401 printf("mod3, ");
402 if(modifier & KEYMOD_MOD4)
403 printf("mod4, ");
404 if(modifier & KEYMOD_MOD5)
405 printf("mod5, ");
406 printf("\b\b]\n");
407 #endif
408
409 /* Be case sensitive */
410 for(i = 0, k = kbt->entry[0]; kbt->entry[i]->action != NULL; i++, k = kbt->entry[i]) {
411 if(k && k->key && strlen(k->key) && ((!(strcmp(k->key, key))) && (modifier == k->modifier))) {
412 kret = k;
413 goto __found;
414 }
415 }
416
417 /* Not case sensitive */
418 /*
419 for(i = 0, k = kbt[0]; kbt[i]->action != NULL; i++, k = kbt[i]) {
420 if((!(strcasecmp(k->key, key))) && (modifier == k->modifier))
421 return k;
422 }
423 */
424 /* Last chance */
425 for(i = 0, k = kbt->entry[0]; kbt->entry[i]->action != NULL; i++, k = kbt->entry[i]) {
426 if(k && k->key && strlen(k->key) && ((!(strcmp(k->key, key))) && (k->modifier == KEYMOD_NOMOD))) {
427 kret = k;
428 break;
429 }
430 }
431
432 __found:
433
434 /* Keybinding unknown */
435 return kret;
436 }
437
438 /* Convert X(Button|Key)(Press|Release) events into string identifier. */
xevent2id(XEvent * event,int * modifier,char * buf,int size)439 static int xevent2id(XEvent *event, int *modifier, char *buf, int size) {
440 int mod;
441 KeySym mkey;
442 char *keySym;
443
444 if (event == NULL)
445 return -1;
446
447 switch (event->type) {
448 case ButtonPress:
449 case ButtonRelease:
450 (void) xitk_get_key_modifier(event, &mod);
451 kbindings_convert_modifier(mod, modifier);
452 snprintf(buf, size, "XButton_%d", event->xbutton.button);
453 return 0;
454
455 case KeyPress:
456 case KeyRelease:
457 (void) xitk_get_key_modifier(event, &mod);
458 kbindings_convert_modifier(mod, modifier);
459 mkey = xitk_get_key_pressed(event);
460
461 switch (mkey) {
462 default:
463 gGui->x_lock_display (event->xany.display);
464 keySym = XKeysymToString(mkey);
465 gGui->x_unlock_display (event->xany.display);
466 if (keySym != NULL) {
467 strlcpy(buf, keySym, size);
468 return 0;
469 }
470 case 0: /* Key without assigned KeySymbol */
471 case XK_VoidSymbol:
472 /* For keys without assigned KeySyms. */
473 snprintf(buf, size, "XKey_%d", event->xkey.keycode);
474 return 0;
475 }
476
477 default:
478 memset(buf, 0, size);
479 return -1;
480 }
481 }
482
483 /*
484 * Handle key event from an XEvent.
485 */
kbindings_handle_kbinding(kbinding_t * kbt,XEvent * event)486 void kbindings_handle_kbinding(kbinding_t *kbt, XEvent *event) {
487 gGui_t *gui = gGui;
488 int modifier;
489 char buf[256];
490 kbinding_entry_t *k;
491
492 if(!gui->kbindings_enabled || (kbt == NULL) || (event == NULL))
493 return;
494
495 if (xevent2id(event, &modifier, buf, sizeof(buf)))
496 return;
497 k = kbindings_lookup_binding(kbt, buf, modifier);
498 if(k && !(gui->no_gui && k->is_gui))
499 gui_execute_action_id (gui, k->action_id);
500 #if 0 /* DEBUG */
501 else
502 printf("%s unhandled\n", kbuf);
503 #endif
504 }
505
506 /*
507 * ***** Key Binding Editor ******
508 */
509 /*
510 * return 1 if key binding editor is ON
511 */
kbedit_is_running(void)512 int kbedit_is_running(void) {
513
514 if(kbedit != NULL)
515 return kbedit->running;
516
517 return 0;
518 }
519
520 /*
521 * Return 1 if setup panel is visible
522 */
kbedit_is_visible(void)523 int kbedit_is_visible(void) {
524 gGui_t *gui = gGui;
525
526 if(kbedit != NULL) {
527 if(gui->use_root_window)
528 return xitk_is_window_visible(gui->display, xitk_window_get_window(kbedit->xwin));
529 else
530 return kbedit->visible && xitk_is_window_visible(gui->display, xitk_window_get_window(kbedit->xwin));
531 }
532
533 return 0;
534 }
535
536 /*
537 * Raise kbedit->xwin
538 */
kbedit_raise_window(void)539 void kbedit_raise_window(void) {
540
541 if(kbedit != NULL)
542 raise_window(xitk_window_get_window(kbedit->xwin), kbedit->visible, kbedit->running);
543 }
544
545 /*
546 * Hide/show the kbedit panel
547 */
kbedit_toggle_visibility(xitk_widget_t * w,void * data)548 void kbedit_toggle_visibility (xitk_widget_t *w, void *data) {
549 if(kbedit != NULL)
550 toggle_window(xitk_window_get_window(kbedit->xwin), kbedit->widget_list,
551 &kbedit->visible, kbedit->running);
552 }
553
kbedit_create_browser_entries(void)554 static void kbedit_create_browser_entries(void) {
555 gGui_t *gui = gGui;
556 xitk_font_t *fs;
557 int i;
558
559 if(kbedit->num_entries) {
560 for(i = 0; i < kbedit->num_entries; i++) {
561 free((char *)kbedit->entries[i]);
562 free((char *)kbedit->shortcuts[i]);
563 }
564 free((char **)kbedit->entries);
565 free((char **)kbedit->shortcuts);
566 }
567
568 fs = xitk_font_load_font(gui->display, br_fontname);
569 xitk_font_set_font(fs, (XITK_WIDGET_LIST_GC(kbedit->widget_list)));
570
571 kbedit->entries = (char **) calloc(kbedit->kbt->num_entries, sizeof(char *));
572 kbedit->shortcuts = (char **) calloc(kbedit->kbt->num_entries, sizeof(char *));
573 kbedit->num_entries = kbedit->kbt->num_entries - 1;
574
575 for(i = 0; i < kbedit->num_entries; i++) {
576 char buf[2048];
577 const char *sc = _kbindings_get_shortcut_from_kbe(kbedit->kbt->entry[i]);
578 char shortcut[32];
579
580 snprintf(shortcut, sizeof(shortcut), "%c%s%c", '[', (sc ? sc : "VOID"), ']');
581
582 if(kbedit->kbt->entry[i]->is_alias)
583 snprintf(buf, sizeof(buf), "@{%s}", kbedit->kbt->entry[i]->comment);
584 else
585 strlcpy(buf, kbedit->kbt->entry[i]->comment, sizeof(buf));
586
587 kbedit->entries[i] = strdup(buf);
588 kbedit->shortcuts[i] = strdup(shortcut);
589 }
590
591 kbedit->entries[i] = NULL;
592 kbedit->shortcuts[i] = NULL;
593
594 xitk_font_unload_font(fs);
595 }
596
kbedit_display_kbinding(const char * action,kbinding_entry_t * kbe)597 static void kbedit_display_kbinding(const char *action, kbinding_entry_t *kbe) {
598
599 if(action && kbe) {
600
601 xitk_label_change_label(kbedit->comment, action);
602 xitk_label_change_label(kbedit->key, kbe->key);
603
604 xitk_checkbox_set_state(kbedit->ctrl, (kbe->modifier & KEYMOD_CONTROL) ? 1 : 0);
605 xitk_checkbox_set_state(kbedit->meta, (kbe->modifier & KEYMOD_META) ? 1 : 0);
606 xitk_checkbox_set_state(kbedit->mod3, (kbe->modifier & KEYMOD_MOD3) ? 1 : 0);
607 xitk_checkbox_set_state(kbedit->mod4, (kbe->modifier & KEYMOD_MOD4) ? 1 : 0);
608 xitk_checkbox_set_state(kbedit->mod5, (kbe->modifier & KEYMOD_MOD5) ? 1 : 0);
609 }
610 }
611
612 /*
613 *
614 */
kbedit_select(int s)615 static void kbedit_select(int s) {
616
617 xitk_enable_and_show_widget(kbedit->alias);
618 xitk_enable_and_show_widget(kbedit->edit);
619 xitk_enable_and_show_widget(kbedit->delete);
620
621 kbedit->ksel = kbedit->kbt->entry[s];
622 kbedit_display_kbinding(kbedit->entries[s], kbedit->kbt->entry[s]);
623 }
624
625 /*
626 *
627 */
kbedit_unset(void)628 static void kbedit_unset(void) {
629
630 if(xitk_labelbutton_get_state(kbedit->alias))
631 xitk_labelbutton_set_state(kbedit->alias, 0);
632
633 if(xitk_labelbutton_get_state(kbedit->edit))
634 xitk_labelbutton_set_state(kbedit->edit, 0);
635
636 xitk_disable_widget(kbedit->alias);
637 xitk_disable_widget(kbedit->edit);
638 xitk_disable_widget(kbedit->delete);
639 xitk_disable_widget(kbedit->grab);
640 kbedit->ksel = NULL;
641
642 xitk_label_change_label(kbedit->comment, _("Nothing selected"));
643 xitk_label_change_label(kbedit->key, _("None"));
644
645 xitk_checkbox_set_state(kbedit->ctrl, 0);
646 xitk_checkbox_set_state(kbedit->meta, 0);
647 xitk_checkbox_set_state(kbedit->mod3, 0);
648 xitk_checkbox_set_state(kbedit->mod4, 0);
649 xitk_checkbox_set_state(kbedit->mod5, 0);
650 }
651
652 /*
653 * Check for redundancy.
654 * return: -2 on failure (null pointer passed)
655 * -1 on success
656 * >=0 if a redundant entry found (bkt array entry num).
657 */
bkedit_check_redundancy(kbinding_t * kbt,kbinding_entry_t * kbe)658 static int bkedit_check_redundancy(kbinding_t *kbt, kbinding_entry_t *kbe) {
659 int ret = -1;
660
661 if(kbt && kbe) {
662 int i;
663
664 for(i = 0; kbt->entry[i]->action != NULL; i++) {
665 if((!strcmp(kbt->entry[i]->key, kbe->key)) &&
666 (kbt->entry[i]->modifier == kbe->modifier) &&
667 (strcasecmp(kbt->entry[i]->key, "void"))) {
668 return i;
669 }
670 }
671 }
672 else
673 ret = -2;
674
675 return ret;
676 }
677
678 /*
679 *
680 */
kbedit_exit(xitk_widget_t * w,void * data)681 static void kbedit_exit(xitk_widget_t *w, void *data) {
682 gGui_t *gui = gGui;
683
684 if(kbedit) {
685 window_info_t wi;
686
687 kbedit->running = 0;
688 kbedit->visible = 0;
689
690 if((xitk_get_window_info(kbedit->kreg, &wi))) {
691 config_update_num("gui.kbedit_x", wi.x);
692 config_update_num("gui.kbedit_y", wi.y);
693 WINDOW_INFO_ZERO(&wi);
694 }
695
696 xitk_unregister_event_handler(&kbedit->kreg);
697
698 xitk_destroy_widgets(kbedit->widget_list);
699 xitk_window_destroy_window(gui->imlib_data, kbedit->xwin);
700
701 kbedit->xwin = NULL;
702 /* xitk_dlist_init (&kbedit->widget_list->list); */
703
704 gui->x_lock_display (gui->display);
705 XFreeGC(gui->display, (XITK_WIDGET_LIST_GC(kbedit->widget_list)));
706 gui->x_unlock_display (gui->display);
707
708 XITK_WIDGET_LIST_FREE(kbedit->widget_list);
709
710 {
711 int i;
712
713 for(i = 0; i < kbedit->num_entries; i++) {
714 free((char *)kbedit->entries[i]);
715 free((char *)kbedit->shortcuts[i]);
716 }
717
718 free((char **)kbedit->entries);
719 free((char **)kbedit->shortcuts);
720 }
721
722 kbindings_free_kbinding(&kbedit->kbt);
723
724 free(kbedit);
725 kbedit = NULL;
726 gui->ssaver_enabled = 1;
727
728 try_to_set_input_focus(gui->video_window);
729 }
730 }
731
732 /*
733 *
734 */
kbedit_sel(xitk_widget_t * w,void * data,int s)735 static void kbedit_sel(xitk_widget_t *w, void *data, int s) {
736
737 if(s >= 0)
738 kbedit_select(s);
739 }
740
741 /*
742 * Create an alias from the selected entry.
743 */
kbedit_alias(xitk_widget_t * w,void * data,int state)744 static void kbedit_alias(xitk_widget_t *w, void *data, int state) {
745
746 xitk_labelbutton_set_state(kbedit->edit, 0);
747
748 if(state) {
749 xitk_enable_widget(kbedit->grab);
750 kbedit->action_wanted = KBEDIT_ALIASING;
751 }
752 else {
753 xitk_disable_widget(kbedit->grab);
754 kbedit->action_wanted = KBEDIT_NOOP;
755 }
756 }
757
758 /*
759 * Change shortcut, should take care about reduncancy.
760 */
kbedit_edit(xitk_widget_t * w,void * data,int state)761 static void kbedit_edit(xitk_widget_t *w, void *data, int state) {
762
763 xitk_labelbutton_set_state(kbedit->alias, 0);
764
765 if(state) {
766 xitk_enable_widget(kbedit->grab);
767 kbedit->action_wanted = KBEDIT_EDITING;
768 }
769 else {
770 xitk_disable_widget(kbedit->grab);
771 kbedit->action_wanted = KBEDIT_NOOP;
772 }
773
774 }
775
776 /*
777 * Remove selected entry, but alias ones only.
778 */
kbedit_delete(xitk_widget_t * w,void * data)779 static void kbedit_delete(xitk_widget_t *w, void *data) {
780 int s = xitk_browser_get_current_selected(kbedit->browser);
781
782 xitk_labelbutton_set_state(kbedit->alias, 0);
783 xitk_labelbutton_set_state(kbedit->edit, 0);
784 xitk_disable_widget(kbedit->grab);
785
786 /* We can delete alias entries, only */
787 if(s >= 0) {
788
789 if(kbedit->kbt->entry[s]->is_alias) {
790 xitk_browser_release_all_buttons(kbedit->browser);
791
792 free(kbedit->kbt->entry[s]->comment);
793 free(kbedit->kbt->entry[s]->action);
794 free(kbedit->kbt->entry[s]->key);
795 free(kbedit->kbt->entry[s]);
796
797
798 for(; s < kbedit->num_entries; s++)
799 kbedit->kbt->entry[s] = kbedit->kbt->entry[s + 1];
800
801 kbedit->kbt->entry[s]->comment = NULL;
802 kbedit->kbt->entry[s]->action = NULL;
803 kbedit->kbt->entry[s]->key = NULL;
804
805 kbedit->kbt->num_entries--;
806
807 kbedit_create_browser_entries();
808
809 xitk_browser_update_list(kbedit->browser,
810 (const char* const*) kbedit->entries,
811 (const char* const*) kbedit->shortcuts, kbedit->num_entries, xitk_browser_get_current_start(kbedit->browser));
812 }
813 else
814 xine_error(_("You can only delete alias entries."));
815
816 }
817 }
818
819 /*
820 * Reset to xine's default table.
821 */
kbedit_reset(xitk_widget_t * w,void * data)822 static void kbedit_reset(xitk_widget_t *w, void *data) {
823
824 xitk_labelbutton_set_state(kbedit->alias, 0);
825 xitk_labelbutton_set_state(kbedit->edit, 0);
826 xitk_disable_widget(kbedit->grab);
827
828 kbindings_reset_kbinding(kbedit->kbt);
829 kbedit_create_browser_entries();
830 xitk_browser_update_list(kbedit->browser,
831 (const char* const*) kbedit->entries,
832 (const char* const*) kbedit->shortcuts, kbedit->num_entries, xitk_browser_get_current_start(kbedit->browser));
833 }
834
835 /*
836 * Save keymap file, then set global table to hacked one
837 */
kbedit_save(xitk_widget_t * w,void * data)838 static void kbedit_save(xitk_widget_t *w, void *data) {
839 gGui_t *gui = gGui;
840 xitk_labelbutton_set_state(kbedit->alias, 0);
841 xitk_labelbutton_set_state(kbedit->edit, 0);
842 xitk_disable_widget(kbedit->grab);
843
844 kbindings_free_kbinding(&gui->kbindings);
845 gui->kbindings = _kbindings_duplicate_kbindings(kbedit->kbt);
846 kbindings_save_kbinding(gui->kbindings);
847 }
848
849 /*
850 * Forget and dismiss kbeditor
851 */
kbedit_end(void)852 void kbedit_end(void) {
853 kbedit_exit(NULL, NULL);
854 }
855
kbedit_accept_yes(xitk_widget_t * w,void * data,int state)856 static void kbedit_accept_yes(xitk_widget_t *w, void *data, int state) {
857 kbinding_entry_t *kbe = (kbinding_entry_t *) data;
858
859 switch(kbedit->action_wanted) {
860
861 case KBEDIT_ALIASING:
862 if(kbedit->kbt->num_entries >= MAX_ENTRIES) {
863 xine_error(_("No more space for additional entries!"));
864 return;
865 }
866
867 kbedit->kbt->entry[kbedit->kbt->num_entries - 1]->comment = strdup(kbedit->ksel->comment);
868 kbedit->kbt->entry[kbedit->kbt->num_entries - 1]->action = strdup(kbedit->ksel->action);
869 kbedit->kbt->entry[kbedit->kbt->num_entries - 1]->action_id = kbedit->ksel->action_id;
870 kbedit->kbt->entry[kbedit->kbt->num_entries - 1]->key = strdup(kbe->key);
871 kbedit->kbt->entry[kbedit->kbt->num_entries - 1]->modifier = kbe->modifier;
872 kbedit->kbt->entry[kbedit->kbt->num_entries - 1]->is_alias = 1;
873 kbedit->kbt->entry[kbedit->kbt->num_entries - 1]->is_gui = kbe->is_gui;
874
875 kbedit->kbt->entry[kbedit->kbt->num_entries] = (kbinding_entry_t *) calloc(1, sizeof(kbinding_entry_t));
876 kbedit->kbt->entry[kbedit->kbt->num_entries]->comment = NULL;
877 kbedit->kbt->entry[kbedit->kbt->num_entries]->action = NULL;
878 kbedit->kbt->entry[kbedit->kbt->num_entries]->action_id = 0;
879 kbedit->kbt->entry[kbedit->kbt->num_entries]->key = NULL;
880 kbedit->kbt->entry[kbedit->kbt->num_entries]->modifier = 0;
881 kbedit->kbt->entry[kbedit->kbt->num_entries]->is_alias = 0;
882 kbedit->kbt->entry[kbedit->kbt->num_entries]->is_gui = 0;
883
884 kbedit->kbt->num_entries++;
885
886 kbedit_create_browser_entries();
887 xitk_browser_update_list(kbedit->browser,
888 (const char* const*) kbedit->entries,
889 (const char* const*) kbedit->shortcuts, kbedit->num_entries, xitk_browser_get_current_start(kbedit->browser));
890 break;
891
892 case KBEDIT_EDITING:
893 kbedit->ksel->key = (char *) realloc(kbedit->ksel->key, sizeof(char) * (strlen(kbe->key) + 1));
894 strcpy(kbedit->ksel->key, kbe->key);
895 kbedit->ksel->modifier = kbe->modifier;
896
897 kbedit_create_browser_entries();
898 xitk_browser_update_list(kbedit->browser,
899 (const char* const*) kbedit->entries,
900 (const char* const*) kbedit->shortcuts, kbedit->num_entries, xitk_browser_get_current_start(kbedit->browser));
901 break;
902 }
903
904 kbedit->action_wanted = KBEDIT_NOOP;
905
906 SAFE_FREE(kbe->comment);
907 SAFE_FREE(kbe->action);
908 SAFE_FREE(kbe->key);
909 SAFE_FREE(kbe);
910 kbedit_unset();
911 }
912
kbedit_accept_no(xitk_widget_t * w,void * data,int state)913 static void kbedit_accept_no(xitk_widget_t *w, void *data, int state) {
914 kbinding_entry_t *kbe = (kbinding_entry_t *) data;
915
916 kbedit->action_wanted = KBEDIT_NOOP;
917
918 xitk_browser_update_list(kbedit->browser,
919 (const char* const*) kbedit->entries,
920 (const char* const*) kbedit->shortcuts, kbedit->num_entries, xitk_browser_get_current_start(kbedit->browser));
921 SAFE_FREE(kbe->comment);
922 SAFE_FREE(kbe->action);
923 SAFE_FREE(kbe->key);
924 SAFE_FREE(kbe);
925 kbedit_unset();
926 }
927
928 /*
929 * Grab key binding.
930 */
kbedit_grab(xitk_widget_t * w,void * data)931 static void kbedit_grab(xitk_widget_t *w, void *data) {
932 gGui_t *gui = gGui;
933 char *olbl;
934 XEvent xev;
935 int mod, modifier;
936 xitk_window_t *xwin;
937 kbinding_entry_t *kbe;
938 int redundant;
939
940 /* We are already grabbing keybinding */
941 if(kbedit->grabbing)
942 return;
943
944 olbl = strdup(xitk_labelbutton_get_label(kbedit->grab));
945
946 kbedit->grabbing = 1;
947
948 kbe = (kbinding_entry_t *) calloc(1, sizeof(kbinding_entry_t));
949 kbe->comment = strdup(kbedit->ksel->comment);
950 kbe->action = strdup(kbedit->ksel->action);
951 kbe->action_id = kbedit->ksel->action_id;
952 kbe->is_alias = kbedit->ksel->is_alias;
953 kbe->is_gui = kbedit->ksel->is_gui;
954
955 xitk_labelbutton_change_label(kbedit->grab, _("Press Keyboard Keys..."));
956 gui->x_lock_display (gui->display);
957 XSync(gui->display, False);
958 gui->x_unlock_display (gui->display);
959
960 {
961 int x, y, w, h;
962
963 xitk_get_window_position(gui->display,
964 (xitk_window_get_window(kbedit->xwin)), &x, &y, &w, &h);
965
966 xwin = xitk_window_create_dialog_window(gui->imlib_data,
967 _("Event Receiver Window: Press keyboard keys to bind..."),
968 x, y, w, h);
969
970 set_window_states_start((xitk_window_get_window(xwin)));
971 }
972
973 gui->x_lock_display (gui->display);
974 XRaiseWindow(gui->display, (xitk_window_get_window(xwin)));
975 XMapWindow(gui->display, (xitk_window_get_window(xwin)));
976 gui->x_unlock_display (gui->display);
977
978 try_to_set_input_focus(xitk_window_get_window(xwin));
979
980 do {
981 /* Although only release events are evaluated, we must also grab the corresponding press */
982 /* events to hide them from the other GUI windows and prevent unexpected side effects. */
983 gui->x_lock_display (gui->display);
984 XMaskEvent(gui->display, ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask, &xev);
985 gui->x_unlock_display (gui->display);
986 } while ((xev.type != KeyRelease && xev.type != ButtonRelease) ||
987 xev.xany.window != xitk_window_get_window(xwin));
988
989 (void) xitk_get_key_modifier(&xev, &mod);
990 kbindings_convert_modifier(mod, &modifier);
991
992 kbe->modifier = modifier;
993
994
995 {
996 char buf[256];
997 xevent2id(&xev, &kbe->modifier, buf, sizeof(buf));
998 kbe->key = strdup(buf);
999 kbe->modifier &= ~MODIFIER_NUML;
1000 }
1001
1002 xitk_labelbutton_change_label(kbedit->grab, olbl);
1003
1004 xitk_window_destroy_window(gui->imlib_data, xwin);
1005
1006 gui->x_lock_display (gui->display);
1007 XSync(gui->display, False);
1008 gui->x_unlock_display (gui->display);
1009
1010 kbedit->grabbing = 0;
1011
1012 if((redundant = bkedit_check_redundancy(kbedit->kbt, kbe)) == -1) {
1013 char shortcut[32];
1014
1015 kbedit_display_kbinding(xitk_label_get_label(kbedit->comment), kbe);
1016
1017 snprintf(shortcut, sizeof(shortcut), "%c%s%c", '[', _kbindings_get_shortcut_from_kbe(kbe), ']');
1018
1019 /* Ask if user wants to store new shortcut */
1020 xitk_window_dialog_yesno_with_width(gui->imlib_data, _("Accept?"),
1021 kbedit_accept_yes,
1022 kbedit_accept_no,
1023 (void *) kbe, 400, ALIGN_CENTER,
1024 _("Store %s as\n'%s' key binding ?"),
1025 shortcut, kbedit->ksel->comment);
1026 }
1027 else {
1028 /* error, redundant */
1029 if(redundant >= 0) {
1030 xine_error(_("This key binding is redundant with action:\n\"%s\".\n"),
1031 kbedit->kbt->entry[redundant]->comment);
1032 }
1033 }
1034
1035 free(olbl);
1036 xitk_labelbutton_set_state(kbedit->alias, 0);
1037 xitk_labelbutton_set_state(kbedit->edit, 0);
1038 xitk_disable_widget(kbedit->grab);
1039 }
1040
1041 /*
1042 *
1043 */
kbedit_handle_event(XEvent * event,void * data)1044 static void kbedit_handle_event(XEvent *event, void *data) {
1045
1046 switch(event->type) {
1047
1048 case KeyPress:
1049 if(xitk_get_key_pressed(event) == XK_Escape)
1050 kbedit_exit(NULL, NULL);
1051 else
1052 gui_handle_event (event, gGui);
1053 break;
1054
1055 case KeyRelease: {
1056 xitk_widget_t *w;
1057
1058 if(!kbedit || !kbedit->widget_list)
1059 return;
1060
1061 w = xitk_get_focused_widget(kbedit->widget_list);
1062
1063 if((w && (w != kbedit->done) && (w != kbedit->save))
1064 && (xitk_browser_get_current_selected(kbedit->browser) < 0)) {
1065 kbedit_unset();
1066 }
1067 }
1068 break;
1069
1070 case ButtonRelease: {
1071 xitk_widget_t *w;
1072
1073 if(!kbedit || !kbedit->widget_list)
1074 return;
1075
1076 w = xitk_get_focused_widget(kbedit->widget_list);
1077
1078 if((w && (w != kbedit->done) && (w != kbedit->save))
1079 && (xitk_browser_get_current_selected(kbedit->browser) < 0)) {
1080 kbedit_unset();
1081 }
1082
1083 }
1084 break;
1085
1086 }
1087 }
1088
kbedit_reparent(void)1089 void kbedit_reparent(void) {
1090 if(kbedit)
1091 reparent_window((xitk_window_get_window(kbedit->xwin)));
1092 }
1093
1094 /*
1095 *
1096 */
kbedit_window(void)1097 void kbedit_window(void) {
1098 gGui_t *gui = gGui;
1099 int x, y, y1;
1100 GC gc;
1101 xitk_pixmap_t *bg;
1102 xitk_labelbutton_widget_t lb;
1103 xitk_label_widget_t l;
1104 xitk_browser_widget_t br;
1105 xitk_checkbox_widget_t cb;
1106 int btnw = 80;
1107 int fontheight;
1108 xitk_font_t *fs;
1109 xitk_widget_t *w;
1110
1111 x = xine_config_register_num(__xineui_global_xine_instance, "gui.kbedit_x",
1112 80,
1113 CONFIG_NO_DESC,
1114 CONFIG_NO_HELP,
1115 CONFIG_LEVEL_DEB,
1116 CONFIG_NO_CB,
1117 CONFIG_NO_DATA);
1118 y = xine_config_register_num(__xineui_global_xine_instance, "gui.kbedit_y",
1119 80,
1120 CONFIG_NO_DESC,
1121 CONFIG_NO_HELP,
1122 CONFIG_LEVEL_DEB,
1123 CONFIG_NO_CB,
1124 CONFIG_NO_DATA);
1125
1126 kbedit = (_kbedit_t *) calloc(1, sizeof(_kbedit_t));
1127
1128 kbedit->kbt = _kbindings_duplicate_kbindings(gui->kbindings);
1129 kbedit->action_wanted = KBEDIT_NOOP;
1130 kbedit->xwin = xitk_window_create_dialog_window(gui->imlib_data,
1131 _("Key Binding Editor"),
1132 x, y, WINDOW_WIDTH, WINDOW_HEIGHT);
1133 set_window_states_start((xitk_window_get_window(kbedit->xwin)));
1134
1135 gui->x_lock_display (gui->display);
1136 gc = XCreateGC(gui->display,
1137 (xitk_window_get_window(kbedit->xwin)), None, None);
1138 gui->x_unlock_display (gui->display);
1139
1140 kbedit->widget_list = xitk_widget_list_new();
1141
1142 xitk_widget_list_set(kbedit->widget_list,
1143 WIDGET_LIST_WINDOW, (void *) (xitk_window_get_window(kbedit->xwin)));
1144 xitk_widget_list_set(kbedit->widget_list, WIDGET_LIST_GC, gc);
1145
1146 bg = xitk_image_create_xitk_pixmap(gui->imlib_data, WINDOW_WIDTH, WINDOW_HEIGHT);
1147
1148 gui->x_lock_display (gui->display);
1149 XCopyArea(gui->display, (xitk_window_get_background(kbedit->xwin)), bg->pixmap,
1150 bg->gc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0);
1151 gui->x_unlock_display (gui->display);
1152
1153 x = 15;
1154 y = 34;
1155
1156 draw_rectangular_inner_box(gui->imlib_data, bg, x, y,
1157 (WINDOW_WIDTH - 30 - 1), (MAX_DISP_ENTRIES * 20 + 16 + 10 - 1));
1158
1159 y += MAX_DISP_ENTRIES * 20 + 16 + 10 + 30;
1160 y1 = y; /* remember for later */
1161 draw_outter_frame(gui->imlib_data, bg,
1162 _("Binding Action"), hboldfontname,
1163 x, y,
1164 (WINDOW_WIDTH - 30), 45);
1165
1166 y += 45 + 3;
1167 draw_outter_frame(gui->imlib_data, bg,
1168 _("Key"), hboldfontname,
1169 x, y,
1170 120, 45);
1171
1172 draw_outter_frame(gui->imlib_data, bg,
1173 _("Modifiers"), hboldfontname,
1174 x + 130, y,
1175 (WINDOW_WIDTH - (x + 130) - 15), 45);
1176
1177
1178 xitk_window_change_background(gui->imlib_data, kbedit->xwin, bg->pixmap,
1179 WINDOW_WIDTH, WINDOW_HEIGHT);
1180
1181 xitk_image_destroy_xitk_pixmap(bg);
1182
1183 kbedit_create_browser_entries();
1184
1185 y = 34;
1186
1187 XITK_WIDGET_INIT(&br, gui->imlib_data);
1188
1189 br.arrow_up.skin_element_name = NULL;
1190 br.slider.skin_element_name = NULL;
1191 br.arrow_dn.skin_element_name = NULL;
1192 br.browser.skin_element_name = NULL;
1193 br.browser.max_displayed_entries = MAX_DISP_ENTRIES;
1194 br.browser.num_entries = kbedit->num_entries;
1195 br.browser.entries = (const char* const*)kbedit->entries;
1196 br.callback = kbedit_sel;
1197 br.dbl_click_callback = NULL;
1198 br.parent_wlist = kbedit->widget_list;
1199 br.userdata = NULL;
1200 kbedit->browser = xitk_noskin_browser_create (kbedit->widget_list, &br,
1201 (XITK_WIDGET_LIST_GC(kbedit->widget_list)), x + 5, y + 5, WINDOW_WIDTH - (30 + 10 + 16), 20, 16, br_fontname);
1202 xitk_add_widget (kbedit->widget_list, kbedit->browser);
1203 xitk_enable_and_show_widget(kbedit->browser);
1204
1205 xitk_browser_set_alignment(kbedit->browser, ALIGN_LEFT);
1206 xitk_browser_update_list(kbedit->browser,
1207 (const char* const*) kbedit->entries,
1208 (const char* const*) kbedit->shortcuts, kbedit->num_entries, xitk_browser_get_current_start(kbedit->browser));
1209
1210 y = y1 - 30 + 4;
1211
1212 XITK_WIDGET_INIT(&lb, gui->imlib_data);
1213
1214 lb.button_type = RADIO_BUTTON;
1215 lb.label = _("Alias");
1216 lb.align = ALIGN_CENTER;
1217 lb.callback = NULL;
1218 lb.state_callback = kbedit_alias;
1219 lb.userdata = NULL;
1220 lb.skin_element_name = NULL;
1221 kbedit->alias = xitk_noskin_labelbutton_create (kbedit->widget_list, &lb, x, y, btnw, 23,
1222 "Black", "Black", "White", hboldfontname);
1223 xitk_add_widget (kbedit->widget_list, kbedit->alias);
1224 xitk_enable_and_show_widget(kbedit->alias);
1225
1226 x += btnw + 4;
1227
1228 lb.button_type = RADIO_BUTTON;
1229 lb.label = _("Edit");
1230 lb.align = ALIGN_CENTER;
1231 lb.callback = NULL;
1232 lb.state_callback = kbedit_edit;
1233 lb.userdata = NULL;
1234 lb.skin_element_name = NULL;
1235 kbedit->edit = xitk_noskin_labelbutton_create (kbedit->widget_list, &lb, x, y, btnw, 23,
1236 "Black", "Black", "White", hboldfontname);
1237 xitk_add_widget (kbedit->widget_list, kbedit->edit);
1238 xitk_enable_and_show_widget(kbedit->edit);
1239
1240 x += btnw + 4;
1241
1242 lb.button_type = CLICK_BUTTON;
1243 lb.label = _("Delete");
1244 lb.align = ALIGN_CENTER;
1245 lb.callback = kbedit_delete;
1246 lb.state_callback = NULL;
1247 lb.userdata = NULL;
1248 lb.skin_element_name = NULL;
1249 kbedit->delete = xitk_noskin_labelbutton_create (kbedit->widget_list, &lb, x, y, btnw, 23,
1250 "Black", "Black", "White", hboldfontname);
1251 xitk_add_widget (kbedit->widget_list, kbedit->delete);
1252 xitk_enable_and_show_widget(kbedit->delete);
1253
1254 x += btnw + 4;
1255
1256 lb.button_type = CLICK_BUTTON;
1257 lb.label = _("Save");
1258 lb.align = ALIGN_CENTER;
1259 lb.callback = kbedit_save;
1260 lb.state_callback = NULL;
1261 lb.userdata = NULL;
1262 lb.skin_element_name = NULL;
1263 kbedit->save = xitk_noskin_labelbutton_create (kbedit->widget_list, &lb, x, y, btnw, 23,
1264 "Black", "Black", "White", hboldfontname);
1265 xitk_add_widget (kbedit->widget_list, kbedit->save);
1266 xitk_enable_and_show_widget(kbedit->save);
1267
1268 x += btnw + 4;
1269
1270 lb.button_type = CLICK_BUTTON;
1271 lb.label = _("Reset");
1272 lb.align = ALIGN_CENTER;
1273 lb.callback = kbedit_reset;
1274 lb.state_callback = NULL;
1275 lb.userdata = NULL;
1276 lb.skin_element_name = NULL;
1277 w = xitk_noskin_labelbutton_create (kbedit->widget_list, &lb, x, y, btnw, 23,
1278 "Black", "Black", "White", hboldfontname);
1279 xitk_add_widget (kbedit->widget_list, w);
1280 xitk_enable_and_show_widget(w);
1281
1282 x += btnw + 4;
1283
1284 lb.button_type = CLICK_BUTTON;
1285 lb.label = _("Done");
1286 lb.align = ALIGN_CENTER;
1287 lb.callback = kbedit_exit;
1288 lb.state_callback = NULL;
1289 lb.userdata = NULL;
1290 lb.skin_element_name = NULL;
1291 kbedit->done = xitk_noskin_labelbutton_create (kbedit->widget_list, &lb, x, y, btnw, 23,
1292 "Black", "Black", "White", hboldfontname);
1293 xitk_add_widget (kbedit->widget_list, kbedit->done);
1294 xitk_enable_and_show_widget(kbedit->done);
1295
1296 x = 15;
1297
1298 XITK_WIDGET_INIT(&l, gui->imlib_data);
1299
1300 fs = xitk_font_load_font(gui->display, hboldfontname);
1301 xitk_font_set_font(fs, (XITK_WIDGET_LIST_GC(kbedit->widget_list)));
1302 fontheight = xitk_font_get_string_height(fs, " ");
1303 xitk_font_unload_font(fs);
1304
1305 y = y1 + (45 / 2); /* Checkbox */
1306 y1 = y - ((fontheight - 10) / 2); /* Text, v-centered to ckeckbox */
1307
1308 l.window = (XITK_WIDGET_LIST_WINDOW(kbedit->widget_list));
1309 l.gc = (XITK_WIDGET_LIST_GC(kbedit->widget_list));
1310 l.skin_element_name = NULL;
1311 l.label = "Binding Action";
1312 l.callback = NULL;
1313 kbedit->comment = xitk_noskin_label_create (kbedit->widget_list, &l, x + 10, y1,
1314 WINDOW_WIDTH - 50 - 2, fontheight, hboldfontname);
1315 xitk_add_widget (kbedit->widget_list, kbedit->comment);
1316 xitk_enable_and_show_widget(kbedit->comment);
1317
1318 y += 45 + 3;
1319 y1 += 45 + 3;
1320
1321 l.window = (XITK_WIDGET_LIST_WINDOW(kbedit->widget_list));
1322 l.gc = (XITK_WIDGET_LIST_GC(kbedit->widget_list));
1323 l.skin_element_name = NULL;
1324 l.label = "THE Key";
1325 l.callback = NULL;
1326 kbedit->key = xitk_noskin_label_create (kbedit->widget_list, &l, x + 10, y1,
1327 100, fontheight, hboldfontname);
1328 xitk_add_widget (kbedit->widget_list, kbedit->key);
1329 xitk_enable_and_show_widget(kbedit->key);
1330
1331 XITK_WIDGET_INIT(&cb, gui->imlib_data);
1332
1333 x += 130 + 10;
1334
1335 cb.callback = NULL;
1336 cb.userdata = NULL;
1337 cb.skin_element_name = NULL;
1338 kbedit->ctrl = xitk_noskin_checkbox_create (kbedit->widget_list, &cb, x, y, 10, 10);
1339 xitk_add_widget (kbedit->widget_list, kbedit->ctrl);
1340 xitk_show_widget(kbedit->ctrl);
1341 xitk_disable_widget(kbedit->ctrl);
1342
1343
1344 x += 15;
1345
1346 l.window = (XITK_WIDGET_LIST_WINDOW(kbedit->widget_list));
1347 l.gc = (XITK_WIDGET_LIST_GC(kbedit->widget_list));
1348 l.skin_element_name = NULL;
1349 l.label = _("ctrl");
1350 l.callback = NULL;
1351 w = xitk_noskin_label_create (kbedit->widget_list, &l, x, y1, 40, fontheight, hboldfontname);
1352 xitk_add_widget (kbedit->widget_list, w);
1353 xitk_enable_and_show_widget(w);
1354
1355 x += 55;
1356
1357 cb.callback = NULL;
1358 cb.userdata = NULL;
1359 cb.skin_element_name = NULL;
1360 kbedit->meta = xitk_noskin_checkbox_create (kbedit->widget_list, &cb, x, y, 10, 10);
1361 xitk_add_widget (kbedit->widget_list, kbedit->meta);
1362 xitk_show_widget(kbedit->meta);
1363 xitk_disable_widget(kbedit->meta);
1364
1365
1366 x += 15;
1367
1368 l.window = (XITK_WIDGET_LIST_WINDOW(kbedit->widget_list));
1369 l.gc = (XITK_WIDGET_LIST_GC(kbedit->widget_list));
1370 l.skin_element_name = NULL;
1371 l.label = _("meta");
1372 l.callback = NULL;
1373 w = xitk_noskin_label_create (kbedit->widget_list, &l, x, y1, 40, fontheight, hboldfontname);
1374 xitk_add_widget (kbedit->widget_list, w);
1375 xitk_enable_and_show_widget(w);
1376
1377 x += 55;
1378
1379 cb.callback = NULL;
1380 cb.userdata = NULL;
1381 cb.skin_element_name = NULL;
1382 kbedit->mod3 = xitk_noskin_checkbox_create (kbedit->widget_list, &cb, x, y, 10, 10);
1383 xitk_add_widget (kbedit->widget_list, kbedit->mod3);
1384 xitk_show_widget(kbedit->mod3);
1385 xitk_disable_widget(kbedit->mod3);
1386
1387
1388 x += 15;
1389
1390 l.window = (XITK_WIDGET_LIST_WINDOW(kbedit->widget_list));
1391 l.gc = (XITK_WIDGET_LIST_GC(kbedit->widget_list));
1392 l.skin_element_name = NULL;
1393 l.label = _("mod3");
1394 l.callback = NULL;
1395 w = xitk_noskin_label_create (kbedit->widget_list, &l, x, y1, 40, fontheight, hboldfontname);
1396 xitk_add_widget (kbedit->widget_list, w);
1397 xitk_enable_and_show_widget(w);
1398
1399 x += 55;
1400
1401 cb.callback = NULL;
1402 cb.userdata = NULL;
1403 cb.skin_element_name = NULL;
1404 kbedit->mod4 = xitk_noskin_checkbox_create (kbedit->widget_list, &cb, x, y, 10, 10);
1405 xitk_add_widget (kbedit->widget_list, kbedit->mod4);
1406 xitk_show_widget(kbedit->mod4);
1407 xitk_disable_widget(kbedit->mod4);
1408
1409
1410 x += 15;
1411
1412 l.window = (XITK_WIDGET_LIST_WINDOW(kbedit->widget_list));
1413 l.gc = (XITK_WIDGET_LIST_GC(kbedit->widget_list));
1414 l.skin_element_name = NULL;
1415 l.label = _("mod4");
1416 l.callback = NULL;
1417 w = xitk_noskin_label_create (kbedit->widget_list, &l, x, y1, 40, fontheight, hboldfontname);
1418 xitk_add_widget (kbedit->widget_list, w);
1419 xitk_enable_and_show_widget(w);
1420
1421 x += 55;
1422
1423 cb.callback = NULL;
1424 cb.userdata = NULL;
1425 cb.skin_element_name = NULL;
1426 kbedit->mod5 = xitk_noskin_checkbox_create (kbedit->widget_list, &cb, x, y, 10, 10);
1427 xitk_add_widget (kbedit->widget_list, kbedit->mod5);
1428 xitk_show_widget(kbedit->mod5);
1429 xitk_disable_widget(kbedit->mod5);
1430
1431
1432 x += 15;
1433
1434 l.window = (XITK_WIDGET_LIST_WINDOW(kbedit->widget_list));
1435 l.gc = (XITK_WIDGET_LIST_GC(kbedit->widget_list));
1436 l.skin_element_name = NULL;
1437 l.label = _("mod5");
1438 l.callback = NULL;
1439 w = xitk_noskin_label_create (kbedit->widget_list, &l, x, y1, 40, fontheight, hboldfontname);
1440 xitk_add_widget (kbedit->widget_list, w);
1441 xitk_enable_and_show_widget(w);
1442
1443 x = 15;
1444 y = WINDOW_HEIGHT - (23 + 15);
1445
1446 lb.button_type = CLICK_BUTTON;
1447 lb.label = _("Grab");
1448 lb.align = ALIGN_CENTER;
1449 lb.callback = kbedit_grab;
1450 lb.state_callback = NULL;
1451 lb.userdata = NULL;
1452 lb.skin_element_name = NULL;
1453 kbedit->grab = xitk_noskin_labelbutton_create (kbedit->widget_list, &lb, x, y, WINDOW_WIDTH - 30, 23,
1454 "Black", "Black", "White", hboldfontname);
1455 xitk_add_widget (kbedit->widget_list, kbedit->grab);
1456 xitk_enable_and_show_widget(kbedit->grab);
1457
1458 kbedit_unset();
1459
1460 kbedit->kreg = xitk_register_event_handler("kbedit",
1461 (xitk_window_get_window(kbedit->xwin)),
1462 kbedit_handle_event,
1463 NULL,
1464 NULL,
1465 kbedit->widget_list,
1466 NULL);
1467
1468
1469 gui->ssaver_enabled = 0;
1470 kbedit->visible = 1;
1471 kbedit->running = 1;
1472 kbedit_raise_window();
1473
1474 try_to_set_input_focus(xitk_window_get_window(kbedit->xwin));
1475 }
1476
1477