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);
69 // TODO: Register to be informed when the window dies/closes?
72 if( gpWM_HotkeyTargets ) {
73 gpWM_HotkeyTargets_Last->Next = t;
76 gpWM_HotkeyTargets = t;
78 gpWM_HotkeyTargets_Last = t;
81 void WM_Hotkey_KeyDown(uint32_t Scancode)
84 gbWM_HasBeenKeyDown = true;
87 void WM_Hotkey_KeyUp(uint32_t Scancode)
91 // Ensure that hotkeys are triggered on the longest sequence
92 // (so Win-Shift-R doesn't trigger Win-R if shift is released)
93 if( !gbWM_HasBeenKeyDown )
96 for( tHotkey *hk = gpWM_Hotkeys; hk; hk = hk->Next )
99 for( i = 0; i < hk->nKeys; i ++ )
101 if( hk->Keys[i] == Scancode ) continue ;
102 if( _IsKeySet(hk->Keys[i]) ) continue ;
105 _SysDebug("%i/%i satisfied for %s", i, hk->nKeys, hk->Target);
110 WM_Hotkey_FireEvent(hk->Target);
115 gbWM_HasBeenKeyDown = false;
118 void WM_Hotkey_FireEvent(const char *Target)
120 // _SysDebug("WM_Hotkey_FireEvent: (%s)", Target);
121 // - Internal events (Alt-Tab, Close, Maximize, etc...)
122 // TODO: Internal event handling
124 // - Application registered events
125 for( tHotkeyTarget *t = gpWM_HotkeyTargets, *prev=NULL; t; t = t->Next )
127 if( strcmp(t->Name, Target) != 0 )
130 struct sWndMsg_Hotkey info = {.ID=t->Index};
131 WM_SendMessage(NULL, t->Window, WNDMSG_HOTKEY, sizeof(info), &info);
133 // Sort the list by most-recently-used
135 prev->Next = t->Next;
136 t->Next = gpWM_HotkeyTargets;
137 gpWM_HotkeyTargets = t;
144 static void _SetKey(uint32_t sc)
146 // _SysDebug("_SetKey: (%x)", sc);
147 if( sc >= MAX_STATE_SCANCODE ) return;
148 gWM_KeyStates[sc/8] |= 1 << (sc % 8);
150 static void _UnsetKey(uint32_t sc)
152 // _SysDebug("_UnsetKey: (%x)", sc);
153 if( sc >= MAX_STATE_SCANCODE ) return;
154 gWM_KeyStates[sc/8] &= ~(1 << (sc % 8));
156 static int _IsKeySet(uint32_t sc)
158 if( sc >= MAX_STATE_SCANCODE ) return 0;
160 return !!(gWM_KeyStates[sc/8] & (1 << (sc % 8)));