Usermode/AxWin3 - Fixed undefined memory usage
[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         h->Next = NULL;
45         if( gpWM_Hotkeys )
46                 gpWM_Hotkeys->Next = h;
47         gpWM_Hotkeys = h;
48 }
49
50 void WM_Hotkey_RegisterAction(const char *ActionName, tWindow *Target, uint16_t Index)
51 {
52         // Check for a duplicate registration
53         for( tHotkeyTarget *t = gpWM_HotkeyTargets; t; t = t->Next )
54         {
55                 if( strcmp(t->Name, ActionName) != 0 )
56                         continue ;
57                 // Duplicate!
58                 return ;
59         }
60
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);
65         t->Window = Target;
66         t->Index = Index;
67         t->Next = NULL;
68
69         // TODO: Register to be informed when the window dies/closes?
70
71         // Append to list
72         if( gpWM_HotkeyTargets ) {
73                 gpWM_HotkeyTargets_Last->Next = t;
74         }
75         else {
76                 gpWM_HotkeyTargets = t;
77         }
78         gpWM_HotkeyTargets_Last = t;
79 }
80
81 void WM_Hotkey_KeyDown(uint32_t Scancode)
82 {
83         _SetKey(Scancode);
84         gbWM_HasBeenKeyDown = true;
85 }
86
87 void WM_Hotkey_KeyUp(uint32_t Scancode)
88 {
89         _UnsetKey(Scancode);
90
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 )
94                 return ;
95
96         for( tHotkey *hk = gpWM_Hotkeys; hk; hk = hk->Next )
97         {
98                 int i;
99                 for( i = 0; i < hk->nKeys; i ++ )
100                 {
101                         if( hk->Keys[i] == Scancode )   continue ;
102                         if( _IsKeySet(hk->Keys[i]) )    continue ;
103                         break;
104                 }
105                 _SysDebug("%i/%i satisfied for %s", i, hk->nKeys, hk->Target);
106                 if( i != hk->nKeys )
107                         continue ;
108                 
109                 // Fire shortcut
110                 WM_Hotkey_FireEvent(hk->Target);
111
112                 break;
113         }
114         
115         gbWM_HasBeenKeyDown = false;
116 }
117
118 void WM_Hotkey_FireEvent(const char *Target)
119 {
120 //      _SysDebug("WM_Hotkey_FireEvent: (%s)", Target);
121         // - Internal events (Alt-Tab, Close, Maximize, etc...)
122         // TODO: Internal event handling
123         
124         // - Application registered events
125         for( tHotkeyTarget *t = gpWM_HotkeyTargets, *prev=NULL; t; t = t->Next )
126         {
127                 if( strcmp(t->Name, Target) != 0 )
128                         continue ;
129
130                 struct sWndMsg_Hotkey   info = {.ID=t->Index};
131                 WM_SendMessage(NULL, t->Window, WNDMSG_HOTKEY, sizeof(info), &info);
132
133                 // Sort the list by most-recently-used
134                 if(prev != NULL) {
135                         prev->Next = t->Next;
136                         t->Next = gpWM_HotkeyTargets;
137                         gpWM_HotkeyTargets = t;
138                 }
139
140                 return ;
141         }
142 }
143
144 static void _SetKey(uint32_t sc)
145 {
146 //      _SysDebug("_SetKey: (%x)", sc);
147         if( sc >= MAX_STATE_SCANCODE )  return;
148         gWM_KeyStates[sc/8] |= 1 << (sc % 8);
149 }
150 static void _UnsetKey(uint32_t sc)
151 {
152 //      _SysDebug("_UnsetKey: (%x)", sc);
153         if( sc >= MAX_STATE_SCANCODE )  return;
154         gWM_KeyStates[sc/8] &= ~(1 << (sc % 8));
155 }
156 static int _IsKeySet(uint32_t sc)
157 {
158         if( sc >= MAX_STATE_SCANCODE )  return 0;
159
160         return !!(gWM_KeyStates[sc/8] & (1 << (sc % 8)));
161 }
162

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