WPrefs: add new mouse actions configuration
[wmaker-crm.git] / WPrefs.app / MouseSettings.c
blob0ef5f35c1e1387949b1668892aa2c322fc8bb579
2 /* MouseSettings.c- mouse options (some are equivalent to xset)
4 * WPrefs - Window Maker Preferences Program
6 * Copyright (c) 1998-2003 Alfredo K. Kojima
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "WPrefs.h"
25 #include <X11/Xutil.h>
26 #include <X11/XKBlib.h>
28 #include <unistd.h>
29 #include <math.h>
32 #define XSET "xset"
34 typedef struct _Panel {
35 WMBox *box;
37 char *sectionName;
39 char *description;
41 CallbackRec callbacks;
43 WMWidget *parent;
45 WMFrame *speedF;
46 WMLabel *speedL;
47 WMSlider *speedS;
48 WMLabel *acceL;
49 WMTextField *acceT;
50 WMLabel *threL;
51 WMTextField *threT;
53 WMFrame *ddelaF;
54 WMButton *ddelaB[5];
55 WMTextField *ddelaT;
56 WMLabel *ddelaL;
57 DoubleTest *tester;
59 WMFrame *menuF;
60 WMLabel *button1L;
61 WMLabel *button2L;
62 WMLabel *button3L;
63 WMLabel *button8L;
64 WMLabel *button9L;
65 WMLabel *wheelL;
66 WMLabel *wheelTiltL;
67 WMPopUpButton *button1P;
68 WMPopUpButton *button2P;
69 WMPopUpButton *button3P;
70 WMPopUpButton *button8P;
71 WMPopUpButton *button9P;
72 WMPopUpButton *wheelP;
73 WMPopUpButton *wheelTiltP;
75 WMButton *disaB;
77 WMFrame *grabF;
78 WMPopUpButton *grabP;
80 /**/ int maxThreshold;
81 float acceleration;
82 } _Panel;
84 #define ICON_FILE "mousesettings"
86 #define SPEED_ICON_FILE "mousespeed"
88 #define DELAY_ICON "timer%i"
89 #define DELAY_ICON_S "timer%is"
91 /* need access to the double click variables */
92 #include <WINGs/WINGsP.h>
94 static char *modifierNames[8];
96 static char *buttonActions[8];
98 static char *wheelActions[3];
100 #define DELAY(i) ((i)*75+170)
103 static void setMouseAccel(WMScreen * scr, float accel, int threshold)
105 int n, d;
107 d = 10;
108 n = accel * d;
110 XChangePointerControl(WMScreenDisplay(scr), True, True, n, d, threshold);
113 static void speedChange(WMWidget * w, void *data)
115 _Panel *panel = (_Panel *) data;
116 int i;
117 char buffer[64];
118 int threshold;
119 char *tmp;
121 if (w == NULL) {
122 float accel;
124 tmp = WMGetTextFieldText(panel->acceT);
125 if (sscanf(tmp, "%f", &accel) != 1 || accel < 0) {
126 WMRunAlertPanel(WMWidgetScreen(panel->acceT), GetWindow(),
127 _("Error"),
128 _("Invalid mouse acceleration value. Must be a positive real value."),
129 _("OK"), NULL, NULL);
130 wfree(tmp);
131 return;
133 panel->acceleration = accel;
134 wfree(tmp);
135 } else {
136 i = (int)WMGetSliderValue(panel->speedS);
138 panel->acceleration = 0.25 + (i * 0.25);
140 sprintf(buffer, "%.2f", 0.25 + (i * 0.25));
141 WMSetTextFieldText(panel->acceT, buffer);
144 tmp = WMGetTextFieldText(panel->threT);
145 if (sscanf(tmp, "%i", &threshold) != 1 || threshold < 0 || threshold > panel->maxThreshold) {
146 WMRunAlertPanel(WMWidgetScreen(panel->parent), GetWindow(), _("Error"),
148 ("Invalid mouse acceleration threshold value. Must be the number of pixels to travel before accelerating."),
149 _("OK"), NULL, NULL);
150 } else {
151 setMouseAccel(WMWidgetScreen(panel->parent), panel->acceleration, threshold);
153 wfree(tmp);
156 static void returnPressed(void *observerData, WMNotification * notification)
158 _Panel *panel = (_Panel *) observerData;
160 /* Parameter not used, but tell the compiler that it is ok */
161 (void) notification;
163 speedChange(NULL, panel);
166 static void doubleClick(WMWidget * w, void *data)
168 _Panel *panel = (_Panel *) data;
169 int i;
170 char buffer[32];
172 for (i = 0; i < 5; i++) {
173 if (panel->ddelaB[i] == w)
174 break;
176 WINGsConfiguration.doubleClickDelay = DELAY(i);
178 sprintf(buffer, "%i", DELAY(i));
179 WMSetTextFieldText(panel->ddelaT, buffer);
182 static int getButtonAction(const char *str)
184 if (!str)
185 return -2;
187 if (strcasecmp(str, "None") == 0)
188 return 0;
189 else if (strcasecmp(str, "OpenApplicationsMenu") == 0)
190 return 1;
191 else if (strcasecmp(str, "OpenWindowListMenu") == 0)
192 return 2;
193 else if (strcasecmp(str, "SelectWindows") == 0)
194 return 3;
195 else if (strcasecmp(str, "MoveToPrevWorkspace") == 0)
196 return 4;
197 else if (strcasecmp(str, "MoveToNextWorkspace") == 0)
198 return 5;
199 else if (strcasecmp(str, "MoveToPrevWindow") == 0)
200 return 6;
201 else if (strcasecmp(str, "MoveToNextWindow") == 0)
202 return 7;
203 else
204 return -1;
208 static int getWheelAction(const char *str)
210 if (!str)
211 return -2;
213 if (strcasecmp(str, "None") == 0)
214 return 0;
215 else if (strcasecmp(str, "SwitchWorkspaces") == 0)
216 return 1;
217 else if (strcasecmp(str, "SwitchWindows") == 0)
218 return 2;
219 else
220 return -1;
224 static void getMouseParameters(Display * dpy, float *accel, int *thre)
226 int n, d;
228 XGetPointerControl(dpy, &n, &d, thre);
230 *accel = (float)n / (float)d;
233 static void showData(_Panel * panel)
235 char *str;
236 int i;
237 int a = -1, b = -1, c = -1, w = -1;
238 float accel;
239 char buffer[32];
240 Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->parent));
242 str = GetStringForKey("MouseLeftButtonAction");
243 i = getButtonAction(str);
244 if (i < 0) {
245 a = 3;
246 if (i == -1) {
247 wwarning(_("bad value %s for option %s"), str, "MouseLeftButtonAction");
249 } else {
250 a = i;
252 WMSetPopUpButtonSelectedItem(panel->button1P, a);
254 str = GetStringForKey("MouseMiddleButtonAction");
255 i = getButtonAction(str);
256 if (i < 0) {
257 b = 2;
258 if (i == -1) {
259 wwarning(_("bad value %s for option %s"), str, "MouseMiddleButtonAction");
261 } else {
262 b = i;
264 WMSetPopUpButtonSelectedItem(panel->button2P, b);
266 str = GetStringForKey("MouseRightButtonAction");
267 i = getButtonAction(str);
268 if (i < 0) {
269 c = 1;
270 if (i == -1) {
271 wwarning(_("bad value %s for option %s"), str, "MouseRightButtonAction");
273 } else {
274 c = i;
276 WMSetPopUpButtonSelectedItem(panel->button3P, c);
278 str = GetStringForKey("MouseBackwardButtonAction");
279 i = getButtonAction(str);
280 if (i < 0) {
281 b = 0;
282 if (i == -1) {
283 wwarning(_("bad value %s for option %s"), str, "MouseBackwardButtonAction");
285 } else {
286 b = i;
288 WMSetPopUpButtonSelectedItem(panel->button8P, b);
290 str = GetStringForKey("MouseForwardButtonAction");
291 i = getButtonAction(str);
292 if (i < 0) {
293 b = 0;
294 if (i == -1) {
295 wwarning(_("bad value %s for option %s"), str, "MouseForwardButtonAction");
297 } else {
298 b = i;
300 WMSetPopUpButtonSelectedItem(panel->button9P, b);
302 str = GetStringForKey("MouseWheelAction");
303 i = getWheelAction(str);
304 if (i < 0) {
305 w = 0;
306 if (i == -1) {
307 wwarning(_("bad value %s for option %s"), str, "MouseWheelAction");
309 } else {
310 w = i;
312 WMSetPopUpButtonSelectedItem(panel->wheelP, w);
314 str = GetStringForKey("MouseWheelTiltAction");
315 i = getWheelAction(str);
316 if (i < 0) {
317 w = 0;
318 if (i == -1) {
319 wwarning(_("bad value %s for option %s"), str, "MouseWheelTiltAction");
321 } else {
322 w = i;
324 WMSetPopUpButtonSelectedItem(panel->wheelTiltP, w);
326 WMSetButtonSelected(panel->disaB, GetBoolForKey("DisableWSMouseActions"));
328 /**/ getMouseParameters(dpy, &accel, &a);
329 panel->maxThreshold = WidthOfScreen(DefaultScreenOfDisplay(dpy));
330 if (a > panel->maxThreshold) {
331 panel->maxThreshold = a;
333 sprintf(buffer, "%i", a);
334 WMSetTextFieldText(panel->threT, buffer);
336 WMSetSliderValue(panel->speedS, (accel - 0.25) / 0.25);
338 panel->acceleration = accel;
339 sprintf(buffer, "%.2f", accel);
340 WMSetTextFieldText(panel->acceT, buffer);
342 /**/ b = GetIntegerForKey("DoubleClickTime");
343 /* find best match */
344 a = -1;
345 for (i = 0; i < 5; i++) {
346 if (DELAY(i) == b)
347 a = i;
349 if (a >= 0)
350 WMPerformButtonClick(panel->ddelaB[a]);
351 sprintf(buffer, "%i", b);
352 WMSetTextFieldText(panel->ddelaT, buffer);
354 /**/ str = GetStringForKey("ModifierKey");
355 if (!str)
356 str = "mod1";
357 a = ModifierFromKey(dpy, str);
359 if (a != -1) {
360 str = modifierNames[a];
362 a = 0;
363 for (i = 0; i < WMGetPopUpButtonNumberOfItems(panel->grabP); i++) {
364 if (strstr(WMGetPopUpButtonItem(panel->grabP, i), str)) {
365 WMSetPopUpButtonSelectedItem(panel->grabP, i);
366 a = 1;
367 break;
372 if (a < 1) {
373 char *previous;
375 previous = WMGetPopUpButtonItem(panel->grabP, 0);
376 if (previous != NULL)
377 WMSetPopUpButtonSelectedItem(panel->grabP, 0);
378 wwarning(_("modifier key %s for option ModifierKey was not recognized. Using %s as default"),
379 str, previous?previous:"(empty)");
383 static void fillModifierPopUp(WMPopUpButton * pop)
385 XModifierKeymap *mapping;
386 Display *dpy = WMScreenDisplay(WMWidgetScreen(pop));
387 int i, j;
388 char *str;
389 char buffer[64];
391 mapping = XGetModifierMapping(dpy);
393 if (!mapping || mapping->max_keypermod == 0) {
394 WMAddPopUpButtonItem(pop, "Mod1");
395 WMAddPopUpButtonItem(pop, "Mod2");
396 WMAddPopUpButtonItem(pop, "Mod3");
397 WMAddPopUpButtonItem(pop, "Mod4");
398 WMAddPopUpButtonItem(pop, "Mod5");
399 wwarning(_("could not retrieve keyboard modifier mapping"));
400 return;
403 for (j = 0; j < 8; j++) {
404 int idx;
405 char *array[8];
406 int a;
407 KeySym ksym;
408 int k;
409 char *ptr;
410 char *tmp;
412 a = 0;
413 memset(array, 0, sizeof(char *) * 8);
414 for (i = 0; i < mapping->max_keypermod; i++) {
415 idx = i + j * mapping->max_keypermod;
416 if (mapping->modifiermap[idx] != 0) {
417 int l;
418 for (l = 0; l < 4; l++) {
419 if (xext_xkb_supported)
420 ksym = XkbKeycodeToKeysym(dpy, mapping->modifiermap[idx], 0, l);
421 else
422 ksym = XKeycodeToKeysym(dpy, mapping->modifiermap[idx], 0);
423 if (ksym != NoSymbol)
424 break;
426 if (ksym != NoSymbol)
427 str = XKeysymToString(ksym);
428 else
429 str = NULL;
430 if (str && !strstr(str, "_Lock") && !strstr(str, "Shift")
431 && !strstr(str, "Control")) {
432 array[a++] = wstrdup(str);
437 for (k = 0; k < a; k++) {
438 if (array[k] == NULL)
439 continue;
440 tmp = wstrdup(array[k]);
441 ptr = strstr(tmp, "_L");
442 if (ptr)
443 *ptr = 0;
444 ptr = strstr(tmp, "_R");
445 if (ptr)
446 *ptr = 0;
447 sprintf(buffer, "%s (%s)", modifierNames[j], tmp);
448 /*sprintf(buffer, "%s", tmp); */
449 WMAddPopUpButtonItem(pop, buffer);
450 for (i = k + 1; i < a; i++) {
451 if (array[i] == NULL)
452 continue;
453 if (strstr(array[i], tmp)) {
454 wfree(array[i]);
455 array[i] = NULL;
456 break;
459 wfree(tmp);
462 while (--a > 0) {
463 if (array[a])
464 wfree(array[a]);
468 if (mapping)
469 XFreeModifiermap(mapping);
472 static void createPanel(Panel * p)
474 _Panel *panel = (_Panel *) p;
475 WMScreen *scr = WMWidgetScreen(panel->parent);
476 WMPixmap *icon;
477 char *buf1, *buf2;
478 int i;
479 RColor color;
480 char *path;
482 color.red = 0xae;
483 color.green = 0xaa;
484 color.blue = 0xae;
486 panel->box = WMCreateBox(panel->parent);
487 WMSetViewExpandsToParent(WMWidgetView(panel->box), 2, 2, 2, 2);
489 /**************** Mouse Speed ****************/
490 panel->speedF = WMCreateFrame(panel->box);
491 WMResizeWidget(panel->speedF, 225, 90);
492 WMMoveWidget(panel->speedF, 15, 5);
493 WMSetFrameTitle(panel->speedF, _("Mouse Speed"));
495 panel->speedL = WMCreateLabel(panel->speedF);
496 WMResizeWidget(panel->speedL, 40, 46);
497 WMMoveWidget(panel->speedL, 10, 14);
498 WMSetLabelImagePosition(panel->speedL, WIPImageOnly);
499 path = LocateImage(SPEED_ICON_FILE);
500 if (path) {
501 icon = WMCreateBlendedPixmapFromFile(scr, path, &color);
502 if (icon) {
503 WMSetLabelImage(panel->speedL, icon);
504 WMReleasePixmap(icon);
505 } else {
506 wwarning(_("could not load icon %s"), path);
508 wfree(path);
511 panel->speedS = WMCreateSlider(panel->speedF);
512 WMResizeWidget(panel->speedS, 150, 15);
513 WMMoveWidget(panel->speedS, 60, 35);
514 WMSetSliderMinValue(panel->speedS, 0);
515 WMSetSliderMaxValue(panel->speedS, 40);
516 WMSetSliderContinuous(panel->speedS, False);
517 WMSetSliderAction(panel->speedS, speedChange, panel);
519 panel->acceL = WMCreateLabel(panel->speedF);
520 WMResizeWidget(panel->acceL, 50, 16);
521 WMMoveWidget(panel->acceL, 10, 65);
522 WMSetLabelTextAlignment(panel->acceL, WARight);
523 WMSetLabelText(panel->acceL, _("Accel.:"));
525 panel->acceT = WMCreateTextField(panel->speedF);
526 WMResizeWidget(panel->acceT, 40, 20);
527 WMMoveWidget(panel->acceT, 60, 63);
528 WMAddNotificationObserver(returnPressed, panel, WMTextDidEndEditingNotification, panel->acceT);
530 panel->threL = WMCreateLabel(panel->speedF);
531 WMResizeWidget(panel->threL, 80, 16);
532 WMMoveWidget(panel->threL, 100, 65);
533 WMSetLabelTextAlignment(panel->threL, WARight);
534 WMSetLabelText(panel->threL, _("Threshold:"));
536 panel->threT = WMCreateTextField(panel->speedF);
537 WMResizeWidget(panel->threT, 30, 20);
538 WMMoveWidget(panel->threT, 180, 63);
539 WMAddNotificationObserver(returnPressed, panel, WMTextDidEndEditingNotification, panel->threT);
541 WMMapSubwidgets(panel->speedF);
543 /* ************** Grab Modifier **************** */
544 panel->grabF = WMCreateFrame(panel->box);
545 WMResizeWidget(panel->grabF, 225, 45);
546 WMMoveWidget(panel->grabF, 15, 95);
547 WMSetFrameTitle(panel->grabF, _("Mouse Grab Modifier"));
549 WMSetBalloonTextForView(_("Keyboard modifier to use for actions that\n"
550 "involve dragging windows with the mouse,\n"
551 "clicking inside the window."), WMWidgetView(panel->grabF));
553 panel->grabP = WMCreatePopUpButton(panel->grabF);
554 WMResizeWidget(panel->grabP, 160, 20);
555 WMMoveWidget(panel->grabP, 50, 18);
557 fillModifierPopUp(panel->grabP);
558 WMMapSubwidgets(panel->grabF);
560 /***************** Doubleclick Delay ****************/
562 panel->ddelaF = WMCreateFrame(panel->box);
563 WMResizeWidget(panel->ddelaF, 225, 87);
564 WMMoveWidget(panel->ddelaF, 15, 140);
565 WMSetFrameTitle(panel->ddelaF, _("Double-Click Delay"));
567 buf1 = wmalloc(strlen(DELAY_ICON) + 2);
568 buf2 = wmalloc(strlen(DELAY_ICON_S) + 2);
570 for (i = 0; i < 5; i++) {
571 panel->ddelaB[i] = WMCreateCustomButton(panel->ddelaF, WBBStateChangeMask);
572 WMResizeWidget(panel->ddelaB[i], 25, 25);
573 WMMoveWidget(panel->ddelaB[i], 20 + (40 * i), 20);
574 WMSetButtonBordered(panel->ddelaB[i], False);
575 WMSetButtonImagePosition(panel->ddelaB[i], WIPImageOnly);
576 WMSetButtonAction(panel->ddelaB[i], doubleClick, panel);
577 if (i > 0) {
578 WMGroupButtons(panel->ddelaB[0], panel->ddelaB[i]);
580 sprintf(buf1, DELAY_ICON, i + 1);
581 sprintf(buf2, DELAY_ICON_S, i + 1);
582 path = LocateImage(buf1);
583 if (path) {
584 icon = WMCreatePixmapFromFile(scr, path);
585 if (icon) {
586 WMSetButtonImage(panel->ddelaB[i], icon);
587 WMReleasePixmap(icon);
588 } else {
589 wwarning(_("could not load icon file %s"), path);
591 wfree(path);
593 path = LocateImage(buf2);
594 if (path) {
595 icon = WMCreatePixmapFromFile(scr, path);
596 if (icon) {
597 WMSetButtonAltImage(panel->ddelaB[i], icon);
598 WMReleasePixmap(icon);
599 } else {
600 wwarning(_("could not load icon file %s"), path);
602 wfree(path);
605 wfree(buf1);
606 wfree(buf2);
608 panel->tester = CreateDoubleTest(panel->ddelaF, _("Test"));
609 WMResizeWidget(panel->tester, 84, 29);
610 WMMoveWidget(panel->tester, 25, 52);
612 panel->ddelaT = WMCreateTextField(panel->ddelaF);
613 WMResizeWidget(panel->ddelaT, 40, 20);
614 WMMoveWidget(panel->ddelaT, 130, 57);
616 panel->ddelaL = WMCreateLabel(panel->ddelaF);
617 WMResizeWidget(panel->ddelaL, 40, 16);
618 WMMoveWidget(panel->ddelaL, 175, 63);
620 WMFont *font;
621 WMColor *color;
623 font = WMSystemFontOfSize(scr, 10);
624 color = WMDarkGrayColor(scr);
625 WMSetLabelTextColor(panel->ddelaL, color);
626 WMSetLabelFont(panel->ddelaL, font);
627 WMReleaseFont(font);
628 WMReleaseColor(color);
630 WMSetLabelText(panel->ddelaL, _("msec"));
632 WMMapSubwidgets(panel->ddelaF);
634 /* ************** Workspace Action Buttons **************** */
636 panel->menuF = WMCreateFrame(panel->box);
637 WMResizeWidget(panel->menuF, 260, 222);
638 WMMoveWidget(panel->menuF, 250, 5);
639 WMSetFrameTitle(panel->menuF, _("Workspace Mouse Actions"));
641 panel->disaB = WMCreateSwitchButton(panel->menuF);
642 WMResizeWidget(panel->disaB, 205, 18);
643 WMMoveWidget(panel->disaB, 10, 15);
644 WMSetButtonText(panel->disaB, _("Disable mouse actions"));
646 panel->button1L = WMCreateLabel(panel->menuF);
647 WMResizeWidget(panel->button1L, 107, 20);
648 WMMoveWidget(panel->button1L, 5, 40);
649 WMSetLabelTextAlignment(panel->button1L, WARight);
650 WMSetLabelText(panel->button1L, _("Left Button"));
652 panel->button1P = WMCreatePopUpButton(panel->menuF);
653 WMResizeWidget(panel->button1P, 135, 20);
654 WMMoveWidget(panel->button1P, 115, 40);
656 panel->button2L = WMCreateLabel(panel->menuF);
657 WMResizeWidget(panel->button2L, 107, 20);
658 WMMoveWidget(panel->button2L, 5, 65);
659 WMSetLabelTextAlignment(panel->button2L, WARight);
660 WMSetLabelText(panel->button2L, _("Middle Button"));
662 panel->button2P = WMCreatePopUpButton(panel->menuF);
663 WMResizeWidget(panel->button2P, 135, 20);
664 WMMoveWidget(panel->button2P, 115, 65);
666 panel->button3L = WMCreateLabel(panel->menuF);
667 WMResizeWidget(panel->button3L, 107, 20);
668 WMMoveWidget(panel->button3L, 5, 90);
669 WMSetLabelTextAlignment(panel->button3L, WARight);
670 WMSetLabelText(panel->button3L, _("Right Button"));
672 panel->button3P = WMCreatePopUpButton(panel->menuF);
673 WMResizeWidget(panel->button3P, 135, 20);
674 WMMoveWidget(panel->button3P, 115, 90);
676 panel->button8L = WMCreateLabel(panel->menuF);
677 WMResizeWidget(panel->button8L, 107, 20);
678 WMMoveWidget(panel->button8L, 5, 115);
679 WMSetLabelTextAlignment(panel->button8L, WARight);
680 WMSetLabelText(panel->button8L, _("Back Button"));
682 panel->button8P = WMCreatePopUpButton(panel->menuF);
683 WMResizeWidget(panel->button8P, 135, 20);
684 WMMoveWidget(panel->button8P, 115, 115);
686 panel->button9L = WMCreateLabel(panel->menuF);
687 WMResizeWidget(panel->button9L, 107, 20);
688 WMMoveWidget(panel->button9L, 5, 140);
689 WMSetLabelTextAlignment(panel->button9L, WARight);
690 WMSetLabelText(panel->button9L, _("Forward Button"));
692 panel->button9P = WMCreatePopUpButton(panel->menuF);
693 WMResizeWidget(panel->button9P, 135, 20);
694 WMMoveWidget(panel->button9P, 115, 140);
696 panel->wheelL = WMCreateLabel(panel->menuF);
697 WMResizeWidget(panel->wheelL, 107, 20);
698 WMMoveWidget(panel->wheelL, 5, 165);
699 WMSetLabelTextAlignment(panel->wheelL, WARight);
700 WMSetLabelText(panel->wheelL, _("Mouse Wheel"));
702 panel->wheelP = WMCreatePopUpButton(panel->menuF);
703 WMResizeWidget(panel->wheelP, 135, 20);
704 WMMoveWidget(panel->wheelP, 115, 165);
706 panel->wheelTiltL = WMCreateLabel(panel->menuF);
707 WMResizeWidget(panel->wheelTiltL, 107, 20);
708 WMMoveWidget(panel->wheelTiltL, 5, 190);
709 WMSetLabelTextAlignment(panel->wheelTiltL, WARight);
710 WMSetLabelText(panel->wheelTiltL, _("Mouse Wheel Tilt"));
712 panel->wheelTiltP = WMCreatePopUpButton(panel->menuF);
713 WMResizeWidget(panel->wheelTiltP, 135, 20);
714 WMMoveWidget(panel->wheelTiltP, 115, 190);
716 for (i = 0; i < wlengthof(buttonActions); i++) {
717 WMAddPopUpButtonItem(panel->button1P, buttonActions[i]);
718 WMAddPopUpButtonItem(panel->button2P, buttonActions[i]);
719 WMAddPopUpButtonItem(panel->button3P, buttonActions[i]);
720 WMAddPopUpButtonItem(panel->button8P, buttonActions[i]);
721 WMAddPopUpButtonItem(panel->button9P, buttonActions[i]);
724 for (i = 0; i < wlengthof(wheelActions); i++) {
725 WMAddPopUpButtonItem(panel->wheelP, wheelActions[i]);
726 WMAddPopUpButtonItem(panel->wheelTiltP, wheelActions[i]);
729 WMMapSubwidgets(panel->menuF);
731 WMRealizeWidget(panel->box);
732 WMMapSubwidgets(panel->box);
734 showData(panel);
737 static void storeCommandInScript(const char *cmd, const char *line)
739 char *path;
740 FILE *f;
741 char buffer[128];
743 path = wstrconcat(wusergnusteppath(), "/Library/WindowMaker/autostart");
745 f = fopen(path, "rb");
746 if (!f) {
747 f = fopen(path, "wb");
748 if (!f) {
749 werror(_("could not create %s"), path);
750 goto end;
752 fprintf(f, "#!/bin/sh\n");
753 fputs(line, f);
754 fputs("\n", f);
755 } else {
756 int len = strlen(cmd);
757 int ok = 0;
758 char *tmppath;
759 FILE *fo;
761 tmppath = wstrconcat(wusergnusteppath(), "/Library/WindowMaker/autostart.tmp");
762 fo = fopen(tmppath, "wb");
763 if (!fo) {
764 werror(_("could not create temporary file %s"), tmppath);
765 wfree(tmppath);
766 goto end;
769 while (!feof(f)) {
770 if (!fgets(buffer, 127, f)) {
771 break;
773 if (buffer[0] == '\n') {
774 /* don't write empty lines, else the file will grow
775 * indefinitely (one '\n' added at end of file on each save).
777 continue;
779 if (strncmp(buffer, cmd, len) == 0) {
780 if (!ok) {
781 fputs(line, fo);
782 fputs("\n", fo);
783 ok = 1;
785 } else {
786 fputs(buffer, fo);
789 if (!ok) {
790 fputs(line, fo);
791 fputs("\n", fo);
793 fsync(fileno(fo));
794 fclose(fo);
796 if (rename(tmppath, path) != 0) {
797 werror(_("could not rename file %s to %s"), tmppath, path);
799 wfree(tmppath);
801 sprintf(buffer, "chmod u+x %s", path);
802 if (system(buffer) == -1)
803 werror(_("could not execute command \"%s\""), buffer);
805 end:
806 wfree(path);
807 if (f) {
808 fsync(fileno(f)); /* this may be rw */
809 fclose(f);
813 static void storeData(_Panel * panel)
815 char buffer[64];
816 int i;
817 char *tmp, *p;
818 static char *button[8] = { "None", "OpenApplicationsMenu", "OpenWindowListMenu", "SelectWindows",
819 "MoveToPrevWorkspace", "MoveToNextWorkspace", "MoveToPrevWindow", "MoveToNextWindow" };
820 static char *wheel[3] = { "None", "SwitchWorkspaces", "SwitchWindows" };
821 WMUserDefaults *udb = WMGetStandardUserDefaults();
823 if (!WMGetUDBoolForKey(udb, "NoXSetStuff")) {
824 tmp = WMGetTextFieldText(panel->threT);
825 if (strlen(tmp) == 0) {
826 wfree(tmp);
827 tmp = wstrdup("4");
830 sprintf(buffer, XSET " m %i/%i %s\n", (int)(panel->acceleration * 10), 10, tmp);
831 storeCommandInScript(XSET " m", buffer);
833 wfree(tmp);
836 tmp = WMGetTextFieldText(panel->ddelaT);
837 if (sscanf(tmp, "%i", &i) == 1 && i > 0)
838 SetIntegerForKey(i, "DoubleClickTime");
839 wfree(tmp);
841 SetBoolForKey(WMGetButtonSelected(panel->disaB), "DisableWSMouseActions");
843 i = WMGetPopUpButtonSelectedItem(panel->button1P);
844 SetStringForKey(button[i], "MouseLeftButtonAction");
846 i = WMGetPopUpButtonSelectedItem(panel->button2P);
847 SetStringForKey(button[i], "MouseMiddleButtonAction");
849 i = WMGetPopUpButtonSelectedItem(panel->button3P);
850 SetStringForKey(button[i], "MouseRightButtonAction");
852 i = WMGetPopUpButtonSelectedItem(panel->button8P);
853 SetStringForKey(button[i], "MouseBackwardButtonAction");
855 i = WMGetPopUpButtonSelectedItem(panel->button9P);
856 SetStringForKey(button[i], "MouseForwardButtonAction");
858 i = WMGetPopUpButtonSelectedItem(panel->wheelP);
859 SetStringForKey(wheel[i], "MouseWheelAction");
861 i = WMGetPopUpButtonSelectedItem(panel->wheelTiltP);
862 SetStringForKey(wheel[i], "MouseWheelTiltAction");
864 tmp = WMGetPopUpButtonItem(panel->grabP, WMGetPopUpButtonSelectedItem(panel->grabP));
865 tmp = wstrdup(tmp);
866 p = strchr(tmp, ' ');
867 if (p != NULL)
868 *p = '\0';
870 SetStringForKey(tmp, "ModifierKey");
872 wfree(tmp);
875 Panel *InitMouseSettings(WMWidget *parent)
877 _Panel *panel;
879 modifierNames[0] = wstrdup(_("Shift"));
880 modifierNames[1] = wstrdup(_("Lock"));
881 modifierNames[2] = wstrdup(_("Control"));
882 modifierNames[3] = wstrdup(_("Mod1"));
883 modifierNames[4] = wstrdup(_("Mod2"));
884 modifierNames[5] = wstrdup(_("Mod3"));
885 modifierNames[6] = wstrdup(_("Mod4"));
886 modifierNames[7] = wstrdup(_("Mod5"));
888 buttonActions[0] = wstrdup(_("None"));
889 buttonActions[1] = wstrdup(_("Applications Menu"));
890 buttonActions[2] = wstrdup(_("Window List Menu"));
891 buttonActions[3] = wstrdup(_("Select Windows"));
892 buttonActions[4] = wstrdup(_("Previous Workspace"));
893 buttonActions[5] = wstrdup(_("Next Workspace"));
894 buttonActions[6] = wstrdup(_("Previous Window"));
895 buttonActions[7] = wstrdup(_("Next Window"));
897 wheelActions[0] = wstrdup(_("None"));
898 wheelActions[1] = wstrdup(_("Switch Workspaces"));
899 wheelActions[2] = wstrdup(_("Switch Windows"));
901 panel = wmalloc(sizeof(_Panel));
903 panel->sectionName = _("Mouse Preferences");
905 panel->description = _("Mouse speed/acceleration, double click delay,\n" "mouse button bindings etc.");
907 panel->parent = parent;
909 panel->callbacks.createWidgets = createPanel;
910 panel->callbacks.updateDomain = storeData;
912 AddSection(panel, ICON_FILE);
914 return panel;