2 Copyright 2003-2011, The AROS Development Team. All rights reserved.
6 #define MUIMASTER_YES_INLINE_STDARG
8 #include <devices/rawkeycodes.h>
9 #include <libraries/kms.h>
10 #include <mui/HotkeyString_mcc.h>
11 #include <zune/customclasses.h>
12 #include <zune/prefseditor.h>
14 #include <proto/alib.h>
15 #include <proto/dos.h>
16 #include <proto/commodities.h>
17 #include <proto/intuition.h>
18 #include <proto/muimaster.h>
21 #include <aros/debug.h>
28 #include "stringify.h"
30 static CONST_STRPTR InputTabs
[] = {NULL
, NULL
, NULL
, };
31 static CONST_STRPTR MouseSpeed
[] = {NULL
, NULL
, NULL
, NULL
, };
33 static struct Hook display_hook
;
35 /*** Instance Data **********************************************************/
38 Object
*iped_KeyTypes
;
41 Object
*iped_SetDefKey
;
42 Object
*iped_SetAltKey
;
43 Object
*iped_RepeatRate
;
44 Object
*iped_RepeatDelay
;
45 Object
*iped_SwitchEnable
;
46 Object
*iped_SwitchKey
;
47 Object
*iped_Accelerated
;
48 Object
*iped_MouseSpeed
;
49 Object
*iped_DoubleClickDelay
;
50 Object
*iped_LeftHandedMouse
;
52 struct Hook iped_setHook
;
53 struct Hook iped_setEnableHook
;
54 struct Hook iped_switchEnableHook
;
57 /*** Local Functions ********************************************************/
58 static BOOL
InputPrefs2Gadgets(struct IPEditor_DATA
*data
);
59 static BOOL
Gadgets2InputPrefs(struct IPEditor_DATA
*data
);
61 /*** Macros *****************************************************************/
62 #define SETUP_INST_DATA struct IPEditor_DATA *data = INST_DATA(CLASS, self)
64 /****************************************************************
65 The display function for the KeyTypes listview
66 *****************************************************************/
67 static void keytypes_display_func(struct Hook
*h
, char **array
, struct ListviewEntry
* entry
)
69 *array
++ = entry
->displayflag
;
70 *array
= entry
->node
.ln_Name
;
73 AROS_UFH3(static void, setFunction
,
74 AROS_UFHA(struct Hook
*, h
, A0
),
75 AROS_UFHA(Object
*, obj
, A2
),
76 AROS_UFHA(APTR
*, msg
, A1
))
80 struct IPEditor_DATA
*data
= h
->h_Data
;
81 Object
*kmobj
= msg
[0];
82 struct ListviewEntry
*entry
= NULL
;
84 DoMethod(data
->iped_KeyTypes
, MUIM_List_GetEntry
, MUIV_List_GetEntry_Active
, &entry
);
85 SET(kmobj
, MUIA_Keymap_Keymap
, entry
);
86 SET(obj
, MUIA_PrefsEditor_Changed
, TRUE
);
91 AROS_UFH3(static void, setEnableFunction
,
92 AROS_UFHA(struct Hook
*, h
, A0
),
93 AROS_UFHA(Object
*, obj
, A2
),
94 AROS_UFHA(APTR
, msg
, A1
))
98 struct IPEditor_DATA
*data
= h
->h_Data
;
99 IPTR sw_enabled
= FALSE
;
101 SET(data
->iped_SetDefKey
, MUIA_Disabled
, FALSE
);
102 GET(data
->iped_SwitchEnable
, MUIA_Selected
, &sw_enabled
);
103 SET(data
->iped_SetAltKey
, MUIA_Disabled
, !sw_enabled
);
108 AROS_UFH3(static void, switchEnableFunction
,
109 AROS_UFHA(struct Hook
*, h
, A0
),
110 AROS_UFHA(Object
*, obj
, A2
),
111 AROS_UFHA(APTR
, msg
, A1
))
115 struct IPEditor_DATA
*data
= h
->h_Data
;
119 GET(data
->iped_SwitchEnable
, MUIA_Selected
, &disabled
);
120 disabled
= !disabled
;
121 SET(data
->iped_SwitchKey
, MUIA_Disabled
, disabled
);
122 SET(data
->iped_AltKey
, MUIA_Disabled
, disabled
);
123 GET(data
->iped_KeyTypes
, MUIA_List_Active
, &active
);
124 SET(data
->iped_SetAltKey
, MUIA_Disabled
, disabled
|| (active
== MUIV_List_Active_Off
));
126 SET(obj
, MUIA_PrefsEditor_Changed
, TRUE
);
133 /*** Methods ****************************************************************/
134 Object
*IPEditor__OM_NEW(Class
*CLASS
, Object
*self
, struct opSet
*message
)
141 Object
*switchEnable
;
144 Object
*GadMouseSpeed
;
145 Object
*DoubleClickDelay
;
146 Object
*LeftHandedMouse
;
150 struct ListviewEntry
*entry
;
152 display_hook
.h_Entry
= HookEntry
;
153 display_hook
.h_SubEntry
= (HOOKFUNC
)keytypes_display_func
;
155 InputTabs
[0] = _(MSG_GAD_TAB_KEYBOARD
);
156 InputTabs
[1] = _(MSG_GAD_TAB_MOUSE
);
158 MouseSpeed
[0] = _(MSG_GAD_MOUSE_SPEED_SLOW
);
159 MouseSpeed
[1] = _(MSG_GAD_MOUSE_SPEED_NORMAL
);
160 MouseSpeed
[2] = _(MSG_GAD_MOUSE_SPEED_FAST
);
162 self
= (Object
*) DoSuperNewTags
166 MUIA_PrefsEditor_Name
, __(MSG_NAME
),
167 MUIA_PrefsEditor_Path
, (IPTR
) "SYS/input.prefs",
168 MUIA_PrefsEditor_IconTool
, (IPTR
) "SYS:Prefs/Input",
170 Child
, (IPTR
) RegisterGroup(InputTabs
),
174 GroupFrameT(__(MSG_GAD_KEY_TYPE
)),
176 Child
, (IPTR
)ListviewObject
,
177 MUIA_Listview_Input
, FALSE
,
178 MUIA_Listview_List
, (IPTR
)(keyTypes
= (Object
*)ListObject
,
180 MUIA_List_AutoVisible
, TRUE
,
181 MUIA_List_MinLineHeight
, 19,
182 MUIA_List_Format
, (IPTR
)"P=\033c,",
183 MUIA_List_DisplayHook
, (IPTR
)&display_hook
,
186 Child
, (IPTR
)ColGroup(3),
187 Child
, (IPTR
)Label1(__(MSG_GAD_KEY_DEF
)),
188 Child
, (IPTR
)(defKey
= KeymapObject
,
191 Child
, (IPTR
)(setDefKey
= TextObject
,
193 MUIA_Font
, MUIV_Font_Button
,
194 MUIA_Text_HiCharIdx
, '_',
195 MUIA_Text_Contents
, __(MSG_GAD_KEY_SET
),
196 MUIA_Text_PreParse
, (IPTR
)"\33c",
197 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
198 MUIA_Background
, MUII_ButtonBack
,
199 MUIA_CycleChain
, TRUE
,
202 Child
, (IPTR
)Label1(__(MSG_GAD_KEY_ALT
)),
203 Child
, (IPTR
)(altKey
= KeymapObject
,
207 Child
, (IPTR
)(setAltKey
= TextObject
,
209 MUIA_Font
, MUIV_Font_Button
,
210 MUIA_Text_HiCharIdx
, '_',
211 MUIA_Text_Contents
, __(MSG_GAD_KEY_SET
),
212 MUIA_Text_PreParse
, (IPTR
)"\33c",
213 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
214 MUIA_Background
, MUII_ButtonBack
,
215 MUIA_CycleChain
, TRUE
,
223 GroupFrameT(__(MSG_GAD_KEY_REPEAT_RATE
)),
224 Child
, (IPTR
)(RepeatRate
= (Object
*)StringifyObject
,
225 MUIA_MyStringifyType
, STRINGIFY_RepeatRate
,
226 MUIA_Numeric_Value
, 0,
228 MUIA_Numeric_Max
, 12,
232 GroupFrameT(__(MSG_GAD_KEY_REPEAT_DELAY
)),
233 Child
, (IPTR
)(RepeatDelay
= (Object
*)StringifyObject
,
234 MUIA_MyStringifyType
, STRINGIFY_RepeatDelay
,
235 MUIA_Numeric_Value
, 0,
237 MUIA_Numeric_Max
, 74,
240 Child
, (IPTR
)ColGroup(2),
241 GroupFrameT(__(MSG_GAD_KEY_SWITCH
)),
242 Child
, (IPTR
)Label1(__(MSG_GAD_KEY_SWITCH_ENABLE
)),
244 Child
, (IPTR
)(switchEnable
= MUI_MakeObject(MUIO_Checkmark
, NULL
)),
245 Child
, (IPTR
)MUI_MakeObject(MUIO_HSpace
, 0),
247 Child
, (IPTR
)Label1(__(MSG_GAD_KEY_SWITCH_KEY
)),
248 Child
, (IPTR
)(switchKey
= MUI_NewObject("HotkeyString.mcc",
254 GroupFrameT(__(MSG_GAD_KEY_TEST
)),
255 Child
, (IPTR
)StringObject
,
259 Child
, (IPTR
)HVSpace
,
265 GroupFrameT(__(MSG_GAD_MOUSE_SPEED
)),
266 Child
, (IPTR
)(GadMouseSpeed
= MUI_MakeObject(MUIO_Cycle
, NULL
, MouseSpeed
)),
268 Child
, (IPTR
)HSpace(0),
269 Child
, (IPTR
)Label1(__(MSG_GAD_MOUSE_ACCELERATED
)),
270 Child
, (IPTR
)(Accelerated
= MUI_MakeObject(MUIO_Checkmark
, NULL
)),
274 GroupFrameT(__(MSG_GAD_MOUSE_BUTTON_SETTINGS
)),
275 Child
, (IPTR
)ColGroup(2),
276 Child
, (IPTR
)Label1(__(MSG_GAD_MOUSE_DOUBLE_CLICK_DELAY
)),
277 Child
, (IPTR
)(DoubleClickDelay
= (Object
*)StringifyObject
,
278 MUIA_MyStringifyType
, STRINGIFY_DoubleClickDelay
,
279 MUIA_Numeric_Value
, 0,
281 MUIA_Numeric_Max
, 199,
283 Child
, (IPTR
)Label1(__(MSG_GAD_LEFT_HANDED_MOUSE
)),
285 Child
, (IPTR
)(LeftHandedMouse
= MUI_MakeObject(MUIO_Checkmark
, NULL
)),
286 Child
, (IPTR
)HSpace(0),
300 data
->iped_RepeatRate
= RepeatRate
;
301 data
->iped_RepeatDelay
= RepeatDelay
;
302 data
->iped_KeyTypes
= keyTypes
;
303 data
->iped_DefKey
= defKey
;
304 data
->iped_AltKey
= altKey
;
305 data
->iped_SetDefKey
= setDefKey
;
306 data
->iped_SetAltKey
= setAltKey
;
307 data
->iped_SwitchEnable
= switchEnable
;
308 data
->iped_SwitchKey
= switchKey
;
309 data
->iped_Accelerated
= Accelerated
;
310 data
->iped_MouseSpeed
= GadMouseSpeed
;
311 data
->iped_DoubleClickDelay
= DoubleClickDelay
;
312 data
->iped_LeftHandedMouse
= LeftHandedMouse
;
314 data
->iped_setHook
.h_Entry
= (HOOKFUNC
)setFunction
;
315 data
->iped_setHook
.h_Data
= data
;
316 data
->iped_setEnableHook
.h_Entry
= (HOOKFUNC
)setEnableFunction
;
317 data
->iped_setEnableHook
.h_Data
= data
;
318 data
->iped_switchEnableHook
.h_Entry
= (HOOKFUNC
)switchEnableFunction
;
319 data
->iped_switchEnableHook
.h_Data
= data
;
323 ForeachNode(&keymap_list
, entry
)
328 MUIM_List_InsertSingle
,
330 MUIV_List_Insert_Bottom
334 /* TODO: Do we want to check for an error? */
340 RepeatRate
, MUIM_Notify
, MUIA_Numeric_Value
, MUIV_EveryTime
,
341 (IPTR
) self
, 3, MUIM_Set
, MUIA_PrefsEditor_Changed
, TRUE
346 RepeatDelay
, MUIM_Notify
, MUIA_Numeric_Value
, MUIV_EveryTime
,
347 (IPTR
) self
, 3, MUIM_Set
, MUIA_PrefsEditor_Changed
, TRUE
352 DoubleClickDelay
, MUIM_Notify
, MUIA_Numeric_Value
, MUIV_EveryTime
,
353 (IPTR
) self
, 3, MUIM_Set
, MUIA_PrefsEditor_Changed
, TRUE
358 GadMouseSpeed
, MUIM_Notify
, MUIA_Cycle_Active
, MUIV_EveryTime
,
359 (IPTR
) self
, 3, MUIM_Set
, MUIA_PrefsEditor_Changed
, TRUE
362 DoMethod(keyTypes
, MUIM_Notify
, MUIA_List_Active
, MUIV_EveryTime
,
363 self
, 2, MUIM_CallHook
, &data
->iped_setEnableHook
);
365 DoMethod(setDefKey
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
366 self
, 3, MUIM_CallHook
, &data
->iped_setHook
, defKey
);
368 DoMethod(setAltKey
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
369 self
, 3, MUIM_CallHook
, &data
->iped_setHook
, altKey
);
371 DoMethod(switchEnable
, MUIM_Notify
, MUIA_Selected
, MUIV_EveryTime
,
372 self
, 2, MUIM_CallHook
, &data
->iped_switchEnableHook
);
374 DoMethod(switchKey
, MUIM_Notify
, MUIA_String_Contents
, MUIV_EveryTime
,
375 self
, 3, MUIM_Set
, MUIA_PrefsEditor_Changed
, TRUE
);
379 Accelerated
, MUIM_Notify
, MUIA_Selected
, MUIV_EveryTime
,
380 (IPTR
) self
, 3, MUIM_Set
, MUIA_PrefsEditor_Changed
, TRUE
385 LeftHandedMouse
, MUIM_Notify
, MUIA_Selected
, MUIV_EveryTime
,
386 (IPTR
) self
, 3, MUIM_Set
, MUIA_PrefsEditor_Changed
, TRUE
393 static BOOL
Gadgets2InputPrefs(struct IPEditor_DATA
*data
)
398 struct InputXpression ix
= {IX_VERSION
, 0};
400 GET(data
->iped_RepeatRate
, MUIA_Numeric_Value
, &val
);
402 micros
= (12 - val
) * 20000;
404 inputprefs
.ip_KeyRptSpeed
.tv_micro
= micros
;
405 inputprefs
.ip_KeyRptSpeed
.tv_secs
= 0;
407 GET(data
->iped_RepeatDelay
, MUIA_Numeric_Value
, &val
);
409 micros
= 20000 + val
* 20000;
410 secs
= (int) (micros
/ 1000000);
411 micros
= micros
% 1000000;
413 inputprefs
.ip_KeyRptDelay
.tv_micro
= micros
;
414 inputprefs
.ip_KeyRptDelay
.tv_secs
= secs
;
416 GET(data
->iped_DoubleClickDelay
, MUIA_Numeric_Value
, &val
);
418 micros
= 20000 + val
* 20000;
419 secs
= (int) (micros
/ 1000000);
420 micros
= micros
% 1000000;
422 inputprefs
.ip_DoubleClick
.tv_micro
= micros
;
423 inputprefs
.ip_DoubleClick
.tv_secs
= secs
;
425 GET(data
->iped_Accelerated
, MUIA_Selected
, &val
);
428 inputprefs
.ip_MouseAccel
= ~0;
430 inputprefs
.ip_MouseAccel
= 0;
432 GET(data
->iped_MouseSpeed
, MUIA_Cycle_Active
, &val
);
434 inputprefs
.ip_PointerTicks
= 1 << (2 - val
);
436 struct ListviewEntry
*entry
= NULL
;
438 GET(data
->iped_DefKey
, MUIA_Keymap_Keymap
, &entry
);
442 D(Printf("Gadgets2Prefs: Default keymap: %s\n", entry
->realname
));
443 strncpy(inputprefs
.ip_KeymapName
, entry
->realname
, sizeof(inputprefs
.ip_KeymapName
));
447 strncpy(inputprefs
.ip_Keymap
, DEFAULT_KEYMAP
, sizeof(inputprefs
.ip_Keymap
));
448 strncpy(inputprefs
.ip_KeymapName
, DEFAULT_KEYMAP
, sizeof(inputprefs
.ip_KeymapName
));
451 GET(data
->iped_LeftHandedMouse
, MUIA_Selected
, &val
);
452 inputprefs
.ip_SwitchMouseButtons
= val
;
454 GET(data
->iped_SwitchEnable
, MUIA_Selected
, &val
);
455 kmsprefs
.kms_Enabled
= val
;
457 GET(data
->iped_AltKey
, MUIA_Keymap_Keymap
, &entry
);
459 strncpy(kmsprefs
.kms_AltKeymap
, entry
->realname
, sizeof(kmsprefs
.kms_AltKeymap
));
461 kmsprefs
.kms_AltKeymap
[0] = 0;
463 GET(data
->iped_SwitchKey
, MUIA_String_Contents
, &key
);
464 if (ParseIX(key
, &ix
))
466 D(Printf("Gadgets2Prefs: IX parse error\n"));
467 kmsprefs
.kms_SwitchQual
= KMS_QUAL_DISABLE
;
468 kmsprefs
.kms_SwitchCode
= KMS_CODE_NOKEY
;
472 D(Printf("Gadgets2Prefs: Switch qualifier 0x%04lX, code 0x%04lX\n", ix
.ix_Qualifier
, ix
.ix_Code
));
473 kmsprefs
.kms_SwitchQual
= ix
.ix_Qualifier
;
475 * ParseIX() sets ix_Code to zero if the expressions consists only of qualifiers.
476 * This can be considered a bug, because 0x00 is a valid code for RAWKEY_TILDE key.
477 * This means that this key can't be a hotkey.
478 * CHECKME: is it the same as in AmigaOS(tm), or it's AROS bug?
480 kmsprefs
.kms_SwitchCode
= ix
.ix_Code
? ix
.ix_Code
: KMS_CODE_NOKEY
;
486 static BOOL
InputPrefs2Gadgets(struct IPEditor_DATA
*data
)
488 ULONG rrate
= 12 -(inputprefs
.ip_KeyRptSpeed
.tv_micro
/ 20000);
489 ULONG rdelay
= ((inputprefs
.ip_KeyRptDelay
.tv_micro
+ (inputprefs
.ip_KeyRptDelay
.tv_secs
* 1000000)) / 20000) - 1;
490 ULONG dcdelay
= ((inputprefs
.ip_DoubleClick
.tv_micro
+ (inputprefs
.ip_DoubleClick
.tv_secs
* 1000000)) / 20000) - 1;
491 char *keymap
= inputprefs
.ip_KeymapName
;
492 struct InputXpression ix
=
498 kmsprefs
.kms_SwitchQual
,
503 D(Printf("Prefs2Gadgets: Switch qualifier 0x%04lX, code 0x%04lX\n", kmsprefs
.kms_SwitchQual
, kmsprefs
.kms_SwitchCode
));
506 * In order to specify qualifier-only hotkey any qualifier key code will do.
507 * We use RAWKEY_LAMIGA for this purpose.
508 * This is HotKeyString.mcc's feature.
510 if (kmsprefs
.kms_SwitchCode
!= KMS_CODE_NOKEY
)
511 ix
.ix_Code
= kmsprefs
.kms_SwitchCode
;
514 keymap
= inputprefs
.ip_Keymap
;
516 NNSET(data
->iped_RepeatRate
, MUIA_Numeric_Value
, (IPTR
) rrate
);
517 NNSET(data
->iped_RepeatDelay
, MUIA_Numeric_Value
, (IPTR
) rdelay
);
518 NNSET(data
->iped_DoubleClickDelay
, MUIA_Numeric_Value
, (IPTR
) dcdelay
);
519 NNSET(data
->iped_Accelerated
, MUIA_Selected
, (IPTR
) (inputprefs
.ip_MouseAccel
!= 0) ? TRUE
: FALSE
);
521 struct ListviewEntry
*entry
;
523 ForeachNode(&keymap_list
, entry
)
525 if (!stricmp(keymap
, entry
->realname
))
526 SET(data
->iped_DefKey
, MUIA_Keymap_Keymap
, entry
);
527 if (!stricmp(kmsprefs
.kms_AltKeymap
, entry
->realname
))
528 SET(data
->iped_AltKey
, MUIA_Keymap_Keymap
, entry
);
533 switch(inputprefs
.ip_PointerTicks
)
550 NNSET(data
->iped_MouseSpeed
, MUIA_Cycle_Active
, active
);
552 NNSET(data
->iped_LeftHandedMouse
, MUIA_Selected
, inputprefs
.ip_SwitchMouseButtons
);
554 SET(data
->iped_SwitchEnable
, MUIA_Selected
, kmsprefs
.kms_Enabled
);
555 NNSET(data
->iped_SwitchKey
, MUIA_HotkeyString_IX
, &ix
);
560 IPTR IPEditor__MUIM_PrefsEditor_ImportFH
562 Class
*CLASS
, Object
*self
,
563 struct MUIP_PrefsEditor_ImportFH
*message
568 if (Prefs_ImportFH(message
->fh
))
570 IPTR back
= InputPrefs2Gadgets(data
);
572 SET(self
, MUIA_PrefsEditor_Changed
, FALSE
);
573 SET(self
, MUIA_PrefsEditor_Testing
, FALSE
);
579 IPTR IPEditor__MUIM_PrefsEditor_ExportFH
581 Class
*CLASS
, Object
*self
,
582 struct MUIP_PrefsEditor_ExportFH
*message
587 if (Gadgets2InputPrefs(data
))
589 return Prefs_ExportFH(message
->fh
);
594 IPTR IPEditor__MUIM_PrefsEditor_SetDefaults
596 Class
*CLASS
, Object
*self
, Msg message
602 success
= Prefs_Default();
604 InputPrefs2Gadgets(data
);
609 /*** Setup ******************************************************************/
612 IPEditor
, NULL
, MUIC_PrefsEditor
, NULL
,
613 OM_NEW
, struct opSet
*,
614 MUIM_PrefsEditor_ImportFH
, struct MUIP_PrefsEditor_ImportFH
*,
615 MUIM_PrefsEditor_ExportFH
, struct MUIP_PrefsEditor_ExportFH
*,
616 MUIM_PrefsEditor_SetDefaults
, Msg