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

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