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));
44 h->Next = gpWM_Hotkeys;
48 void WM_Hotkey_RegisterAction(const char *ActionName, tWindow *Target, uint16_t Index)
50 // Check for a duplicate registration
51 for( tHotkeyTarget *t = gpWM_HotkeyTargets; t; t = t->Next )
53 if( strcmp(t->Name, ActionName) != 0 )
59 // Create new structure
60 tHotkeyTarget *t = malloc(sizeof(tHotkeyTarget) + strlen(ActionName) + 1);
61 t->Name = (void*)(t + 1);
62 strcpy((char*)t->Name, ActionName);
67 // TODO: Register to be informed when the window dies/closes?
70 if( gpWM_HotkeyTargets ) {
71 gpWM_HotkeyTargets_Last->Next = t;
74 gpWM_HotkeyTargets = t;
76 gpWM_HotkeyTargets_Last = t;
79 void WM_Hotkey_KeyDown(uint32_t Scancode)
82 gbWM_HasBeenKeyDown = true;
85 void WM_Hotkey_KeyUp(uint32_t Scancode)
89 // Ensure that hotkeys are triggered on the longest sequence
90 // (so Win-Shift-R doesn't trigger Win-R if shift is released)
91 if( !gbWM_HasBeenKeyDown )
94 for( tHotkey *hk = gpWM_Hotkeys; hk; hk = hk->Next )
97 for( i = 0; i < hk->nKeys; i ++ )
99 if( hk->Keys[i] == Scancode ) continue ;
100 if( _IsKeySet(hk->Keys[i]) ) continue ;
103 _SysDebug("%i/%i satisfied for %s", i, hk->nKeys, hk->Target);
108 WM_Hotkey_FireEvent(hk->Target);
113 gbWM_HasBeenKeyDown = false;
116 void WM_Hotkey_FireEvent(const char *Target)
118 // _SysDebug("WM_Hotkey_FireEvent: (%s)", Target);
119 // - Internal events (Alt-Tab, Close, Maximize, etc...)
120 // TODO: Internal event handling
122 // - Application registered events
123 for( tHotkeyTarget *t = gpWM_HotkeyTargets, *prev=NULL; t; t = t->Next )
125 if( strcmp(t->Name, Target) != 0 )
128 struct sWndMsg_Hotkey info = {.ID=t->Index};
129 WM_SendMessage(NULL, t->Window, WNDMSG_HOTKEY, sizeof(info), &info);
131 // Sort the list by most-recently-used
133 prev->Next = t->Next;
134 t->Next = gpWM_HotkeyTargets;
135 gpWM_HotkeyTargets = t;
142 static void _SetKey(uint32_t sc)
144 // _SysDebug("_SetKey: (%x)", sc);
145 if( sc >= MAX_STATE_SCANCODE ) return;
146 gWM_KeyStates[sc/8] |= 1 << (sc % 8);
148 static void _UnsetKey(uint32_t sc)
150 // _SysDebug("_UnsetKey: (%x)", sc);
151 if( sc >= MAX_STATE_SCANCODE ) return;
152 gWM_KeyStates[sc/8] &= ~(1 << (sc % 8));
154 static int _IsKeySet(uint32_t sc)
156 if( sc >= MAX_STATE_SCANCODE ) return 0;
158 return !!(gWM_KeyStates[sc/8] & (1 << (sc % 8)));