CtrlKbd.cpp

IƱaki Zabala, 11/16/2014 04:46 PM

Download (12.4 KB)

 
1
#include "CtrlCore.h"
2

    
3
NAMESPACE_UPP
4

    
5
#define LLOG(x)  // DLOG(x)
6

    
7
Ptr<Ctrl> Ctrl::focusCtrl;
8
Ptr<Ctrl> Ctrl::focusCtrlWnd;
9
Ptr<Ctrl> Ctrl::lastActiveWnd;
10
Ptr<Ctrl> Ctrl::caretCtrl;
11
Rect      Ctrl::caretRect;
12
bool      Ctrl::ignorekeyup;
13

    
14
Ptr<Ctrl>           Ctrl::defferedSetFocus;
15
Vector< Ptr<Ctrl> > Ctrl::defferedChildLostFocus;
16

    
17

    
18
#ifdef flagSO
19
Ptr<Ctrl> Ctrl::FocusCtrl() { return focusCtrl; }
20
void Ctrl::FocusCtrl(Ptr<Ctrl> fc) { focusCtrl = fc; }
21
#endif
22

    
23
static bool s_hotkey;
24

    
25
void Ctrl::RefreshAccessKeys()
26
{
27
        GuiLock __;
28
        if(GetAccessKeys())
29
                Refresh();
30
        for(Ctrl *ctrl = GetFirstChild(); ctrl; ctrl = ctrl->GetNext())
31
                ctrl->RefreshAccessKeys();
32
}
33

    
34
void Ctrl::RefreshAccessKeysDo(bool vis)
35
{
36
        GuiLock __;
37
        if(GUI_AltAccessKeys() && vis != akv) {
38
                akv = vis;
39
                RefreshAccessKeys();
40
        }
41
}
42

    
43
bool Ctrl::DispatchKey(dword keycode, int count)
44
{
45
        GuiLock __;
46
        if(GUI_AltAccessKeys()) {
47
                bool alt = GetAlt();
48
                Ctrl *c = GetActiveCtrl();
49
                if(c)
50
                        c->RefreshAccessKeysDo(alt);
51
        }
52
//        RLOGBLOCK("Ctrl::DispatchKey");
53
//        RLOG("DispatchKey: focusCtrl = " << FormatIntHex((int)~focusCtrl) << ", wnd = " << FormatIntHex((int)~focusCtrlWnd) << ")");
54
        LLOG("DispatchKey " << keycode << " (0x" << Sprintf("%08x", keycode)
55
                << ", " << GetKeyDesc(keycode) << "), count:" << count
56
                << " focusCtrl:" << UPP::Name(focusCtrl) << " focusCtrlWnd:" << UPP::Name(focusCtrlWnd));
57
        if((keycode & K_KEYUP) && ignorekeyup)
58
        {
59
                ignorekeyup = false;
60
                return true;
61
        }
62
        for(int i = 0; i < keyhook().GetCount(); i++)
63
                if((*keyhook()[i])(focusCtrl, keycode, count))
64
                        return true;
65
        dword k = keycode;
66
        word l = LOWORD(keycode);
67
        if(!(k & K_DELTA) && l >= 32 && l != 127 && GetDefaultCharset() != CHARSET_UNICODE)
68
                k = MAKELONG((word)FromUnicode(l, CHARSET_DEFAULT), HIWORD(keycode));
69
        if(!focusCtrl)
70
                return false;
71
        Ptr<Ctrl> p = focusCtrl;
72
        if(Ini::user_log) {
73
                String kl;
74
                dword k = keycode;
75
                const char *l = "";
76
                if(k < 65536) {
77
                        kl << "CHAR \'" << ToUtf8((wchar)keycode) << "\' (" << keycode << ')';
78
                        l = "  ";
79
                }
80
                else {
81
                        kl << "KEY";
82
                        if(k & K_KEYUP) {
83
                                kl << "UP";
84
                                k &= ~K_KEYUP;
85
                                l = "  ";
86
                        }
87
                        kl << " " << GetKeyDesc(k);
88
                }
89
                USRLOG(l << kl);
90
        }
91
        for(;;) {
92
                LLOG("Trying to DispatchKey: p = " << Desc(p));
93
                if(p->IsEnabled() && p->Key(p->unicode ? keycode : k, count))
94
                {
95
                        LLOG("Ctrl::DispatchKey(" << FormatIntHex(keycode) << ", " << GetKeyDesc(keycode)
96
                                << "): eaten in " << Desc(p));
97
                        if(Ini::user_log)
98
                                USRLOG("  -> " << Desc(p));
99
                        eventCtrl = focusCtrl;
100
                        return true;
101
                }
102
                s_hotkey = true;
103
                if(!p->GetParent()) {
104
                        if(p->HotKey(keycode)) {
105
                                eventCtrl = focusCtrl;
106
                                return true;
107
                        }
108
                        return false;
109
                }
110
                p = p->GetParent();
111
        }
112

    
113
        USRLOG("  key was ignored");
114

    
115
        return false;
116
}
117

    
118
bool Ctrl::HotKey(dword key)
119
{
120
        GuiLock __;
121
        LLOG("HotKey " << GetKeyDesc(key) << " at " << Name(this));
122
        if(!IsEnabled() || !IsVisible()) return false;
123
        for(Ptr<Ctrl> ctrl = firstchild; ctrl; ctrl = ctrl->next)
124
        {
125
                LLOG("Trying HotKey " << GetKeyDesc(key) << " at " << Name(ctrl));
126
                if(ctrl->IsOpen() && ctrl->IsVisible() && ctrl->IsEnabled() && ctrl->HotKey(key))
127
                {
128
                        if(Ini::user_log && s_hotkey) {
129
                                USRLOG("  HOT-> " << UPP::Name(ctrl));
130
                                s_hotkey = false;
131
                        }
132
                        LLOG("ACCEPTED");
133
                        return true;
134
                }
135
        }
136
        return false;
137
}
138

    
139
void Ctrl::DoDeactivate(Ptr<Ctrl> pfocusCtrl, Ptr<Ctrl> nfocusCtrl)
140
{
141
        GuiLock __;
142
        if(pfocusCtrl) {
143
                Ptr<Ctrl> ptop = pfocusCtrl->GetTopCtrl();
144
                Ctrl *ntop = nfocusCtrl ? nfocusCtrl->GetTopCtrl() : NULL;
145
                LLOG("DoDeactivate " << UPP::Name(ptop) << " in favor of " << UPP::Name(ntop));
146
                if(ntop != ptop && !ptop->destroying) {
147
                        ptop->Deactivate();
148
                        if(ptop)
149
                                ptop->StateH(DEACTIVATE);
150
                        if(ptop)
151
                                ptop->RefreshAccessKeysDo(false);
152
                }
153
        }
154
}
155

    
156
void Ctrl::DoKillFocus(Ptr<Ctrl> pfocusCtrl, Ptr<Ctrl> nfocusCtrl)
157
{
158
        GuiLock __;
159
        if(pfocusCtrl && !pfocusCtrl->destroying) {
160
                pfocusCtrl->StateH(FOCUS);
161
                LLOG("LostFocus: " << Name(pfocusCtrl));
162
                pfocusCtrl->LostFocus();
163
        }
164
        if(pfocusCtrl && pfocusCtrl->parent && !pfocusCtrl->parent->destroying)
165
                pfocusCtrl->parent->ChildLostFocus();
166
        SyncCaret();
167
}
168

    
169
void Ctrl::DoSetFocus(Ptr<Ctrl> pfocusCtrl, Ptr<Ctrl> nfocusCtrl, bool activate)
170
{
171
        GuiLock __;
172
        if(activate && focusCtrl == nfocusCtrl && nfocusCtrl) {
173
                Ctrl *top = nfocusCtrl->GetTopCtrl();
174
                if((!pfocusCtrl || pfocusCtrl->GetTopCtrl() != top) && !top->destroying) {
175
                        top->StateH(ACTIVATE);
176
                        top->Activate();
177
                        top->RefreshAccessKeysDo(top->VisibleAccessKeys());
178
                }
179
        }
180

    
181
        if(focusCtrl == nfocusCtrl && nfocusCtrl && !nfocusCtrl->destroying) {
182
                nfocusCtrl->GotFocus();
183
                nfocusCtrl->StateH(FOCUS);
184
        }
185
        if(focusCtrl == nfocusCtrl && nfocusCtrl && nfocusCtrl->parent &&
186
           !nfocusCtrl->parent->destroying)
187
                nfocusCtrl->parent->ChildGotFocus();
188
        SyncCaret();
189
}
190

    
191
/*
192
bool Ctrl::SetFocus0(bool activate)
193
{
194
        GuiLock __;
195
        if(IsUsrLog())
196
                UsrLogT(6, String().Cat() << "SETFOCUS " << Desc(this));
197
        LLOG("Ctrl::SetFocus " << Desc(this));
198
        LLOG("focusCtrlWnd " << UPP::Name(focusCtrlWnd));
199
        LLOG("Ctrl::SetFocus0 -> deferredSetFocus = NULL; was: " << UPP::Name(defferedSetFocus));
200
        defferedSetFocus = NULL;
201
        if(focusCtrl == this) return true;
202
        if(!IsOpen() || !IsEnabled() || !IsVisible()) return false;
203
        Ptr<Ctrl> pfocusCtrl = focusCtrl;
204
        Ptr<Ctrl> topwindow = GetTopWindow();
205
        Ptr<Ctrl> topctrl = GetTopCtrl();
206
        Ptr<Ctrl> _this = this;
207
        if(!topwindow) topwindow = topctrl;
208
        LLOG("SetFocus -> SetWndFocus: topwindow = " << UPP::Name(topwindow) << ", focusCtrlWnd = " << UPP::Name(focusCtrlWnd));
209
        if(!topwindow->HasWndFocus() && !topwindow->SetWndFocus()) return false;// cxl 31.1.2004
210
        if(activate) // Dolik/fudadmin 2011-5-1
211
                topctrl->SetWndForeground();  // cxl 2007-4-27
212
        LLOG("SetFocus -> focusCtrl = this: " << FormatIntHex(this) << ", _this = " << FormatIntHex(~_this) << ", " << UPP::Name(_this));
213
        focusCtrl = _this;
214
        focusCtrlWnd = topwindow;
215
        DoKillFocus(pfocusCtrl, _this);
216
        LLOG("SetFocus 2");
217
        DoDeactivate(pfocusCtrl, _this);
218
        DoSetFocus(pfocusCtrl, _this, activate);
219
        if(topwindow)
220
                lastActiveWnd = topwindow;
221
        return true;
222
}
223
*/
224

    
225
bool Ctrl::SetFocus0(bool activate)
226
{
227
        GuiLock __;
228
        USRLOG("      SETFOCUS " << Desc(this));
229
        LLOG("Ctrl::SetFocus " << Desc(this));
230
        LLOG("focusCtrlWnd " << UPP::Name(focusCtrlWnd));
231
        LLOG("Ctrl::SetFocus0 -> deferredSetFocus = NULL; was: " << UPP::Name(defferedSetFocus));
232
        defferedSetFocus = NULL;
233
        if(focusCtrl == this) return true;
234
        if(!IsOpen() || !IsEnabled() || !IsVisible()) return false;
235
        Ptr<Ctrl> pfocusCtrl = focusCtrl;
236
        Ptr<Ctrl> topwindow = GetTopWindow();
237
        Ptr<Ctrl> topctrl = GetTopCtrl();
238
        Ptr<Ctrl> _this = this;
239
        if(!topwindow) topwindow = topctrl;
240
        LLOG("SetFocus -> SetWndFocus: topwindow = " << UPP::Name(topwindow) << ", focusCtrlWnd = " << UPP::Name(focusCtrlWnd));
241
        if(!topwindow->HasWndFocus() && !topwindow->SetWndFocus()) return false;// cxl 31.1.2004
242
#ifdef PLATFORM_OSX11 // ugly temporary hack - popups not behaving right in MacOS
243
        // before 2012-9-2 was #ifdef GUI_X11, but that caused issues in most linux distros (cxl)
244
        // as parent window of popup always manages focus/keyboard for popup in X11
245
        if(activate) // Dolik/fudadmin 2011-5-1
246
                topctrl->SetWndForeground();
247
#else
248
        topwindow->SetWndForeground();  // cxl 2007-4-27
249
#endif
250
        LLOG("SetFocus -> focusCtrl = this: " << FormatIntHex(this) << ", _this = " << FormatIntHex(~_this) << ", " << UPP::Name(_this));
251
        focusCtrl = _this;
252
        focusCtrlWnd = topwindow;
253
        DoKillFocus(pfocusCtrl, _this);
254
        LLOG("SetFocus 2");
255
        DoDeactivate(pfocusCtrl, _this);
256
        DoSetFocus(pfocusCtrl, _this, activate);
257
        if(topwindow)
258
                lastActiveWnd = topwindow;
259
        return true;
260
}
261

    
262

    
263
bool Ctrl::SetFocus()
264
{
265
        GuiLock __;
266
        LLOG("Ctrl::SetFocus(" << Name() << ")");
267
        return SetFocus0(true);
268
}
269

    
270
void Ctrl::ActivateWnd()
271
{
272
        GuiLock __;
273
        // notification, don't set physical focus here
274
        LLOG("ActivateWnd " << Name());
275
        Ptr<Ctrl> nfocusCtrl = this;
276
        Ptr<Ctrl> pfocusCtrl = focusCtrl;
277
        LLOG("About to set focus: " << UPP::Name(nfocusCtrl));
278
        DoDeactivate(pfocusCtrl, nfocusCtrl);
279
        focusCtrl = nfocusCtrl;
280
        focusCtrlWnd = this;
281
        DoKillFocus(pfocusCtrl, nfocusCtrl);
282
        DoSetFocus(pfocusCtrl, nfocusCtrl, true);
283
        LLOG("Focus: " << UPP::Name(focusCtrl) << " FocusWnd:" << UPP::Name(focusCtrlWnd));
284
}
285

    
286
void Ctrl::SetFocusWnd()
287
{
288
        GuiLock __;
289
        // notification, don't set host platform focus here
290
        LLOG("Ctrl::SetFocusWnd");
291
        if(focusCtrlWnd != this) {
292
                LLOG("Ctrl::SetFocusWnd->ActivateWnd");
293
                ActivateWnd();
294
        }
295
}
296

    
297
void Ctrl::KillFocusWnd()
298
{
299
        GuiLock __;
300
        // notification, don't set host platform focus here
301
        LLOG("KillFocusWnd " << Name());
302
        if(this == ~focusCtrlWnd) {
303
                Ptr<Ctrl> pfocusCtrl = focusCtrl;
304
                DoDeactivate(pfocusCtrl, NULL);
305
                focusCtrl = focusCtrlWnd = NULL;
306
                DoKillFocus(pfocusCtrl, NULL);
307
        }
308
}
309

    
310
void Ctrl::ClickActivateWnd()
311
{
312
        GuiLock __;
313
        LLOG("Ctrl::ClickActivateWnd");
314
        if(this == ~focusCtrlWnd && focusCtrl && focusCtrl->GetTopCtrl() != this) {
315
                LLOG("Ctrl::ClickActivateWnd -> ActivateWnd");
316
                ActivateWnd();
317
        }
318
}
319

    
320
void Ctrl::DefferedFocusSync()
321
{
322
        GuiLock __;
323
        while(defferedChildLostFocus.GetCount() || defferedSetFocus) {
324
                LLOG("Ctrl::DeferredFocusSync, defferedSetFocus = " << UPP::Name(defferedSetFocus));
325
                Vector< Ptr<Ctrl> > b = pick(defferedChildLostFocus);
326
                defferedChildLostFocus.Clear();
327
                for(int i = 0; i < b.GetCount(); i++)
328
                        if(b[i]) {
329
                                LLOG("Ctrl::DeferredFocusSync -> ChildLostFocus " << UPP::Name(b[i]));
330
                                b[i]->ChildLostFocus();
331
                        }
332
                if(defferedSetFocus) {
333
                        LLOG("Ctrl::DeferredFocusSync -> SetFocus " << UPP::Name(defferedSetFocus));
334
                        defferedSetFocus->SetFocus();
335
                }
336
                defferedSetFocus = NULL;
337
                SyncCaret();
338
        }
339
}
340

    
341
void Ctrl::RefreshCaret()
342
{
343
        GuiLock __;
344
        if(caretCtrl)
345
                caretCtrl->Refresh(caretCtrl->caretx, caretCtrl->carety,
346
                                   caretCtrl->caretcx, caretCtrl->caretcy);
347
}
348

    
349
Ctrl *Ctrl::GetActiveWindow()
350
{
351
        GuiLock __;
352
        Ctrl *q = GetActiveCtrl();
353
        return q ? q->GetTopWindow() : NULL;
354
}
355

    
356
bool  Ctrl::HasFocusDeep() const
357
{
358
        GuiLock __;
359
        if(HasFocus() || HasChildDeep(FocusCtrl())) return true;
360
        Ctrl *a = GetActiveCtrl();
361
        if(!a || !a->IsPopUp()) return false;
362
        a = a->GetOwnerCtrl();
363
        return a && HasChildDeep(a);
364
}
365

    
366
String GetKeyDesc(dword key)
367
{
368
        String desc;
369
//        key &= 0xFFFF;
370

    
371
        if(key == 0)
372
                return desc;
373

    
374
        if(key & K_CTRL)  desc << t_("key\vCtrl+");
375
        if(key & K_ALT)   desc << t_("key\vAlt+");
376
        if(key & K_SHIFT) desc << t_("key\vShift+");
377
        if(key & K_KEYUP) desc << t_("key\vUP ");
378

    
379

    
380
        key &= ~(K_CTRL | K_ALT | K_SHIFT | K_KEYUP);
381
        if(key < K_DELTA && key > 32 && key != K_DELETE)
382
                return desc + ToUtf8((wchar)key);
383
        if(key >= K_NUMPAD0 && key <= K_NUMPAD9)
384
                desc << "Num " << (char)(key - K_NUMPAD0 + '0');
385
        else if(key >= K_0 && key <= K_9)
386
                desc << (char)('0' + key - K_0);
387
        else if(key >= K_A && key <= K_Z)
388
                desc << (char)('A' + key - K_A);
389
        else if(key >= K_F1 && key <= K_F12)
390
                desc << Format("F%d", (int)key - K_F1 + 1);
391
        else {
392
                static struct {
393
                        dword key;
394
                        const char *name;
395
                } nkey[] = {
396
                        { K_TAB, tt_("key\vTab") }, { K_SPACE, tt_("key\vSpace") },
397
                        { K_RETURN, tt_("key\vEnter") }, { K_BACKSPACE, tt_("key\vBackspace") },
398
                        { K_CAPSLOCK, tt_("key\vCaps Lock") }, { K_ESCAPE, tt_("key\vEsc") },
399
                        { K_PAGEUP, tt_("key\vPage Up") }, { K_PAGEDOWN, tt_("key\vPage Down") },
400
                        { K_END, tt_("key\vEnd") }, { K_HOME, tt_("key\vHome") },
401
                        { K_LEFT, tt_("key\vLeft") }, { K_UP, tt_("key\vUp") },
402
                        { K_RIGHT, tt_("key\vRight") }, { K_DOWN, tt_("key\vDown") },
403
                        { K_INSERT, tt_("key\vInsert") }, { K_DELETE, tt_("key\vDelete") },{ K_BREAK, tt_("key\vBreak") },
404
                        { K_MULTIPLY, tt_("key\vNum[*]") }, { K_ADD, tt_("key\vNum[+]") }, { K_SUBTRACT, tt_("key\vNum[-]") }, { K_DIVIDE, tt_("key\vNum[/]") },
405
                        { K_ALT_KEY, tt_("key\vAlt") }, { K_SHIFT_KEY, tt_("key\vShift") }, { K_CTRL_KEY, tt_("key\vCtrl") },
406
                        { K_PLUS, tt_("key\v[+]") }, { K_MINUS, tt_("key\v[-]") }, { K_COMMA, tt_("key\v[,]") }, { K_PERIOD, tt_("key\v[.]") },
407
                        { K_SEMICOLON, tt_("key\v[;]") }, { K_SLASH, tt_("key\v[/]") }, { K_GRAVE, tt_("key\v[`]") }, { K_LBRACKET, tt_("key\v[[]") },
408
                        { K_BACKSLASH, tt_("key\v[\\]") }, { K_RBRACKET, tt_("key\v[]]") }, { K_QUOTEDBL, tt_("key\v[']") },
409
                        { 0, NULL }
410
                };
411
                for(int i = 0; nkey[i].key; i++)
412
                        if(nkey[i].key == key) {
413
                                desc << GetLngString(nkey[i].name);
414
                                return desc;
415
                        }
416
                desc << Format("%04x", (int)key);
417
        }
418
        return desc;
419
}
420

    
421
END_UPP_NAMESPACE