X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Usermode%2FApplications%2Faxwin3_src%2FWM%2Fwm_hotkeys.c;fp=Usermode%2FApplications%2Faxwin3_src%2FWM%2Fwm_hotkeys.c;h=3fbe4f762342fdac0b3f57473bf38f993488e5ce;hb=305bad29632e0cf47307e010ae7dea55617f2dfd;hp=0000000000000000000000000000000000000000;hpb=88547c29ae10d9bd709b7382a4bf78d94f0b2be4;p=tpg%2Facess2.git diff --git a/Usermode/Applications/axwin3_src/WM/wm_hotkeys.c b/Usermode/Applications/axwin3_src/WM/wm_hotkeys.c new file mode 100644 index 00000000..3fbe4f76 --- /dev/null +++ b/Usermode/Applications/axwin3_src/WM/wm_hotkeys.c @@ -0,0 +1,150 @@ +/* + * Acess2 Window Manager v3 + * - By John Hodge (thePowersGang) + * + * wm_hotkeys.c + * - Hotkey and key shortcut code + */ +#include +#include +#include +#include +#include + +#define true 1 +#define false 0 + +#define MAX_STATE_SCANCODE 256 + +// === GOBALS === +char gbWM_HasBeenKeyDown = true; +uint8_t gWM_KeyStates[MAX_STATE_SCANCODE/8]; +tHotkey *gpWM_Hotkeys; +tHotkeyTarget *gpWM_HotkeyTargets; +tHotkeyTarget *gpWM_HotkeyTargets_Last; + +// === PROTOTYPES === +static void _SetKey(uint32_t sc); +static void _UnsetKey(uint32_t sc); +static int _IsKeySet(uint32_t sc); +void WM_Hotkey_FireEvent(const char *Target); + +// === CODE === +void WM_Hotkey_Register(int nKeys, uint32_t *Keys, const char *ActionName) +{ + // TODO: Duplicate detection + + // Create new structure + tHotkey *h = malloc(sizeof(tHotkey) + nKeys * sizeof(uint32_t) + strlen(ActionName) + 1); + h->nKeys = nKeys; + h->Target = (void*)( h->Keys + nKeys ); + strcpy((char*)h->Target, ActionName); + memcpy(h->Keys, Keys, nKeys * sizeof(uint32_t)); +} + +void WM_Hotkey_RegisterAction(const char *ActionName, tWindow *Target, uint16_t Index) +{ + // Check for a duplicate registration + for( tHotkeyTarget *t = gpWM_HotkeyTargets; t; t = t->Next ) + { + if( strcmp(t->Name, ActionName) != 0 ) + continue ; + // Duplicate! + return ; + } + + // Create new structure + tHotkeyTarget *t = malloc(sizeof(tHotkeyTarget) + strlen(ActionName) + 1); + t->Name = (void*)(t + 1); + strcpy((char*)t->Name, ActionName); + t->Window = Target; + t->Index = Index; + + // TODO: Register to be informed when the window dies/closes? + + // Append to list + if( gpWM_HotkeyTargets ) { + gpWM_HotkeyTargets_Last->Next = t; + } + else { + gpWM_HotkeyTargets = t; + } + gpWM_HotkeyTargets_Last = t; +} + +void WM_Hotkey_KeyDown(uint32_t Scancode) +{ + _SetKey(Scancode); + gbWM_HasBeenKeyDown = true; +} + +void WM_Hotkey_KeyUp(uint32_t Scancode) +{ + _UnsetKey(Scancode); + + if( !gbWM_HasBeenKeyDown ) + return ; + + for( tHotkey *hk = gpWM_Hotkeys; hk; hk = hk->Next ) + { + int i; + for( i = 0; i < hk->nKeys; i ++ ) + { + if( hk->Keys[i] == Scancode ) continue ; + if( _IsKeySet(hk->Keys[i]) ) continue ; + break; + } + if( i == hk->nKeys ) + continue ; + + // Fire shortcut + WM_Hotkey_FireEvent(hk->Target); + + break; + } + + gbWM_HasBeenKeyDown = false; +} + +void WM_Hotkey_FireEvent(const char *Target) +{ + // - Internal events (Alt-Tab, Close, Maximize, etc...) + // TODO: Internal event handling + + // - Application registered events + for( tHotkeyTarget *t = gpWM_HotkeyTargets, *prev=NULL; t; t = t->Next ) + { + if( strcmp(t->Name, Target) != 0 ) + continue ; + + struct sWndMsg_Hotkey info = {.ID=t->Index}; + WM_SendMessage(NULL, t->Window, WNDMSG_HOTKEY, sizeof(info), &info); + + // Sort the list by most-recently-used + if(prev != NULL) { + prev->Next = t->Next; + t->Next = gpWM_HotkeyTargets; + gpWM_HotkeyTargets = t; + } + + return ; + } +} + +static void _SetKey(uint32_t sc) +{ + if( sc >= MAX_STATE_SCANCODE ) return; + gWM_KeyStates[sc/8] |= 1 << (sc % 8); +} +static void _UnsetKey(uint32_t sc) +{ + if( sc >= MAX_STATE_SCANCODE ) return; + gWM_KeyStates[sc/8] &= ~(1 << (sc % 8)); +} +static int _IsKeySet(uint32_t sc) +{ + if( sc >= MAX_STATE_SCANCODE ) return 0; + + return !!(gWM_KeyStates[sc/8] & (1 << (sc % 8))); +} +