2 * Acess2 Window Manager v3
3 * - By John Hodge (thePowersGang)
6 * - Hotkey and key shortcut code
9 #include <wm_internals.h>
10 #include <wm_messages.h>
11 #include <wm_hotkeys.h>
17 #define MAX_STATE_SCANCODE 256
20 char gbWM_HasBeenKeyDown = true;
21 uint8_t gWM_KeyStates[MAX_STATE_SCANCODE/8];
22 tHotkey *gpWM_Hotkeys;
23 tHotkeyTarget *gpWM_HotkeyTargets;
24 tHotkeyTarget *gpWM_HotkeyTargets_Last;
27 static void _SetKey(uint32_t sc);
28 static void _UnsetKey(uint32_t sc);
29 static int _IsKeySet(uint32_t sc);
30 void WM_Hotkey_FireEvent(const char *Target);
33 void WM_Hotkey_Register(int nKeys, uint32_t *Keys, const char *ActionName)
35 // TODO: Duplicate detection
37 // Create new structure
38 tHotkey *h = malloc(sizeof(tHotkey) + nKeys * sizeof(uint32_t) + strlen(ActionName) + 1);
40 h->Target = (void*)( h->Keys + nKeys );
41 strcpy((char*)h->Target, ActionName);
42 memcpy(h->Keys, Keys, nKeys * sizeof(uint32_t));
46 gpWM_Hotkeys->Next = h;
50 void WM_Hotkey_RegisterAction(const char *ActionName, tWindow *Target, uint16_t Index)
52 // Check for a duplicate registration
53 for( tHotkeyTarget *t = gpWM_HotkeyTargets; t; t = t->Next )
55 if( strcmp(t->Name, ActionName) != 0 )
61 // Create new structure
62 tHotkeyTarget *t = malloc(sizeof(tHotkeyTarget) + strlen(ActionName) + 1);
63 t->Name = (void*)(t + 1);
64 strcpy((char*)t->Name, ActionName);
68 // TODO: Register to be informed when the window dies/closes?
71 if( gpWM_HotkeyTargets ) {
72 gpWM_HotkeyTargets_Last->Next = t;
75 gpWM_HotkeyTargets = t;
77 gpWM_HotkeyTargets_Last = t;
80 void WM_Hotkey_KeyDown(uint32_t Scancode)
83 gbWM_HasBeenKeyDown = true;
86 void WM_Hotkey_KeyUp(uint32_t Scancode)
90 // Ensure that hotkeys are triggered on the longest sequence
91 // (so Win-Shift-R doesn't trigger Win-R if shift is released)
92 if( !gbWM_HasBeenKeyDown )
95 for( tHotkey *hk = gpWM_Hotkeys; hk; hk = hk->Next )
98 for( i = 0; i < hk->nKeys; i ++ )
100 if( hk->Keys[i] == Scancode ) continue ;
101 if( _IsKeySet(hk->Keys[i]) ) continue ;
104 _SysDebug("%i/%i satisfied for %s", i, hk->nKeys, hk->Target);
109 WM_Hotkey_FireEvent(hk->Target);
114 gbWM_HasBeenKeyDown = false;
117 void WM_Hotkey_FireEvent(const char *Target)
119 // _SysDebug("WM_Hotkey_FireEvent: (%s)", Target);
120 // - Internal events (Alt-Tab, Close, Maximize, etc...)
121 // TODO: Internal event handling
123 // - Application registered events
124 for( tHotkeyTarget *t = gpWM_HotkeyTargets, *prev=NULL; t; t = t->Next )
126 if( strcmp(t->Name, Target) != 0 )
129 struct sWndMsg_Hotkey info = {.ID=t->Index};
130 WM_SendMessage(NULL, t->Window, WNDMSG_HOTKEY, sizeof(info), &info);
132 // Sort the list by most-recently-used
134 prev->Next = t->Next;
135 t->Next = gpWM_HotkeyTargets;
136 gpWM_HotkeyTargets = t;
143 static void _SetKey(uint32_t sc)
145 // _SysDebug("_SetKey: (%x)", sc);
146 if( sc >= MAX_STATE_SCANCODE ) return;
147 gWM_KeyStates[sc/8] |= 1 << (sc % 8);
149 static void _UnsetKey(uint32_t sc)
151 // _SysDebug("_UnsetKey: (%x)", sc);
152 if( sc >= MAX_STATE_SCANCODE ) return;
153 gWM_KeyStates[sc/8] &= ~(1 << (sc % 8));
155 static int _IsKeySet(uint32_t sc)
157 if( sc >= MAX_STATE_SCANCODE ) return 0;
159 return !!(gWM_KeyStates[sc/8] & (1 << (sc % 8)));