Usermode/AxWin3 - Wokring on hotkeys
[tpg/acess2.git] / Usermode / Applications / axwin3_src / WM / wm_hotkeys.c
1 /*
2  * Acess2 Window Manager v3
3  * - By John Hodge (thePowersGang)
4  * 
5  * wm_hotkeys.c
6  * - Hotkey and key shortcut code
7  */
8 #include <common.h>
9 #include <wm_internals.h>
10 #include <wm_messages.h>
11 #include <wm_hotkeys.h>
12 #include <string.h>
13
14 #define true    1
15 #define false   0
16
17 #define MAX_STATE_SCANCODE      256
18
19 // === GOBALS ===
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;
25
26 // === PROTOTYPES ===
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);
31
32 // === CODE ===
33 void WM_Hotkey_Register(int nKeys, uint32_t *Keys, const char *ActionName)
34 {
35         // TODO: Duplicate detection
36         
37         // Create new structure
38         tHotkey *h = malloc(sizeof(tHotkey) + nKeys * sizeof(uint32_t) + strlen(ActionName) + 1);
39         h->nKeys = nKeys;
40         h->Target = (void*)( h->Keys + nKeys );
41         strcpy((char*)h->Target, ActionName);
42         memcpy(h->Keys, Keys, nKeys * sizeof(uint32_t));
43 }
44
45 void WM_Hotkey_RegisterAction(const char *ActionName, tWindow *Target, uint16_t Index)
46 {
47         // Check for a duplicate registration
48         for( tHotkeyTarget *t = gpWM_HotkeyTargets; t; t = t->Next )
49         {
50                 if( strcmp(t->Name, ActionName) != 0 )
51                         continue ;
52                 // Duplicate!
53                 return ;
54         }
55
56         // Create new structure
57         tHotkeyTarget   *t = malloc(sizeof(tHotkeyTarget) + strlen(ActionName) + 1);
58         t->Name = (void*)(t + 1);
59         strcpy((char*)t->Name, ActionName);
60         t->Window = Target;
61         t->Index = Index;
62
63         // TODO: Register to be informed when the window dies/closes?
64
65         // Append to list
66         if( gpWM_HotkeyTargets ) {
67                 gpWM_HotkeyTargets_Last->Next = t;
68         }
69         else {
70                 gpWM_HotkeyTargets = t;
71         }
72         gpWM_HotkeyTargets_Last = t;
73 }
74
75 void WM_Hotkey_KeyDown(uint32_t Scancode)
76 {
77         _SetKey(Scancode);
78         gbWM_HasBeenKeyDown = true;
79 }
80
81 void WM_Hotkey_KeyUp(uint32_t Scancode)
82 {
83         _UnsetKey(Scancode);
84
85         if( !gbWM_HasBeenKeyDown )
86                 return ;
87
88         for( tHotkey *hk = gpWM_Hotkeys; hk; hk = hk->Next )
89         {
90                 int i;
91                 for( i = 0; i < hk->nKeys; i ++ )
92                 {
93                         if( hk->Keys[i] == Scancode )   continue ;
94                         if( _IsKeySet(hk->Keys[i]) )    continue ;
95                         break;
96                 }
97                 if( i == hk->nKeys )
98                         continue ;
99                 
100                 // Fire shortcut
101                 WM_Hotkey_FireEvent(hk->Target);
102
103                 break;
104         }
105         
106         gbWM_HasBeenKeyDown = false;
107 }
108
109 void WM_Hotkey_FireEvent(const char *Target)
110 {
111         // - Internal events (Alt-Tab, Close, Maximize, etc...)
112         // TODO: Internal event handling
113         
114         // - Application registered events
115         for( tHotkeyTarget *t = gpWM_HotkeyTargets, *prev=NULL; t; t = t->Next )
116         {
117                 if( strcmp(t->Name, Target) != 0 )
118                         continue ;
119
120                 struct sWndMsg_Hotkey   info = {.ID=t->Index};
121                 WM_SendMessage(NULL, t->Window, WNDMSG_HOTKEY, sizeof(info), &info);
122
123                 // Sort the list by most-recently-used
124                 if(prev != NULL) {
125                         prev->Next = t->Next;
126                         t->Next = gpWM_HotkeyTargets;
127                         gpWM_HotkeyTargets = t;
128                 }
129
130                 return ;
131         }
132 }
133
134 static void _SetKey(uint32_t sc)
135 {
136         if( sc >= MAX_STATE_SCANCODE )  return;
137         gWM_KeyStates[sc/8] |= 1 << (sc % 8);
138 }
139 static void _UnsetKey(uint32_t sc)
140 {
141         if( sc >= MAX_STATE_SCANCODE )  return;
142         gWM_KeyStates[sc/8] &= ~(1 << (sc % 8));
143 }
144 static int _IsKeySet(uint32_t sc)
145 {
146         if( sc >= MAX_STATE_SCANCODE )  return 0;
147
148         return !!(gWM_KeyStates[sc/8] & (1 << (sc % 8)));
149 }
150

UCC git Repository :: git.ucc.asn.au