2 /* MouseSettings.c- mouse options (some are equivalent to xset)
4 * WPrefs - Window Maker Preferences Program
6 * Copyright (c) 1998 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
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
27 #include <X11/Xutil.h>
31 /* double-click tester */
40 typedef struct _Panel
{
47 CallbackRec callbacks
;
84 #define ICON_FILE "mousesettings"
86 #define SPEED_ICON_FILE "mousespeed"
88 #define DELAY_ICON "timer%i"
89 #define DELAY_ICON_S "timer%is"
92 /* need access to the double click variables */
93 #include <WINGs/WINGsP.h>
97 static char *modifierNames
[8];
100 static char *buttonNames
[6];
103 #define DELAY(i) ((i)*75+170)
106 int ModifierFromKey(Display
*dpy
, char *key
);
110 setMouseAccel(WMScreen
*scr
, float accel
, int threshold
)
117 XChangePointerControl(WMScreenDisplay(scr
), True
, True
, n
, d
, threshold
);
122 speedChange(WMWidget
*w
, void *data
)
124 _Panel
*panel
= (_Panel
*)data
;
133 tmp
= WMGetTextFieldText(panel
->acceT
);
134 if (sscanf(tmp
, "%f", &accel
)!=1 || accel
< 0) {
135 WMRunAlertPanel(WMWidgetScreen(panel
->acceT
), GetWindow(panel
),
137 _("Invalid mouse acceleration value. Must be a positive real value."),
138 _("OK"), NULL
, NULL
);
142 panel
->acceleration
= accel
;
145 i
= (int)WMGetSliderValue(panel
->speedS
);
147 panel
->acceleration
= 0.25+(i
*0.25);
149 sprintf(buffer
, "%.2f", 0.25+(i
*0.25));
150 WMSetTextFieldText(panel
->acceT
, buffer
);
153 tmp
= WMGetTextFieldText(panel
->threT
);
154 if (sscanf(tmp
, "%i", &threshold
)!=1 || threshold
< 0
155 || threshold
> panel
->maxThreshold
) {
156 WMRunAlertPanel(WMWidgetScreen(panel
->parent
), GetWindow(panel
), _("Error"),
157 _("Invalid mouse acceleration threshold value. Must be the number of pixels to travel before accelerating."),
158 _("OK"), NULL
, NULL
);
160 setMouseAccel(WMWidgetScreen(panel
->parent
), panel
->acceleration
,
168 returnPressed(void *observerData
, WMNotification
*notification
)
170 _Panel
*panel
= (_Panel
*)observerData
;
172 speedChange(NULL
, panel
);
177 doubleClick(WMWidget
*w
, void *data
)
179 _Panel
*panel
= (_Panel
*)data
;
181 extern _WINGsConfiguration WINGsConfiguration
;
184 for (i
=0; i
<5; i
++) {
185 if (panel
->ddelaB
[i
]==w
)
188 WINGsConfiguration
.doubleClickDelay
= DELAY(i
);
190 sprintf(buffer
, "%i", DELAY(i
));
191 WMSetTextFieldText(panel
->ddelaT
, buffer
);
202 if (strcasecmp(str
, "none")==0)
204 else if (strcasecmp(str
, "left")==0)
206 else if (strcasecmp(str
, "middle")==0)
208 else if (strcasecmp(str
, "right")==0)
210 else if (strcasecmp(str
, "button1")==0)
212 else if (strcasecmp(str
, "button2")==0)
214 else if (strcasecmp(str
, "button3")==0)
216 else if (strcasecmp(str
, "button4")==0)
218 else if (strcasecmp(str
, "button5")==0) {
227 getMouseParameters(Display
*dpy
, float *accel
, int *thre
)
231 XGetPointerControl(dpy
, &n
, &d
, thre
);
233 *accel
= (float)n
/(float)d
;
239 showData(_Panel
*panel
)
243 int a
=-1, b
=-1, c
=-1;
246 Display
*dpy
= WMScreenDisplay(WMWidgetScreen(panel
->parent
));
248 str
= GetStringForKey("SelectWindowsMouseButton");
253 wwarning(_("bad value %s for option %s"),str
, "SelectWindowsMouseButton");
260 WMSetPopUpButtonSelectedItem(panel
->selP
, a
);
262 str
= GetStringForKey("WindowListMouseButton");
267 wwarning(_("bad value %s for option %s"), str
, "WindowListMouseButton");
274 WMSetPopUpButtonSelectedItem(panel
->listP
, b
);
276 str
= GetStringForKey("ApplicationMenuMouseButton");
281 wwarning(_("bad value %s for option %s"), str
, "ApplicationMenuMouseButton");
288 WMSetPopUpButtonSelectedItem(panel
->appP
, c
);
290 WMSetButtonSelected(panel
->disaB
, GetBoolForKey("DisableWSMouseActions"));
293 getMouseParameters(dpy
, &accel
, &a
);
294 panel
->maxThreshold
= WidthOfScreen(DefaultScreenOfDisplay(dpy
));
295 if (a
> panel
->maxThreshold
) {
296 panel
->maxThreshold
= a
;
298 sprintf(buffer
, "%i", a
);
299 WMSetTextFieldText(panel
->threT
, buffer
);
301 WMSetSliderValue(panel
->speedS
, (accel
- 0.25)/0.25);
303 panel
->acceleration
= accel
;
304 sprintf(buffer
, "%.2f", accel
);
305 WMSetTextFieldText(panel
->acceT
, buffer
);
308 b
= GetIntegerForKey("DoubleClickTime");
309 /* find best match */
311 for (i
=0; i
<5; i
++) {
316 WMPerformButtonClick(panel
->ddelaB
[a
]);
317 sprintf(buffer
, "%i", b
);
318 WMSetTextFieldText(panel
->ddelaT
, buffer
);
321 str
= GetStringForKey("ModifierKey");
324 a
= ModifierFromKey(dpy
, str
);
327 str
= modifierNames
[a
];
330 for (i
=0; i
<WMGetPopUpButtonNumberOfItems(panel
->grabP
); i
++) {
331 if (strstr(WMGetPopUpButtonItem(panel
->grabP
, i
), str
)) {
332 WMSetPopUpButtonSelectedItem(panel
->grabP
, i
);
340 sscanf(WMGetPopUpButtonItem(panel
->grabP
, 0), "%s", buffer
);
341 WMSetPopUpButtonSelectedItem(panel
->grabP
, 0);
342 wwarning(_("modifier key %s for option ModifierKey was not recognized. Using %s as default"),
350 fillModifierPopUp(WMPopUpButton
*pop
)
352 XModifierKeymap
*mapping
;
353 Display
*dpy
= WMScreenDisplay(WMWidgetScreen(pop
));
359 mapping
= XGetModifierMapping(dpy
);
361 if (!mapping
|| mapping
->max_keypermod
==0) {
362 WMAddPopUpButtonItem(pop
, "Mod1");
363 WMAddPopUpButtonItem(pop
, "Mod2");
364 WMAddPopUpButtonItem(pop
, "Mod3");
365 WMAddPopUpButtonItem(pop
, "Mod4");
366 WMAddPopUpButtonItem(pop
, "Mod5");
367 wwarning(_("could not retrieve keyboard modifier mapping"));
372 for (j
=0; j
<8; j
++) {
382 memset(array
, 0, sizeof(char*)*8);
383 for (i
=0; i
< mapping
->max_keypermod
; i
++) {
384 idx
= i
+j
*mapping
->max_keypermod
;
385 if (mapping
->modifiermap
[idx
]!=0) {
387 for (l
=0; l
<4; l
++) {
388 ksym
= XKeycodeToKeysym(dpy
, mapping
->modifiermap
[idx
], l
);
393 str
= XKeysymToString(ksym
);
396 if (str
&& !strstr(str
, "_Lock") && !strstr(str
, "Shift")
397 && !strstr(str
, "Control")) {
398 array
[a
++] = wstrdup(str
);
403 for (k
=0; k
<a
; k
++) {
406 tmp
= wstrdup(array
[k
]);
407 ptr
= strstr(tmp
, "_L");
410 ptr
= strstr(tmp
, "_R");
413 sprintf(buffer
, "%s (%s)", modifierNames
[j
], tmp
);
414 /*sprintf(buffer, "%s", tmp);*/
415 WMAddPopUpButtonItem(pop
, buffer
);
416 for (i
=k
+1; i
<a
; i
++) {
417 if (array
[i
] == NULL
)
419 if (strstr(array
[i
], tmp
)) {
435 XFreeModifiermap(mapping
);
441 createPanel(Panel
*p
)
443 _Panel
*panel
= (_Panel
*)p
;
444 WMScreen
*scr
= WMWidgetScreen(panel
->parent
);
455 panel
->box
= WMCreateBox(panel
->parent
);
456 WMSetViewExpandsToParent(WMWidgetView(panel
->box
), 2, 2, 0, 0);
458 /**************** Mouse Speed ****************/
459 panel
->speedF
= WMCreateFrame(panel
->box
);
460 WMResizeWidget(panel
->speedF
, 245, 100);
461 WMMoveWidget(panel
->speedF
, 15, 15);
462 WMSetFrameTitle(panel
->speedF
, _("Mouse Speed"));
464 panel
->speedL
= WMCreateLabel(panel
->speedF
);
465 WMResizeWidget(panel
->speedL
, 40, 46);
466 WMMoveWidget(panel
->speedL
, 15, 14);
467 WMSetLabelImagePosition(panel
->speedL
, WIPImageOnly
);
468 path
= LocateImage(SPEED_ICON_FILE
);
470 icon
= WMCreateBlendedPixmapFromFile(scr
, path
, &color
);
472 WMSetLabelImage(panel
->speedL
, icon
);
473 WMReleasePixmap(icon
);
475 wwarning(_("could not load icon %s"), path
);
480 panel
->speedS
= WMCreateSlider(panel
->speedF
);
481 WMResizeWidget(panel
->speedS
, 160, 15);
482 WMMoveWidget(panel
->speedS
, 70, 35);
483 WMSetSliderMinValue(panel
->speedS
, 0);
484 WMSetSliderMaxValue(panel
->speedS
, 40);
485 WMSetSliderContinuous(panel
->speedS
, False
);
486 WMSetSliderAction(panel
->speedS
, speedChange
, panel
);
488 panel
->acceL
= WMCreateLabel(panel
->speedF
);
489 WMResizeWidget(panel
->acceL
, 70, 16);
490 WMMoveWidget(panel
->acceL
, 10, 67);
491 WMSetLabelTextAlignment(panel
->acceL
, WARight
);
492 WMSetLabelText(panel
->acceL
, _("Acceler.:"));
494 panel
->acceT
= WMCreateTextField(panel
->speedF
);
495 WMResizeWidget(panel
->acceT
, 40, 20);
496 WMMoveWidget(panel
->acceT
, 80, 65);
497 WMAddNotificationObserver(returnPressed
, panel
,
498 WMTextDidEndEditingNotification
, panel
->acceT
);
501 panel
->threL
= WMCreateLabel(panel
->speedF
);
502 WMResizeWidget(panel
->threL
, 80, 16);
503 WMMoveWidget(panel
->threL
, 120, 67);
504 WMSetLabelTextAlignment(panel
->threL
, WARight
);
505 WMSetLabelText(panel
->threL
, _("Threshold:"));
507 panel
->threT
= WMCreateTextField(panel
->speedF
);
508 WMResizeWidget(panel
->threT
, 30, 20);
509 WMMoveWidget(panel
->threT
, 200, 65);
510 WMAddNotificationObserver(returnPressed
, panel
,
511 WMTextDidEndEditingNotification
, panel
->threT
);
513 WMMapSubwidgets(panel
->speedF
);
515 /***************** Doubleclick Delay ****************/
517 panel
->ddelaF
= WMCreateFrame(panel
->box
);
518 WMResizeWidget(panel
->ddelaF
, 245, 95);
519 WMMoveWidget(panel
->ddelaF
, 15, 125);
520 WMSetFrameTitle(panel
->ddelaF
, _("Double-Click Delay"));
522 buf1
= wmalloc(strlen(DELAY_ICON
)+2);
523 buf2
= wmalloc(strlen(DELAY_ICON_S
)+2);
525 for (i
= 0; i
< 5; i
++) {
526 panel
->ddelaB
[i
] = WMCreateCustomButton(panel
->ddelaF
,
528 WMResizeWidget(panel
->ddelaB
[i
], 25, 25);
529 WMMoveWidget(panel
->ddelaB
[i
], 30+(40*i
), 20);
530 WMSetButtonBordered(panel
->ddelaB
[i
], False
);
531 WMSetButtonImagePosition(panel
->ddelaB
[i
], WIPImageOnly
);
532 WMSetButtonAction(panel
->ddelaB
[i
], doubleClick
, panel
);
534 WMGroupButtons(panel
->ddelaB
[0], panel
->ddelaB
[i
]);
536 sprintf(buf1
, DELAY_ICON
, i
+1);
537 sprintf(buf2
, DELAY_ICON_S
, i
+1);
538 path
= LocateImage(buf1
);
540 icon
= WMCreatePixmapFromFile(scr
, path
);
542 WMSetButtonImage(panel
->ddelaB
[i
], icon
);
543 WMReleasePixmap(icon
);
545 wwarning(_("could not load icon file %s"), path
);
549 path
= LocateImage(buf2
);
551 icon
= WMCreatePixmapFromFile(scr
, path
);
553 WMSetButtonAltImage(panel
->ddelaB
[i
], icon
);
554 WMReleasePixmap(icon
);
556 wwarning(_("could not load icon file %s"), path
);
564 panel
->tester
= CreateDoubleTest(panel
->ddelaF
, _("Test"));
565 WMResizeWidget(panel
->tester
, 84, 29);
566 WMMoveWidget(panel
->tester
, 35, 55);
568 panel
->ddelaT
= WMCreateTextField(panel
->ddelaF
);
569 WMResizeWidget(panel
->ddelaT
, 40, 20);
570 WMMoveWidget(panel
->ddelaT
, 140, 60);
572 panel
->ddelaL
= WMCreateLabel(panel
->ddelaF
);
573 WMResizeWidget(panel
->ddelaL
, 40, 16);
574 WMMoveWidget(panel
->ddelaL
, 185, 65);
579 font
= WMSystemFontOfSize(scr
, 10);
580 color
= WMDarkGrayColor(scr
);
581 WMSetLabelTextColor(panel
->ddelaL
, color
);
582 WMSetLabelFont(panel
->ddelaL
, font
);
584 WMReleaseColor(color
);
586 WMSetLabelText(panel
->ddelaL
, _("msec"));
588 WMMapSubwidgets(panel
->ddelaF
);
590 /* ************** Workspace Action Buttons **************** */
591 panel
->menuF
= WMCreateFrame(panel
->box
);
592 WMResizeWidget(panel
->menuF
, 240, 145);
593 WMMoveWidget(panel
->menuF
, 270, 15);
594 WMSetFrameTitle(panel
->menuF
, _("Workspace Mouse Actions"));
596 panel
->disaB
= WMCreateSwitchButton(panel
->menuF
);
597 WMResizeWidget(panel
->disaB
, 205, 18);
598 WMMoveWidget(panel
->disaB
, 10, 20);
599 WMSetButtonText(panel
->disaB
, _("Disable mouse actions"));
602 panel
->appL
= WMCreateLabel(panel
->menuF
);
603 WMResizeWidget(panel
->appL
, 125, 16);
604 WMMoveWidget(panel
->appL
, 5, 45);
605 WMSetLabelTextAlignment(panel
->appL
, WARight
);
606 WMSetLabelText(panel
->appL
, _("Applications menu"));
608 panel
->appP
= WMCreatePopUpButton(panel
->menuF
);
609 WMResizeWidget(panel
->appP
, 95, 20);
610 WMMoveWidget(panel
->appP
, 135, 45);
612 panel
->listL
= WMCreateLabel(panel
->menuF
);
613 WMResizeWidget(panel
->listL
, 125, 16);
614 WMMoveWidget(panel
->listL
, 5, 80);
615 WMSetLabelTextAlignment(panel
->listL
, WARight
);
616 WMSetLabelText(panel
->listL
, _("Window list menu"));
618 panel
->listP
= WMCreatePopUpButton(panel
->menuF
);
619 WMResizeWidget(panel
->listP
, 95, 20);
620 WMMoveWidget(panel
->listP
, 135, 80);
623 panel
->selL
= WMCreateLabel(panel
->menuF
);
624 WMResizeWidget(panel
->selL
, 125, 16);
625 WMMoveWidget(panel
->selL
, 5, 115);
626 WMSetLabelTextAlignment(panel
->selL
, WARight
);
627 WMSetLabelText(panel
->selL
, _("Select windows"));
629 panel
->selP
= WMCreatePopUpButton(panel
->menuF
);
630 WMResizeWidget(panel
->selP
, 95, 20);
631 WMMoveWidget(panel
->selP
, 135, 115);
633 for (i
= 0; i
< sizeof(buttonNames
)/sizeof(char*); i
++) {
634 WMAddPopUpButtonItem(panel
->appP
, buttonNames
[i
]);
635 WMAddPopUpButtonItem(panel
->selP
, buttonNames
[i
]);
636 WMAddPopUpButtonItem(panel
->listP
, buttonNames
[i
]);
639 WMMapSubwidgets(panel
->menuF
);
641 /* ************** Grab Modifier **************** */
642 panel
->grabF
= WMCreateFrame(panel
->box
);
643 WMResizeWidget(panel
->grabF
, 240, 55);
644 WMMoveWidget(panel
->grabF
, 270, 165);
645 WMSetFrameTitle(panel
->grabF
, _("Mouse Grab Modifier"));
647 WMSetBalloonTextForView(_("Keyboard modifier to use for actions that\n"
648 "involve dragging windows with the mouse,\n"
649 "clicking inside the window."),
650 WMWidgetView(panel
->grabF
));
652 panel
->grabP
= WMCreatePopUpButton(panel
->grabF
);
653 WMResizeWidget(panel
->grabP
, 160, 20);
654 WMMoveWidget(panel
->grabP
, 40, 25);
656 fillModifierPopUp(panel
->grabP
);
658 WMMapSubwidgets(panel
->grabF
);
660 WMRealizeWidget(panel
->box
);
661 WMMapSubwidgets(panel
->box
);
669 storeCommandInScript(char *cmd
, char *line
)
675 path
= wstrconcat(wusergnusteppath(), "/Library/WindowMaker/autostart");
677 f
= fopen(path
, "r");
679 f
= fopen(path
, "w");
681 wsyserror(_("could not create %s"), path
);
684 fprintf(f
, "#!/bin/sh\n");
688 int len
= strlen(cmd
);
693 tmppath
= wstrconcat(wusergnusteppath(),
694 "/Library/WindowMaker/autostart.tmp");
695 fo
= fopen(tmppath
, "w");
697 wsyserror(_("could not create temporary file %s"), tmppath
);
703 if (!fgets(buffer
, 127, f
)) {
706 if (buffer
[0] == '\n') {
707 /* don't write empty lines, else the file will grow
708 * indefinitely (one '\n' added at end of file on each save).
712 if (strncmp(buffer
, cmd
, len
)==0) {
728 if (rename(tmppath
, path
)!=0) {
729 wsyserror(_("could not rename file %s to %s\n"), tmppath
, path
);
733 sprintf(buffer
, "chmod u+x %s", path
);
744 storeData(_Panel
*panel
)
749 static char *button
[6] = {"None", "left", "middle", "right", "Button4", "Button5"};
750 WMUserDefaults
*udb
= WMGetStandardUserDefaults();
752 if (!WMGetUDBoolForKey(udb
, "NoXSetStuff")) {
753 tmp
= WMGetTextFieldText(panel
->threT
);
754 if (strlen(tmp
)==0) {
759 sprintf(buffer
, XSET
" m %i/%i %s\n", (int)(panel
->acceleration
*10),
761 storeCommandInScript(XSET
" m", buffer
);
766 tmp
= WMGetTextFieldText(panel
->ddelaT
);
767 if (sscanf(tmp
, "%i", &i
) == 1 && i
> 0)
768 SetIntegerForKey(i
, "DoubleClickTime");
770 SetBoolForKey(WMGetButtonSelected(panel
->disaB
), "DisableWSMouseActions");
772 i
= WMGetPopUpButtonSelectedItem(panel
->appP
);
773 SetStringForKey(button
[i
], "ApplicationMenuMouseButton");
775 i
= WMGetPopUpButtonSelectedItem(panel
->listP
);
776 SetStringForKey(button
[i
], "WindowListMouseButton");
778 i
= WMGetPopUpButtonSelectedItem(panel
->selP
);
779 SetStringForKey(button
[i
], "SelectWindowsMouseButton");
781 tmp
= WMGetPopUpButtonItem(panel
->grabP
,
782 WMGetPopUpButtonSelectedItem(panel
->grabP
));
784 p
= strchr(tmp
, ' ');
787 SetStringForKey(tmp
, "ModifierKey");
794 InitMouseSettings(WMScreen
*scr
, WMWidget
*parent
)
798 modifierNames
[0] = wstrdup(_("Shift"));
799 modifierNames
[1] = wstrdup(_("Lock"));
800 modifierNames
[2] = wstrdup(_("Control"));
801 modifierNames
[3] = wstrdup(_("Mod1"));
802 modifierNames
[4] = wstrdup(_("Mod2"));
803 modifierNames
[5] = wstrdup(_("Mod3"));
804 modifierNames
[6] = wstrdup(_("Mod4"));
805 modifierNames
[7] = wstrdup(_("Mod5"));
807 buttonNames
[0] = wstrdup(_("None"));
808 buttonNames
[1] = wstrdup(_("Btn1 (left)"));
809 buttonNames
[2] = wstrdup(_("Btn2 (middle)"));
810 buttonNames
[3] = wstrdup(_("Btn3 (right)"));
811 buttonNames
[4] = wstrdup(_("Btn4"));
812 buttonNames
[5] = wstrdup(_("Btn5"));
814 panel
= wmalloc(sizeof(_Panel
));
815 memset(panel
, 0, sizeof(_Panel
));
817 panel
->sectionName
= _("Mouse Preferences");
819 panel
->description
= _("Mouse speed/acceleration, double click delay,\n"
820 "mouse button bindings etc.");
822 panel
->parent
= parent
;
824 panel
->callbacks
.createWidgets
= createPanel
;
825 panel
->callbacks
.updateDomain
= storeData
;
827 AddSection(panel
, ICON_FILE
);