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
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
;
70 WMPopUpButton
*button1P
;
71 WMPopUpButton
*button2P
;
72 WMPopUpButton
*button3P
;
73 WMPopUpButton
*wheelP
;
86 #define ICON_FILE "mousesettings"
88 #define SPEED_ICON_FILE "mousespeed"
90 #define DELAY_ICON "timer%i"
91 #define DELAY_ICON_S "timer%is"
94 /* need access to the double click variables */
95 #include <WINGs/WINGsP.h>
99 static char *modifierNames
[8];
102 static char *buttonActions
[4];
104 static char *wheelActions
[2];
107 #define DELAY(i) ((i)*75+170)
110 int ModifierFromKey(Display
*dpy
, char *key
);
114 setMouseAccel(WMScreen
*scr
, float accel
, int threshold
)
121 XChangePointerControl(WMScreenDisplay(scr
), True
, True
, n
, d
, threshold
);
126 speedChange(WMWidget
*w
, void *data
)
128 _Panel
*panel
= (_Panel
*)data
;
137 tmp
= WMGetTextFieldText(panel
->acceT
);
138 if (sscanf(tmp
, "%f", &accel
)!=1 || accel
< 0) {
139 WMRunAlertPanel(WMWidgetScreen(panel
->acceT
), GetWindow(panel
),
141 _("Invalid mouse acceleration value. Must be a positive real value."),
142 _("OK"), NULL
, NULL
);
146 panel
->acceleration
= accel
;
149 i
= (int)WMGetSliderValue(panel
->speedS
);
151 panel
->acceleration
= 0.25+(i
*0.25);
153 sprintf(buffer
, "%.2f", 0.25+(i
*0.25));
154 WMSetTextFieldText(panel
->acceT
, buffer
);
157 tmp
= WMGetTextFieldText(panel
->threT
);
158 if (sscanf(tmp
, "%i", &threshold
)!=1 || threshold
< 0
159 || threshold
> panel
->maxThreshold
) {
160 WMRunAlertPanel(WMWidgetScreen(panel
->parent
), GetWindow(panel
), _("Error"),
161 _("Invalid mouse acceleration threshold value. Must be the number of pixels to travel before accelerating."),
162 _("OK"), NULL
, NULL
);
164 setMouseAccel(WMWidgetScreen(panel
->parent
), panel
->acceleration
,
172 returnPressed(void *observerData
, WMNotification
*notification
)
174 _Panel
*panel
= (_Panel
*)observerData
;
176 speedChange(NULL
, panel
);
181 doubleClick(WMWidget
*w
, void *data
)
183 _Panel
*panel
= (_Panel
*)data
;
185 extern _WINGsConfiguration WINGsConfiguration
;
188 for (i
=0; i
<5; i
++) {
189 if (panel
->ddelaB
[i
]==w
)
192 WINGsConfiguration
.doubleClickDelay
= DELAY(i
);
194 sprintf(buffer
, "%i", DELAY(i
));
195 WMSetTextFieldText(panel
->ddelaT
, buffer
);
200 getButtonAction(char *str
)
205 if (strcasecmp(str
, "None")==0)
207 else if (strcasecmp(str
, "OpenApplicationsMenu")==0)
209 else if (strcasecmp(str
, "OpenWindowListMenu")==0)
211 else if (strcasecmp(str
, "SelectWindows")==0)
220 getWheelAction(char *str
)
225 if (strcasecmp(str
, "None")==0)
227 else if (strcasecmp(str
, "SwitchWorkspaces")==0)
236 getMouseParameters(Display
*dpy
, float *accel
, int *thre
)
240 XGetPointerControl(dpy
, &n
, &d
, thre
);
242 *accel
= (float)n
/(float)d
;
248 showData(_Panel
*panel
)
252 int a
=-1, b
=-1, c
=-1, w
=-1;
255 Display
*dpy
= WMScreenDisplay(WMWidgetScreen(panel
->parent
));
257 str
= GetStringForKey("MouseLeftButtonAction");
258 i
= getButtonAction(str
);
262 wwarning(_("bad value %s for option %s"), str
, "MouseLeftButtonAction");
267 WMSetPopUpButtonSelectedItem(panel
->button1P
, a
);
269 str
= GetStringForKey("MouseMiddleButtonAction");
270 i
= getButtonAction(str
);
274 wwarning(_("bad value %s for option %s"), str
, "MouseMiddleButtonAction");
279 WMSetPopUpButtonSelectedItem(panel
->button2P
, b
);
281 str
= GetStringForKey("MouseRightButtonAction");
282 i
= getButtonAction(str
);
286 wwarning(_("bad value %s for option %s"), str
, "MouseRightButtonAction");
291 WMSetPopUpButtonSelectedItem(panel
->button3P
, c
);
293 str
= GetStringForKey("MouseWheelAction");
294 i
= getWheelAction(str
);
298 wwarning(_("bad value %s for option %s"), str
, "MouseWheelAction");
303 WMSetPopUpButtonSelectedItem(panel
->wheelP
, w
);
305 WMSetButtonSelected(panel
->disaB
, GetBoolForKey("DisableWSMouseActions"));
308 getMouseParameters(dpy
, &accel
, &a
);
309 panel
->maxThreshold
= WidthOfScreen(DefaultScreenOfDisplay(dpy
));
310 if (a
> panel
->maxThreshold
) {
311 panel
->maxThreshold
= a
;
313 sprintf(buffer
, "%i", a
);
314 WMSetTextFieldText(panel
->threT
, buffer
);
316 WMSetSliderValue(panel
->speedS
, (accel
- 0.25)/0.25);
318 panel
->acceleration
= accel
;
319 sprintf(buffer
, "%.2f", accel
);
320 WMSetTextFieldText(panel
->acceT
, buffer
);
323 b
= GetIntegerForKey("DoubleClickTime");
324 /* find best match */
326 for (i
=0; i
<5; i
++) {
331 WMPerformButtonClick(panel
->ddelaB
[a
]);
332 sprintf(buffer
, "%i", b
);
333 WMSetTextFieldText(panel
->ddelaT
, buffer
);
336 str
= GetStringForKey("ModifierKey");
339 a
= ModifierFromKey(dpy
, str
);
342 str
= modifierNames
[a
];
345 for (i
=0; i
<WMGetPopUpButtonNumberOfItems(panel
->grabP
); i
++) {
346 if (strstr(WMGetPopUpButtonItem(panel
->grabP
, i
), str
)) {
347 WMSetPopUpButtonSelectedItem(panel
->grabP
, i
);
355 sscanf(WMGetPopUpButtonItem(panel
->grabP
, 0), "%s", buffer
);
356 WMSetPopUpButtonSelectedItem(panel
->grabP
, 0);
357 wwarning(_("modifier key %s for option ModifierKey was not recognized. Using %s as default"),
365 fillModifierPopUp(WMPopUpButton
*pop
)
367 XModifierKeymap
*mapping
;
368 Display
*dpy
= WMScreenDisplay(WMWidgetScreen(pop
));
374 mapping
= XGetModifierMapping(dpy
);
376 if (!mapping
|| mapping
->max_keypermod
==0) {
377 WMAddPopUpButtonItem(pop
, "Mod1");
378 WMAddPopUpButtonItem(pop
, "Mod2");
379 WMAddPopUpButtonItem(pop
, "Mod3");
380 WMAddPopUpButtonItem(pop
, "Mod4");
381 WMAddPopUpButtonItem(pop
, "Mod5");
382 wwarning(_("could not retrieve keyboard modifier mapping"));
387 for (j
=0; j
<8; j
++) {
397 memset(array
, 0, sizeof(char*)*8);
398 for (i
=0; i
< mapping
->max_keypermod
; i
++) {
399 idx
= i
+j
*mapping
->max_keypermod
;
400 if (mapping
->modifiermap
[idx
]!=0) {
402 for (l
=0; l
<4; l
++) {
403 ksym
= XKeycodeToKeysym(dpy
, mapping
->modifiermap
[idx
], l
);
408 str
= XKeysymToString(ksym
);
411 if (str
&& !strstr(str
, "_Lock") && !strstr(str
, "Shift")
412 && !strstr(str
, "Control")) {
413 array
[a
++] = wstrdup(str
);
418 for (k
=0; k
<a
; k
++) {
421 tmp
= wstrdup(array
[k
]);
422 ptr
= strstr(tmp
, "_L");
425 ptr
= strstr(tmp
, "_R");
428 sprintf(buffer
, "%s (%s)", modifierNames
[j
], tmp
);
429 /*sprintf(buffer, "%s", tmp);*/
430 WMAddPopUpButtonItem(pop
, buffer
);
431 for (i
=k
+1; i
<a
; i
++) {
432 if (array
[i
] == NULL
)
434 if (strstr(array
[i
], tmp
)) {
450 XFreeModifiermap(mapping
);
456 createPanel(Panel
*p
)
458 _Panel
*panel
= (_Panel
*)p
;
459 WMScreen
*scr
= WMWidgetScreen(panel
->parent
);
470 panel
->box
= WMCreateBox(panel
->parent
);
471 WMSetViewExpandsToParent(WMWidgetView(panel
->box
), 2, 2, 2, 2);
473 /**************** Mouse Speed ****************/
474 panel
->speedF
= WMCreateFrame(panel
->box
);
475 WMResizeWidget(panel
->speedF
, 245, 100);
476 WMMoveWidget(panel
->speedF
, 15, 5);
477 WMSetFrameTitle(panel
->speedF
, _("Mouse Speed"));
479 panel
->speedL
= WMCreateLabel(panel
->speedF
);
480 WMResizeWidget(panel
->speedL
, 40, 46);
481 WMMoveWidget(panel
->speedL
, 15, 14);
482 WMSetLabelImagePosition(panel
->speedL
, WIPImageOnly
);
483 path
= LocateImage(SPEED_ICON_FILE
);
485 icon
= WMCreateBlendedPixmapFromFile(scr
, path
, &color
);
487 WMSetLabelImage(panel
->speedL
, icon
);
488 WMReleasePixmap(icon
);
490 wwarning(_("could not load icon %s"), path
);
495 panel
->speedS
= WMCreateSlider(panel
->speedF
);
496 WMResizeWidget(panel
->speedS
, 160, 15);
497 WMMoveWidget(panel
->speedS
, 70, 35);
498 WMSetSliderMinValue(panel
->speedS
, 0);
499 WMSetSliderMaxValue(panel
->speedS
, 40);
500 WMSetSliderContinuous(panel
->speedS
, False
);
501 WMSetSliderAction(panel
->speedS
, speedChange
, panel
);
503 panel
->acceL
= WMCreateLabel(panel
->speedF
);
504 WMResizeWidget(panel
->acceL
, 70, 16);
505 WMMoveWidget(panel
->acceL
, 10, 67);
506 WMSetLabelTextAlignment(panel
->acceL
, WARight
);
507 WMSetLabelText(panel
->acceL
, _("Acceler.:"));
509 panel
->acceT
= WMCreateTextField(panel
->speedF
);
510 WMResizeWidget(panel
->acceT
, 40, 20);
511 WMMoveWidget(panel
->acceT
, 80, 65);
512 WMAddNotificationObserver(returnPressed
, panel
,
513 WMTextDidEndEditingNotification
, panel
->acceT
);
516 panel
->threL
= WMCreateLabel(panel
->speedF
);
517 WMResizeWidget(panel
->threL
, 80, 16);
518 WMMoveWidget(panel
->threL
, 120, 67);
519 WMSetLabelTextAlignment(panel
->threL
, WARight
);
520 WMSetLabelText(panel
->threL
, _("Threshold:"));
522 panel
->threT
= WMCreateTextField(panel
->speedF
);
523 WMResizeWidget(panel
->threT
, 30, 20);
524 WMMoveWidget(panel
->threT
, 200, 65);
525 WMAddNotificationObserver(returnPressed
, panel
,
526 WMTextDidEndEditingNotification
, panel
->threT
);
528 WMMapSubwidgets(panel
->speedF
);
530 /***************** Doubleclick Delay ****************/
532 panel
->ddelaF
= WMCreateFrame(panel
->box
);
533 WMResizeWidget(panel
->ddelaF
, 245, 105);
534 WMMoveWidget(panel
->ddelaF
, 15, 115);
535 WMSetFrameTitle(panel
->ddelaF
, _("Double-Click Delay"));
537 buf1
= wmalloc(strlen(DELAY_ICON
)+2);
538 buf2
= wmalloc(strlen(DELAY_ICON_S
)+2);
540 for (i
= 0; i
< 5; i
++) {
541 panel
->ddelaB
[i
] = WMCreateCustomButton(panel
->ddelaF
,
543 WMResizeWidget(panel
->ddelaB
[i
], 25, 25);
544 WMMoveWidget(panel
->ddelaB
[i
], 30+(40*i
), 25);
545 WMSetButtonBordered(panel
->ddelaB
[i
], False
);
546 WMSetButtonImagePosition(panel
->ddelaB
[i
], WIPImageOnly
);
547 WMSetButtonAction(panel
->ddelaB
[i
], doubleClick
, panel
);
549 WMGroupButtons(panel
->ddelaB
[0], panel
->ddelaB
[i
]);
551 sprintf(buf1
, DELAY_ICON
, i
+1);
552 sprintf(buf2
, DELAY_ICON_S
, i
+1);
553 path
= LocateImage(buf1
);
555 icon
= WMCreatePixmapFromFile(scr
, path
);
557 WMSetButtonImage(panel
->ddelaB
[i
], icon
);
558 WMReleasePixmap(icon
);
560 wwarning(_("could not load icon file %s"), path
);
564 path
= LocateImage(buf2
);
566 icon
= WMCreatePixmapFromFile(scr
, path
);
568 WMSetButtonAltImage(panel
->ddelaB
[i
], icon
);
569 WMReleasePixmap(icon
);
571 wwarning(_("could not load icon file %s"), path
);
579 panel
->tester
= CreateDoubleTest(panel
->ddelaF
, _("Test"));
580 WMResizeWidget(panel
->tester
, 84, 29);
581 WMMoveWidget(panel
->tester
, 35, 60);
583 panel
->ddelaT
= WMCreateTextField(panel
->ddelaF
);
584 WMResizeWidget(panel
->ddelaT
, 40, 20);
585 WMMoveWidget(panel
->ddelaT
, 140, 65);
587 panel
->ddelaL
= WMCreateLabel(panel
->ddelaF
);
588 WMResizeWidget(panel
->ddelaL
, 40, 16);
589 WMMoveWidget(panel
->ddelaL
, 185, 70);
594 font
= WMSystemFontOfSize(scr
, 10);
595 color
= WMDarkGrayColor(scr
);
596 WMSetLabelTextColor(panel
->ddelaL
, color
);
597 WMSetLabelFont(panel
->ddelaL
, font
);
599 WMReleaseColor(color
);
601 WMSetLabelText(panel
->ddelaL
, _("msec"));
603 WMMapSubwidgets(panel
->ddelaF
);
605 /* ************** Workspace Action Buttons **************** */
606 panel
->menuF
= WMCreateFrame(panel
->box
);
607 WMResizeWidget(panel
->menuF
, 240, 160);
608 WMMoveWidget(panel
->menuF
, 270, 5);
609 WMSetFrameTitle(panel
->menuF
, _("Workspace Mouse Actions"));
611 panel
->disaB
= WMCreateSwitchButton(panel
->menuF
);
612 WMResizeWidget(panel
->disaB
, 205, 18);
613 WMMoveWidget(panel
->disaB
, 10, 18);
614 WMSetButtonText(panel
->disaB
, _("Disable mouse actions"));
616 panel
->button1L
= WMCreateLabel(panel
->menuF
);
617 WMResizeWidget(panel
->button1L
, 87, 20);
618 WMMoveWidget(panel
->button1L
, 5, 45);
619 WMSetLabelTextAlignment(panel
->button1L
, WARight
);
620 WMSetLabelText(panel
->button1L
, _("Left Button"));
622 panel
->button1P
= WMCreatePopUpButton(panel
->menuF
);
623 WMResizeWidget(panel
->button1P
, 135, 20);
624 WMMoveWidget(panel
->button1P
, 95, 45);
626 panel
->button2L
= WMCreateLabel(panel
->menuF
);
627 WMResizeWidget(panel
->button2L
, 87, 20);
628 WMMoveWidget(panel
->button2L
, 5, 73);
629 WMSetLabelTextAlignment(panel
->button2L
, WARight
);
630 WMSetLabelText(panel
->button2L
, _("Middle Button"));
632 panel
->button2P
= WMCreatePopUpButton(panel
->menuF
);
633 WMResizeWidget(panel
->button2P
, 135, 20);
634 WMMoveWidget(panel
->button2P
, 95, 73);
636 panel
->button3L
= WMCreateLabel(panel
->menuF
);
637 WMResizeWidget(panel
->button3L
, 87, 20);
638 WMMoveWidget(panel
->button3L
, 5, 101);
639 WMSetLabelTextAlignment(panel
->button3L
, WARight
);
640 WMSetLabelText(panel
->button3L
, _("Right Button"));
642 panel
->button3P
= WMCreatePopUpButton(panel
->menuF
);
643 WMResizeWidget(panel
->button3P
, 135, 20);
644 WMMoveWidget(panel
->button3P
, 95, 101);
646 panel
->wheelL
= WMCreateLabel(panel
->menuF
);
647 WMResizeWidget(panel
->wheelL
, 87, 20);
648 WMMoveWidget(panel
->wheelL
, 5, 129);
649 WMSetLabelTextAlignment(panel
->wheelL
, WARight
);
650 WMSetLabelText(panel
->wheelL
, _("Mouse Wheel"));
652 panel
->wheelP
= WMCreatePopUpButton(panel
->menuF
);
653 WMResizeWidget(panel
->wheelP
, 135, 20);
654 WMMoveWidget(panel
->wheelP
, 95, 129);
656 for (i
= 0; i
< sizeof(buttonActions
)/sizeof(char*); i
++) {
657 WMAddPopUpButtonItem(panel
->button1P
, buttonActions
[i
]);
658 WMAddPopUpButtonItem(panel
->button2P
, buttonActions
[i
]);
659 WMAddPopUpButtonItem(panel
->button3P
, buttonActions
[i
]);
662 for (i
= 0; i
< sizeof(wheelActions
)/sizeof(char*); i
++) {
663 WMAddPopUpButtonItem(panel
->wheelP
, wheelActions
[i
]);
666 WMMapSubwidgets(panel
->menuF
);
668 /* ************** Grab Modifier **************** */
669 panel
->grabF
= WMCreateFrame(panel
->box
);
670 WMResizeWidget(panel
->grabF
, 240, 50);
671 WMMoveWidget(panel
->grabF
, 270, 170);
672 WMSetFrameTitle(panel
->grabF
, _("Mouse Grab Modifier"));
674 WMSetBalloonTextForView(_("Keyboard modifier to use for actions that\n"
675 "involve dragging windows with the mouse,\n"
676 "clicking inside the window."),
677 WMWidgetView(panel
->grabF
));
679 panel
->grabP
= WMCreatePopUpButton(panel
->grabF
);
680 WMResizeWidget(panel
->grabP
, 160, 20);
681 WMMoveWidget(panel
->grabP
, 40, 20);
683 fillModifierPopUp(panel
->grabP
);
685 WMMapSubwidgets(panel
->grabF
);
687 WMRealizeWidget(panel
->box
);
688 WMMapSubwidgets(panel
->box
);
696 storeCommandInScript(char *cmd
, char *line
)
702 path
= wstrconcat(wusergnusteppath(), "/Library/WindowMaker/autostart");
704 f
= fopen(path
, "rb");
706 f
= fopen(path
, "wb");
708 wsyserror(_("could not create %s"), path
);
711 fprintf(f
, "#!/bin/sh\n");
715 int len
= strlen(cmd
);
720 tmppath
= wstrconcat(wusergnusteppath(),
721 "/Library/WindowMaker/autostart.tmp");
722 fo
= fopen(tmppath
, "wb");
724 wsyserror(_("could not create temporary file %s"), tmppath
);
730 if (!fgets(buffer
, 127, f
)) {
733 if (buffer
[0] == '\n') {
734 /* don't write empty lines, else the file will grow
735 * indefinitely (one '\n' added at end of file on each save).
739 if (strncmp(buffer
, cmd
, len
)==0) {
755 if (rename(tmppath
, path
)!=0) {
756 wsyserror(_("could not rename file %s to %s\n"), tmppath
, path
);
760 sprintf(buffer
, "chmod u+x %s", path
);
771 storeData(_Panel
*panel
)
776 static char *button
[4] = {"None", "OpenApplicationsMenu", "OpenWindowListMenu", "SelectWindows"};
777 static char *wheel
[2] = {"None", "SwitchWorkspaces"};
778 WMUserDefaults
*udb
= WMGetStandardUserDefaults();
780 if (!WMGetUDBoolForKey(udb
, "NoXSetStuff")) {
781 tmp
= WMGetTextFieldText(panel
->threT
);
782 if (strlen(tmp
)==0) {
787 sprintf(buffer
, XSET
" m %i/%i %s\n", (int)(panel
->acceleration
*10),
789 storeCommandInScript(XSET
" m", buffer
);
794 tmp
= WMGetTextFieldText(panel
->ddelaT
);
795 if (sscanf(tmp
, "%i", &i
) == 1 && i
> 0)
796 SetIntegerForKey(i
, "DoubleClickTime");
798 SetBoolForKey(WMGetButtonSelected(panel
->disaB
), "DisableWSMouseActions");
800 i
= WMGetPopUpButtonSelectedItem(panel
->button1P
);
801 SetStringForKey(button
[i
], "MouseLeftButtonAction");
803 i
= WMGetPopUpButtonSelectedItem(panel
->button2P
);
804 SetStringForKey(button
[i
], "MouseMiddleButtonAction");
806 i
= WMGetPopUpButtonSelectedItem(panel
->button3P
);
807 SetStringForKey(button
[i
], "MouseRightButtonAction");
809 i
= WMGetPopUpButtonSelectedItem(panel
->wheelP
);
810 SetStringForKey(wheel
[i
], "MouseWheelAction");
812 tmp
= WMGetPopUpButtonItem(panel
->grabP
,
813 WMGetPopUpButtonSelectedItem(panel
->grabP
));
815 p
= strchr(tmp
, ' ');
818 SetStringForKey(tmp
, "ModifierKey");
825 InitMouseSettings(WMScreen
*scr
, WMWidget
*parent
)
829 modifierNames
[0] = wstrdup(_("Shift"));
830 modifierNames
[1] = wstrdup(_("Lock"));
831 modifierNames
[2] = wstrdup(_("Control"));
832 modifierNames
[3] = wstrdup(_("Mod1"));
833 modifierNames
[4] = wstrdup(_("Mod2"));
834 modifierNames
[5] = wstrdup(_("Mod3"));
835 modifierNames
[6] = wstrdup(_("Mod4"));
836 modifierNames
[7] = wstrdup(_("Mod5"));
838 buttonActions
[0] = wstrdup(_("None"));
839 buttonActions
[1] = wstrdup(_("Applications Menu"));
840 buttonActions
[2] = wstrdup(_("Window List Menu"));
841 buttonActions
[3] = wstrdup(_("Select Windows"));
843 wheelActions
[0] = wstrdup(_("None"));
844 wheelActions
[1] = wstrdup(_("Switch Workspaces"));
846 panel
= wmalloc(sizeof(_Panel
));
847 memset(panel
, 0, sizeof(_Panel
));
849 panel
->sectionName
= _("Mouse Preferences");
851 panel
->description
= _("Mouse speed/acceleration, double click delay,\n"
852 "mouse button bindings etc.");
854 panel
->parent
= parent
;
856 panel
->callbacks
.createWidgets
= createPanel
;
857 panel
->callbacks
.updateDomain
= storeData
;
859 AddSection(panel
, ICON_FILE
);