-
Notifications
You must be signed in to change notification settings - Fork 0
/
StdWindow.cpp
3284 lines (2445 loc) · 92.2 KB
/
StdWindow.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#include "StdFuncs.h"
#include "StdApplication.h"
#include "StdGadgets.h"
#include "StdWindow.h"
#include <ctype.h>
#include <string.h>
#ifdef __amigaos__
#include "StdReaction.h"
#include "Amiga/AmiMenus.h"
#include <proto/gadtools.h>
#include <proto/graphics.h>
#include <proto/utility.h>
#include <classes/window.h>
#include <intuition/imageclass.h>
#ifdef __amigaos4__
#include <intuition/gui.h>
#endif /* __amigaos4__ */
#elif defined(QT_GUI_LIB)
#include "Qt/QtAction.h"
#include "Qt/QtWindow.h"
#include <QtGui/QKeyEvent>
#include <QtGui/QScreen>
#include <QtWidgets/QApplication>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QVBoxLayout>
#elif defined(WIN32)
#include "StdRendezvous.h"
#include <VersionHelpers.h>
#endif /* WIN32 */
#if defined(WIN32) && !defined(QT_GUI_LIB)
/* Array of key mappings for mapping Windows keys onto standard keys */
static const SKeyMapping g_acoKeyMap[] =
{
{ STD_KEY_SHIFT, VK_SHIFT }, { STD_KEY_CONTROL, VK_CONTROL }, { STD_KEY_BACKSPACE, VK_BACK },
{ STD_KEY_ENTER, VK_RETURN }, { STD_KEY_UP, VK_UP }, { STD_KEY_DOWN, VK_DOWN },
{ STD_KEY_LEFT, VK_LEFT }, { STD_KEY_RIGHT, VK_RIGHT }, { STD_KEY_HOME, VK_HOME },
{ STD_KEY_END, VK_END }, { STD_KEY_PGUP, VK_PRIOR }, { STD_KEY_PGDN, VK_NEXT }, { STD_KEY_ESC, VK_ESCAPE },
{ STD_KEY_DELETE, VK_DELETE }, { STD_KEY_TAB, VK_TAB }, { STD_KEY_F1, VK_F1 }, { STD_KEY_F2, VK_F2 },
{ STD_KEY_F3, VK_F3 }, { STD_KEY_F4, VK_F4 }, { STD_KEY_F5, VK_F5 }, { STD_KEY_F6, VK_F6 },
{ STD_KEY_F7, VK_F7 }, { STD_KEY_F8, VK_F8 }, { STD_KEY_F9, VK_F9 }, { STD_KEY_F10, VK_F10 },
{ STD_KEY_F11, VK_F11 }, { STD_KEY_F12, VK_F12 }
};
#define NUM_KEYMAPPINGS (sizeof(g_acoKeyMap) / sizeof(struct SKeyMapping))
CWindow *CWindow::m_poActiveDialog; /* Ptr to currently active dialog, if any */
#endif /* defined(WIN32) && !defined(QT_GUI_LIB) */
TBool CWindow::m_bAltPressed; /* ETrue if alt is currently pressed */
TBool CWindow::m_bCtrlPressed; /* ETrue if ctrl is currently pressed */
TBool CWindow::m_bMetaPressed; /* ETrue if meta is currently pressed */
TBool CWindow::m_bShiftPressed; /* ETrue if shift is currently pressed */
TBool CWindow::m_bIsActive; /* ETrue if the window is currently active */
#ifdef __amigaos__
/* Written: Saturday 20-Nov-2010 11:05 am */
ULONG CWindow::IDCMPFunction(struct Hook *a_poHook, Object * /*a_poObject*/, struct IntuiMessage *a_poIntuiMessage)
{
struct TagItem *TagItem;
CStdGadgetLayout *LayoutGadget;
CWindow *Window;
/* Get a ptr to the Window associated with the hook */
Window = (CWindow *) a_poHook->h_Data;
#ifdef __amigaos4__
/* If this is a mouse wheel event then convert the delta to a Qt/Windows style reading */
/* (+/- 120 per notch) and notify the window */
if (a_poIntuiMessage->Class == IDCMP_EXTENDEDMOUSE)
{
struct IntuiWheelData *IntuiWheelData = (struct IntuiWheelData *) a_poIntuiMessage->IAddress;
Window->HandleWheelEvent(-IntuiWheelData->WheelY * 120);
}
else
#endif /* __amigaos4__ */
/* If this is a message from a BOOPSI object saying that it has been updated, find the object and */
/* map it onto its matching gadget and call the gadget's Updated() function */
if (a_poIntuiMessage->Class == IDCMP_IDCMPUPDATE)
{
/* Get the gadget's unique ID */
if ((TagItem = FindTagItem(GA_ID, (struct TagItem *) a_poIntuiMessage->IAddress)) != NULL)
{
/* Recursively search through the window's tree of layout gadgets and search each one to see */
/* if it contains a gadget that represents the Reaction slider that was just moved */
if ((LayoutGadget = Window->m_poRootLayout) != NULL)
{
LayoutGadget->SendUpdate((void *) TagItem->ti_Data, 0);
}
}
/* It could be that the gadget that was updated has requested a redraw, which will be */
/* indicated by one or more dirty regions being present. Check for this and perform a */
/* redraw so that the redraw happens immediately */
if (Window->m_oDirtyRegions.size() > 0)
{
Window->InternalRedraw();
}
}
return(DOSTRUE);
}
#elif defined(QT_GUI_LIB)
/**
* CQtCentralWidget constructor.
* Simply initialisaes the central widget with a ptr to the generic framework
* window that owns it.
*
* @date Friday 08-Mar-2013 9:13, Leo's house in Vienna
* @param a_poWindow Ptr to parent framework window ptr to be saved
*/
CQtCentralWidget::CQtCentralWidget(CWindow *a_poWindow) : QWidget(a_poWindow->m_poWindow)
{
m_poWindow = a_poWindow;
}
/**
* Qt helper function to receive paint events.
* This function is called whenever Qt performs a repaint of the window and will pass
* the event along to the generic CWindow::draw() function, so that client code can
* perform its custom drawing.
*
* @date Thursday 06-Sep-2012 1:35 pm
* @param a_poPaintEvent Ptr to a structure containing information about the event
*/
void CQtCentralWidget::paintEvent(QPaintEvent *a_poPaintEvent)
{
QRect Rect = a_poPaintEvent->rect();
/* Pass the request along to the underlying framework window. Note that QRect::bottom() */
/* will return the inclusive bottom pixel but our framework works with exclusive pixel */
/* positions. We therefore need to calculate that position using QRect::height() */
m_poWindow->draw(Rect.top(), (Rect.top() + Rect.height()));
}
#elif defined(WIN32)
/* Written: Saturday 08-May-2010 4:43 pm */
LRESULT CALLBACK CWindow::WindowProc(HWND a_poWindow, UINT a_uiMessage, WPARAM a_oWParam, LPARAM a_oLParam)
{
bool Result;
TBool Checked;
TInt Command, Index, Key;
TBool Handled;
HKL KeyboardLayout;
LRESULT RetVal;
const struct SStdMenuItem *MenuItem;
CWindow *Window;
COPYDATASTRUCT *CopyData;
/* Return 0 by default for processed messages */
RetVal = 0;
/* Get the ptr to the C++ class associated with this window from the window word */
Window = (CWindow *) GetWindowLongPtr(a_poWindow, GWLP_USERDATA);
switch (a_uiMessage)
{
case WM_ACTIVATE :
{
/* If there is an active dialog then check to see if the window was just activated */
/* by any other mechanism than a mouse click. If so then this means that the */
/* application was switched away from and then back to so we want to re-activate */
/* the previously active dialog */
if (m_poActiveDialog)
{
if ((a_oWParam == WA_ACTIVE) && (m_poActiveDialog))
{
m_poActiveDialog->Activate();
}
/* Otherwise the window was clicked on so indicate that there is no longer an */
/* active dialog. This must be done here and not in the dialog's WM_ACTIVATE */
/* as the dialog has no knowledge of how it is being deactivated */
else
{
m_poActiveDialog = NULL;
}
}
/* Window focus is changing so let the client know that the window is activating */
/* or deactivating */
Window->Activated(a_oWParam == WA_ACTIVE);
/* Forget about the modifier keypresses as we won't get a key up event for them due */
/* to the window no longer being active */
m_bAltPressed = m_bCtrlPressed = m_bShiftPressed = EFalse;
break;
}
case WM_SETFOCUS :
{
/* Create a native Windows cursor and if successful, show it and position it at its assigned */
/* X and Y positions */
if (CreateCaret(Window->m_poWindow, NULL, 0, Window->m_iCursorHeight))
{
if (ShowCaret(Window->m_poWindow) == TRUE)
{
SetCaretPos(Window->m_iCursorX, Window->m_iCursorY);
}
}
break;
}
case WM_CLOSE :
{
/* Allow the client window itself to handle the close */
Window->HandleCommand(IDCANCEL);
break;
}
case WM_DESTROY :
{
/* When the WM_DESTROY message is received, the Windows window has already been */
/* destroyed so set its handle to NULL so that we do not try to destroy it again */
/* in CWindow's destructor */
Window->m_poWindow = NULL;
PostQuitMessage(0);
break;
}
case WM_COMMAND :
{
/* Get the ID of the command received */
Command = LOWORD(a_oWParam);
/* In Windows, all menu items are checkable, but we only want to toggle the checkmark */
/* on menu items of type EStdMenuCheck. So we must search our own menu list for the */
/* menu item to determine whether it is checkable */
MenuItem = Window->m_poApplication->MenuItems();
do
{
/* Is this the menu item for which we are searching and is it checkable? */
if ((MenuItem->m_iCommand == Command) && (MenuItem->m_eType == EStdMenuCheck))
{
/* Yes, got it! Get its current check state and toggle it */
Checked = Window->MenuItemChecked(Command);
Window->CheckMenuItem(Command, (!(Checked)));
break;
}
++MenuItem;
}
while (MenuItem->m_eType != EStdMenuEnd);
/* Call the CWindow::HandleCommand() function so the client can process the message */
Window->HandleCommand(Command);
break;
}
case WM_CHAR :
case WM_SYSCHAR :
{
/* If the ctrl key is currently pressed then convert the keycode back to standard ASCII, */
/* but NOT if alt is also pressed or it will break German keymappings that use altgr! */
if ((m_bCtrlPressed) && (!(m_bAltPressed)))
{
/* Convert the key to lower case */
a_oWParam |= 0x60;
/* This is awful hackiness taken to the next level. For reasons unknown, the '[' */
/* and ']' keys (on the UK/US keyboard layouts) are setup to return the keycodes 27 */
/* (escape) and 29 (group separator) when pressed in conjunction with the ctrl key. */
/* The keys in the equivalent position on a German keyboard ('ü' and '+' respectively) */
/* are also setup to return these key values! Although this explains the mystery of how */
/* MSVC magically uses these keys on different keyboard layouts, it makes it impossible */
/* to write truly generic keyboard handling code. In a hack of horrific dimensions we */
/* translate these keys into the values for the real keys at these positions. This might */
/* have to be extended to use a table in the future, if more crazy key mappings and */
/* languages are to be supported */
if ((a_oWParam == 123) || (a_oWParam == 125))
{
/* Determine the current input locale */
KeyboardLayout = GetKeyboardLayout(0);
if (LOBYTE((DWORD_PTR) KeyboardLayout) == LANG_ENGLISH)
{
if (a_oWParam == 123)
{
a_oWParam = '[';
}
else if (a_oWParam == 125)
{
a_oWParam = ']';
}
}
else
{
if (a_oWParam == 123)
{
/* Use the 8859-15 encoding for 'ü', as this file is encoded as UTF-8 and using 'ü' */
/* in a string will generate an incorrect value */
a_oWParam = 0xfc;
}
else if (a_oWParam == 125)
{
a_oWParam = '+';
}
}
}
}
/* Call the CWindow::OfferKeyEvent() function, passing in only valid ASCII characters */
if ((a_oWParam >= 32) && (a_oWParam <= 254))
{
Handled = Window->OfferKeyEvent((TInt) a_oWParam, ETrue);
/* For WM_SYSCHAR we have some special processing to allow client code to override */
/* alt+x key combinations while still allowing menu shortcuts to work. If the client */
/* returns ETrue then it has consumed the keypress - that is it has performed some action */
/* on it such as a shortcut. In this case we don't want to pass the keypress onto the */
/* system as it would activate menu items with the same keycode. If the keypress was not */
/* consumed then set RetVal to 1 to pass the kepress onto the system using DefWindowProc() */
if ((a_uiMessage == WM_SYSCHAR) && (!(Handled)))
{
RetVal = 1;
}
}
break;
}
case WM_SYSKEYDOWN :
case WM_SYSKEYUP :
{
/* Intercept the menu activation key (F10 or alt+x key combination) so that we can keep track */
/* of the state of the alt and ctrl keys. This is to allow activation of menus in the normal */
/* manner while also allowing the client to override the menu activation key for other tasks */
if (a_oWParam == VK_MENU)
{
if (a_uiMessage == WM_SYSKEYDOWN)
{
m_bAltPressed = ETrue;
}
else
{
m_bAltPressed = m_bCtrlPressed = EFalse;
}
}
/* Pass the raw key onto the CWindow::OfferRawKeyEvent() function, without any kind */
/* of preprocessing */
Window->OfferRawKeyEvent((TInt) a_oWParam, (a_uiMessage == WM_SYSKEYDOWN));
/* Have some special processing for the alt key, passing it onto the client code. Even */
/* though the the alt key is not handled through the usual g_acoKeyMap array, to client */
/* code its handling will appear consistent */
if (a_oWParam == VK_MENU)
{
Window->OfferKeyEvent(STD_KEY_ALT, m_bAltPressed);
}
/* And indicate that we want to pass the keypress onto the system */
RetVal = 1;
break;
}
case WM_MENUSELECT :
{
/* Forget about the modifier keypresses as we won't get a WM_KEYUP or WM_SYSKEYUP for them */
/* due to the window no longer being active. This message is also sent when alt is pressed */
/* so in this case ignore it */
if (a_oLParam != 0)
{
m_bAltPressed = m_bCtrlPressed = m_bShiftPressed = EFalse;
}
break;
}
case WM_KEYDOWN :
case WM_KEYUP :
{
/* Scan through the key mappings and find the one that has just been pressed */
for (Index = 0; Index < (TInt) NUM_KEYMAPPINGS; ++Index)
{
if (g_acoKeyMap[Index].m_iNativeKey == (int) a_oWParam)
{
break;
}
}
/* If it was a known key then convert it to the standard value and pass it to the */
/* CWindow::OfferKeyEvent() function */
if (Index < (TInt) NUM_KEYMAPPINGS)
{
Key = g_acoKeyMap[Index].m_iStdKey;
/* First record the state of the shift key, it it was indeed shift that was pressed */
/* or released */
if (Key == STD_KEY_SHIFT)
{
m_bShiftPressed = (a_uiMessage == WM_KEYDOWN) ? ETrue : EFalse;
}
Window->OfferKeyEvent(Key, (a_uiMessage == WM_KEYDOWN));
}
/* This is pretty horrible. Because Windows mixes its WM_KEY#? and WM_CHAR events, we */
/* can get duplicate keys that need to get filtered out in order to provide a consistent */
/* pattern to calling CWindow::OfferKeyEvent(). Also, when ctrl is pressed the ASCII */
/* characters sent to WM_CHAR messages are different so again we need to adjust these */
/* back to standard ASCII so keeping track of the state of the ctrl key is the only way */
/* to achieve this */
if (a_oWParam == VK_CONTROL)
{
m_bCtrlPressed = (a_uiMessage == WM_KEYDOWN) ? ETrue : EFalse;
}
/* This is even more horrible. When the ALT GR key is pressed, rather than using a special */
/* key, Windows sends through a VK_CONTROL WM_KEYDOWN event, followed by VK_MENU (otherwise */
/* known as ALT) WM_KEYDOWN and WM_KEYUP events, with NO following VK_CONTROL WM_KEYUP event! */
/* So we need to put some special magic in here to handle this nonsense or we will think that */
/* the ctrl key is pressed when it isn't. We also have to keep track of the VK_MENU key to */
/* extend our workarounds to work when using altgr to enter characters on German keyboards */
else if (a_oWParam == VK_MENU)
{
if (a_uiMessage == WM_KEYDOWN)
{
m_bAltPressed = ETrue;
}
else
{
m_bAltPressed = m_bCtrlPressed = EFalse;
}
}
/* Now take the horribleness to the next level. Certain keys (including the mysterious */
/* VK_OEM_MINUS key) are simply not passed to WM_CHAR if the control key is pressed. But */
/* we need these keys and they work without special treatment on other operating systems. */
/* So we have to look out for them individually and simulate a WM_CHAR event if found */
TBool OfferKey;
UINT VirtualKey;
if ((m_bCtrlPressed) && (!m_bAltPressed))
{
if ((a_oWParam == VK_SUBTRACT) || (a_oWParam == VK_ADD) || (a_oWParam == VK_OEM_MINUS) || (a_oWParam == VK_OEM_PLUS))
{
VirtualKey = MapVirtualKey((UINT) a_oWParam, MAPVK_VK_TO_CHAR);
/* Determine the current input locale */
KeyboardLayout = GetKeyboardLayout(0);
/* Do some deep magic based on some empirical investigation into what special key get sent */
/* by Windows multiple times in which keyboard mappings. If there is a logic to this, I */
/* I don't get it */
if (LOBYTE((DWORD_PTR) KeyboardLayout) == LANG_ENGLISH)
{
if ((ShiftPressed()) && (a_oWParam == VK_OEM_MINUS))
{
OfferKey = EFalse;
}
else
{
OfferKey = ETrue;
}
}
else
{
if ((ShiftPressed()) && (a_oWParam == VK_OEM_MINUS))
{
OfferKey = EFalse;
}
else if ((!ShiftPressed()) && (a_oWParam == VK_OEM_PLUS))
{
OfferKey = EFalse;
}
else
{
OfferKey = ETrue;
}
}
/* Horribleness++. It turns out that three of our "mysterious" keys are always mapped to their */
/* unshifted state, even if the shift key is pressed. There is no function I could find that */
/* will these map correctly, so for these two keys we will perform a manual shift to get the */
/* required keys */
if (ShiftPressed())
{
if (VirtualKey == '-')
{
VirtualKey = '_';
}
else if (VirtualKey == '=')
{
VirtualKey = '+';
}
/* The final nightmare inconsistency is only valid in German keyboard layouts */
else if ((LOBYTE((DWORD_PTR) KeyboardLayout) == LANG_GERMAN) && (VirtualKey == '+'))
{
VirtualKey = '*';
}
}
/* Offer the key to the client only if it has been determined that it is not one of the */
/* keys that will also be sent by WM_CHAR */
if (OfferKey)
{
Window->OfferKeyEvent(VirtualKey, (a_uiMessage == WM_KEYDOWN));
}
}
/* Number keys also do not generate a WM_CHAR if the control key is pressed, so again we */
/* must simulate it. Numbers do not need to be mapped as their virtual keys are the same as */
/* their character values */
else if ((a_oWParam >= 0x30) && (a_oWParam <= 0x39))
{
Window->OfferKeyEvent((TInt) a_oWParam, (a_uiMessage == WM_KEYDOWN));
}
}
/* Pass the raw key onto the CWindow::OfferRawKeyEvent() function, without any kind */
/* of preprocessing */
Window->OfferRawKeyEvent((TInt) a_oWParam, (a_uiMessage == WM_KEYDOWN));
break;
}
case WM_KILLFOCUS :
{
/* Destroy the native Windows cursor as the window is losing focus */
DestroyCaret();
break;
}
case WM_LBUTTONDOWN :
{
/* Extract the mouse's X and Y positions and send them to the client window */
Window->HandlePointerEvent(LOWORD(a_oLParam), HIWORD(a_oLParam), EStdMouseDown);
break;
}
case WM_LBUTTONUP :
{
/* Extract the mouse's X and Y positions and send them to the client window */
Window->HandlePointerEvent(LOWORD(a_oLParam), HIWORD(a_oLParam), EStdMouseUp);
break;
}
case WM_LBUTTONDBLCLK :
{
/* Extract the mouse's X and Y positions and send them to the client window */
Window->HandlePointerEvent(LOWORD(a_oLParam), HIWORD(a_oLParam), EStdMouseDoubleClick);
break;
}
case WM_MOUSEMOVE :
{
/* Extract the mouse's X and Y positions and send them to the client window */
Window->HandlePointerEvent(LOWORD(a_oLParam), HIWORD(a_oLParam), EStdMouseMove);
break;
}
case WM_MOUSEWHEEL :
{
/* Extract the 16 bit amount the wheel has been scrolled and ensure that it is signed */
Window->HandleWheelEvent((short) HIWORD(a_oWParam));
break;
}
case WM_PAINT :
{
/* Prepare the device context for painting and call the CWindow::draw() routine. */
/* If this fails then there isn't much we can do besides ignore the error */
if ((Window->m_poDC = BeginPaint(a_poWindow, &Window->m_oPaintStruct)) != NULL)
{
Window->draw(Window->m_oPaintStruct.rcPaint.top, Window->m_oPaintStruct.rcPaint.bottom);
EndPaint(a_poWindow, &Window->m_oPaintStruct);
/* And indicate that there is no longer a valid DC allocated so that nobody */
/* tried to use it */
Window->m_poDC = NULL;
}
break;
}
case WM_SIZE :
{
Window->InternalResize(LOWORD(a_oLParam), HIWORD(a_oLParam));
break;
}
case WM_COPYDATA :
{
/* Let the RRendezvous class know that a rendevous has been received */
CopyData = (COPYDATASTRUCT *) a_oLParam;
g_oRendezvous.MessageReceived((unsigned char *) CopyData->lpData, CopyData->cbData);
/* And indicate that the message has been processed */
RetVal = 1;
break;
}
case WM_HSCROLL :
case WM_VSCROLL :
{
/* Recursively search through the window's tree of layout gadgets and search each one to see */
/* if it contains a gadget that represents the Windows slider that was just moved */
Result = false;
if (Window->m_poRootLayout)
{
Result = Window->m_poRootLayout->SendUpdate((void *) a_oLParam, LOWORD(a_oWParam));
}
break;
}
default :
{
RetVal = 1;
break;
}
}
/* If the event was not handled then call the system's default window procedure */
if (RetVal != 0)
{
RetVal = DefWindowProc(a_poWindow, a_uiMessage, a_oWParam, a_oLParam);
}
return(RetVal);
}
#endif /* WIN32 */
/* Written: Monday 08-Feb-2010 7:19 am */
CWindow::~CWindow()
{
close();
}
/* Written: Wednesday 13-Oct-2010 7:29 am */
void CWindow::Activate()
{
ASSERTM(m_poWindow, "CWindow::Activate() => Window must already be open");
#ifdef __amigaos__
SetAttrs(m_poWindowObj, WINDOW_FrontBack, WT_FRONT, TAG_DONE);
ActivateWindow(m_poWindow);
#elif defined(WIN32) && !defined(QT_GUI_LIB)
DEBUGCHECK((SetActiveWindow(m_poWindow) != NULL), "CWindow::Activate() => Unable to activate window");
#endif /* defined(WIN32) && !defined(QT_GUI_LIB) */
}
/**
* Appends an accelerator to the Windows accelerator table.
* This Windows specific function will add an accelerator to the application's current
* accelerator table. There is no such function in the Windows API so this function
* retrieves a copy of the current accelerator table, appends an accelerator to it and
* makes that new accelerator table the currently active one.
*
* @date Wednesday 05-Jun-2013 6:36 am Code HQ Ehinger Tor
* @param a_pcoMenuItem Ptr to the SStdMenuItem structure representing the accelerator
* @return KErrNone if successful
* @return KErrNoMemory if not enough memory was available to allocate the accelerator
*/
#if defined(WIN32) && !defined(QT_GUI_LIB)
TInt CWindow::AddAccelerator(const struct SStdMenuItem *a_pcoMenuItem)
{
TInt NumAccelerators, RetVal;
ACCEL *Accelerators;
HACCEL OldAccelerators;
/* Assume failure */
RetVal = KErrNoMemory;
/* Determine how many accelerators are in the current accelerator table and allocate */
/* enough memory to represent those accelerators + one new one */
NumAccelerators = CopyAcceleratorTable(m_poAccelerators, NULL, 0);
if ((Accelerators = new ACCEL[NumAccelerators + 1]) != NULL)
{
/* Get a copy of the existing accelerator table into the newly allocate memory */
NumAccelerators = CopyAcceleratorTable(m_poAccelerators, Accelerators, NumAccelerators);
/* Append a new accelerator to the table, representing the menu item passed in */
InitialiseAccelerator(&Accelerators[NumAccelerators], a_pcoMenuItem);
/* Save a ptr to the old accelerator table and create a new one, only deleting the */
/* old one if creation of the new was successful */
OldAccelerators = m_poAccelerators;
if ((m_poAccelerators = CreateAcceleratorTable(Accelerators, (NumAccelerators + 1))) != NULL)
{
RetVal = KErrNone;
/* The new accelerator table was created successfully so delete the old one */
DestroyAcceleratorTable(OldAccelerators);
}
delete [] Accelerators;
}
return(RetVal);
}
#endif /* defined(WIN32) && !defined(QT_GUI_LIB) */
#ifndef __amigaos__
/**
* Adds a menu item to an already existing dropdown menu.
* This is an internal function. Client code should use the public version of CWindow::AddMenuItem(),
* which is a wrapper around this version. This version accepts a structure containing information about
* the menu item to add and an OS specific handle to the dropdown menu to which to add the new item.
*
* @date Thursday 23-May-2013 7:40 am Code HQ Ehinger Tor
* @param a_pcoMenuItem Ptr to structure containing information such as the label, command ID etc.
* @param a_pvDropdownMenu OS specific handle to the dropdown menu to which to add the menu item
* @return KErrNone if successful
* @return KErrNoMemory if not enough memory was available to allocate the menu item
*/
TInt CWindow::AddMenuItem(const struct SStdMenuItem *a_pcoMenuItem, void *a_pvDropdownMenu)
{
TInt RetVal;
ASSERTM((a_pcoMenuItem!= NULL), "CWindow::AddMenuItem() => MenuItem structure must be specified");
ASSERTM((a_pvDropdownMenu != NULL), "CWindow::AddMenuItem() => Menu bar must be specified");
/* Assume success */
RetVal = KErrNone;
#ifdef QT_GUI_LIB
QAction *Action;
QMenu *DropdownMenu;
QString Shortcut;
DropdownMenu = (QMenu *) a_pvDropdownMenu;
/* Create a new menu item and add it to the previously created drop down menu */
if ((Action = new CQtAction(a_pcoMenuItem->m_iCommand, a_pcoMenuItem->m_pccLabel, m_poWindow)) != NULL)
{
/* If this is a checkable menu option or a separator then adjust the style of the newly */
/* added menu item to reflect this */
if (a_pcoMenuItem->m_eType == EStdMenuCheck)
{
Action->setCheckable(true);
}
else if (a_pcoMenuItem->m_eType == EStdMenuSeparator)
{
Action->setSeparator(true);
}
/* If the menu item has a hotkey then generate a key sequence and assign it to the action */
if (a_pcoMenuItem->m_pccHotKey)
{
/* The most convenient type of QKeySequence to use for our purposes is */
/* a fully text based one, so start by converting the modifier keys to */
/* a textual prefix */
if ((a_pcoMenuItem->m_iHotKeyModifier == STD_KEY_CONTROL) || (a_pcoMenuItem->m_iHotKeyModifier == STD_KEY_MENU))
{
Shortcut = "Ctrl+";
}
else if (a_pcoMenuItem->m_iHotKeyModifier == STD_KEY_ALT)
{
Shortcut = "Alt+";
}
else if (a_pcoMenuItem->m_iHotKeyModifier == STD_KEY_SHIFT)
{
Shortcut = "Shift+";
}
/* There is no modifier. However, by default a QString really is empty */
/* and cannot be appended to, so we must populate it with an empty string */
else
{
Shortcut = "";
}
/* Append the hotkey name to the prefix and add the shortcut to the action */
Shortcut.append(a_pcoMenuItem->m_pccHotKey);
Action->setShortcut(Shortcut);
}
/* And add the new menu item to the drop down menu */
DropdownMenu->addAction(Action);
}
else
{
Utils::info("CWindow::AddMenuItem() => Unable to create menu item");
RetVal = KErrNoMemory;
}
#else /* ! QT_GUI_LIB */
const char *Label;
HMENU DropdownMenu;
Label = NULL;
DropdownMenu = (HMENU) a_pvDropdownMenu;
/* If this is a separator then create a separator menu item and add it to the previously */
/* created drop down menu */
if (a_pcoMenuItem->m_eType == EStdMenuSeparator)
{
DEBUGCHECK((AppendMenu(DropdownMenu, MF_SEPARATOR, a_pcoMenuItem->m_iCommand, NULL) != FALSE),
"CWindow::AddMenuItem() => Unable to append separator menu item");
}
/* Otherwise it is a "normal" menu item so create a menu item for it. This will involve */
/* also interpreting the requested hotkey and adding a textual string representing said */
/* hotkey to the menu */
else
{
ASSERTM((DropdownMenu != NULL), "CWindow::AddMenuItem() => Menu bar must be created before a menu item can be added");
ASSERTM((a_pcoMenuItem->m_pccLabel != NULL), "CWindow::AddMenuItem() => All menu items must have a name");
/* Build the menu item's label as a composite of the menu's label and its shortcut */
if ((Label = InitialiseMenuLabel(a_pcoMenuItem)) != NULL)
{
/* And create a new menu item using the newly constructed label and add it to the */
/* previously created drop down menu */
DEBUGCHECK((AppendMenu(DropdownMenu, 0, a_pcoMenuItem->m_iCommand, Label) != FALSE),
"CWindow::AddMenuItem() => Unable to append new menu item");
/* And free the temporary buffer used for the menu item labels */
delete [] (char *) Label;
}
else
{
Utils::info("CWindow::AddMenuItem() => Unable to allocate memory for menu item label");
RetVal = KErrNoMemory;
}
}
#endif /* ! QT_GUI_LIB */
return(RetVal);
}
#endif /* ! __amigaos__ */
/**
* Adds a menu item to an already existing dropdown menu.
* This function appends a new menu item to a dropdown menu. The label passed in can contain
* a character preceded by a '&' character, in which case that character will be used as the
* menu item's shortcut. If no label is passed in then a separator will be added to the menu.
*
* The dropdown menu to which to add the menu item is specified as an ordinal starting from
* zero, where zero is the leftmost dropdown menu and (NumMenus - 1) is the rightmost.
*
* @date Wednesday 22-May-2013 6:23 pm, Frankfurt am Main Airport, awaiting flight TP 579 to Lisbon
* @param a_eMenuItemType The type of menu item to be added
* @param a_pccLabel Label to be used for the new menu item, or NULL for a separator
* @param a_pccHotKey Shortcut key to be displayed, or NULL for no shortcut. Ignored for separators
* @param a_iOrdinal Ordinal offset of the dropdown menu to which to add the menu item
* @param a_iSubOrdinal Ordinal offset of the submenu within the dropdown menu to which to add the
* menu item. Set to -1 if no submenu is to be used
* @param a_iCommand Command ID that will be passed to the window's HandleCommand() function
* @return KErrNone if successful
* @return KErrNotFound if the dropdown menu represented by a_iOrdinal was not found
* @return KErrNoMemory if not enough memory was available to allocate the menu item
*/
TInt CWindow::AddMenuItem(TStdMenuItemType a_eMenuItemType, const char *a_pccLabel, const char *a_pccHotKey, TInt a_iOrdinal, TInt a_iSubOrdinal, TInt a_iCommand)
{
TInt RetVal;
#ifndef __amigaos__
struct SStdMenuItem MenuItem = { a_eMenuItemType, a_pccLabel, a_pccHotKey, STD_KEY_ALT, a_iCommand };
#endif /* ! __amigaos__ */
#ifdef __amigaos__