1 /*
2 * tracker/wince/WinCE_main.cpp
3 *
4 * Copyright 2009 Peter Barth
5 *
6 * This file is part of Milkytracker.
7 *
8 * Milkytracker is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * Milkytracker is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with Milkytracker. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23 // ------------------ WinCE -------------------------------
24 #include <windows.h>
25 #include <aygshell.h>
26 #include <gx.h>
27 #include "WinCE_main.h"
28 #include "VirtualKeyToScanCodeTable.h"
29 // ------------------ tracker -----------------------------
30 #include "PPUI.h"
31 #include "PPMutex.h"
32 #include "Screen.h"
33 #include "Tracker.h"
34 #include "DisplayDevice_GAPI.h"
35 #include "ButtonMapper.h"
36 #include "WaitStateThread.h"
37 #include "LogoSmall.h"
38 #include "XMFile.h"
39 #include "GlobalColorConfig.h"
40
41 #define WINDOWS_DEFAULT_TIMER
42 #undef RESOLUTION_CHECK
43
44 #define MAX_LOADSTRING 100
45 #define DBLCLKTIME 1000
46 #define DRAGSENSITIVITY 2
47
48 HINSTANCE hInst; // The current instance
49 WNDCLASS wc;
50 HWND hwndCB; // The command bar handle
51 HWND hWnd;
52
53 BOOL gxInit = FALSE;
54 BOOL taskBar = TRUE;
55 BOOL gxActive = FALSE;
56
57 PPMutex* globalMutex = NULL;
58
59 unsigned short* vScreen = NULL;
60 PPSize windowSize(DISPLAYDEVICE_WIDTH,DISPLAYDEVICE_HEIGHT);
61
62 // Global GAPI variables:
63 GXDisplayProperties gx_displayprop;
64
65 #ifndef WINDOWS_DEFAULT_TIMER
66 #include "WinCE_ThreadTimer.h"
67 #define WM_MYTIMER (WM_USER + 10)
68
69 static CThreadTimer myThreadTimer;
70
MyThreadTimerProc(void * obj,UINT idEvent)71 void MyThreadTimerProc(void* obj, UINT idEvent)
72 {
73 SendMessage(hWnd, WM_MYTIMER, 0, 0);
74 }
75 #endif
76
77 // ------------------ Tracker --------------------------------------------------------------------------
78 EOrientation orientation = eOrientation90CW;
79 pp_int32 doublePixels = FALSE;
80 pp_int32 allowVirtualKeys = FALSE;
81 pp_int32 hideTaskBar = TRUE;
82 pp_int32 dontTurnOffDevice = FALSE;
83
84 static PPScreen* myTrackerScreen = NULL;
85 static Tracker* myTracker = NULL;
86 static PPDisplayDevice* myDisplayDevice = NULL;
87
88 // ------------------- Logger -----------------------------
89 #ifdef DEBUG
90 #include "Logger.h"
91 #include "Simple.h"
92 #include "PPSystem.h"
93 static CLogger* logger = NULL;
94 #endif
95
96 void TrackerCreate();
97 void TrackerStartUp(bool showSplash);
98 void TrackerInitGUI(bool showSplash);
99
100 // ------------------ Forward declarations of functions included in this code module: ------------------
101 void TaskBar(bool show);
102 ATOM MyRegisterClass(HINSTANCE, LPTSTR);
103 BOOL InitInstance(HINSTANCE, int);
104 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
105
106 // ------------------ debugging forwards ---------------------------------------------------------------
107 void drawString(const char*, unsigned short*, unsigned int, unsigned int, unsigned int, unsigned short);
108
109 // ------------------- update screen -------------------------------------------------------------------
110 void UpdateScreen(unsigned short*);
111 void UpdateScreen();
112 void DrawBackground(bool shade = true);
113 bool NeedsDrawBackground();
114
115
116 //////////////////////////////////////////////////////////////////////////
117 // Exported functions:
118 // PPGetTickCount() is used for milisecond timing
119 // QueryKeyModifiers is used for detecting the state of the modifier keys
120 // SuspendFullScreen() is used to disable full screen mode
121 // ResumeFullScreen() is used to disable full screen mode
122 //////////////////////////////////////////////////////////////////////////
PPGetTickCount()123 pp_uint32 PPGetTickCount()
124 {
125 return ::GetTickCount();
126 }
127
QueryKeyModifiers()128 void QueryKeyModifiers()
129 {
130 if (::GetAsyncKeyState(VK_SHIFT)>>15)
131 setKeyModifier(KeyModifierSHIFT);
132 else
133 clearKeyModifier(KeyModifierSHIFT);
134
135 if (::GetAsyncKeyState(VK_MENU)>>15)
136 setKeyModifier(KeyModifierALT);
137 else
138 clearKeyModifier(KeyModifierALT);
139
140 if (::GetAsyncKeyState(VK_CONTROL)>>15)
141 setKeyModifier(KeyModifierCTRL);
142 else
143 clearKeyModifier(KeyModifierCTRL);
144 }
145
SuspendFullScreen()146 void SuspendFullScreen()
147 {
148 GXCloseInput();
149 GXCloseDisplay();
150 TaskBar(true);
151 gxActive = FALSE;
152 ShowWindow(hWnd, SW_SHOW);
153 }
154
ResumeFullScreen()155 void ResumeFullScreen()
156 {
157 ShowWindow(hWnd, SW_SHOW);
158 TaskBar(false);
159 SHSipPreference(hWnd, SIP_FORCEDOWN);
160 GXOpenDisplay(hWnd, GX_FULLSCREEN);
161 GXOpenInput();
162 gxActive = TRUE;
163
164 // clear screen with shade if necessary
165 if (NeedsDrawBackground())
166 DrawBackground();
167
168 UpdateScreen();
169 }
170
171
172 //////////////////////////////////////////////////////////////////////////
173 // Taskbar handling
174 //////////////////////////////////////////////////////////////////////////
TaskBar(bool show)175 void TaskBar(bool show)
176 {
177 if (!hideTaskBar)
178 return;
179
180 RECT rc;
181 GetWindowRect( hWnd, &rc );
182 HWND hWndTB = FindWindow(TEXT("HHTaskbar"),NULL);
183 if (show && hWndTB)
184 {
185 if (taskBar) return;
186 SHFullScreen( hWnd, SHFS_SHOWTASKBAR | SHFS_SHOWSIPBUTTON + SHFS_SHOWSTARTICON );
187 ShowWindow( hWndTB, SW_SHOW );
188 MoveWindow( hWnd, rc.left, rc.top + 26, rc.right, rc.bottom - 26, TRUE );
189 taskBar = TRUE;
190 }
191 else if (hWndTB)
192 {
193 if (!taskBar) return;
194 SHFullScreen( hWnd, SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON + SHFS_HIDESTARTICON );
195 ShowWindow( hWndTB, SW_HIDE );
196 MoveWindow( hWnd, rc.left, rc.top - 26, rc.right, rc.bottom + 26, TRUE );
197 taskBar = FALSE;
198 }
199 }
200
201 //////////////////////////////////////////////////////////////////////////
202 // Init GAPI
203 // To-do: Should go into DisplayDevice someday
204 //////////////////////////////////////////////////////////////////////////
InitGAPI(HWND hWnd)205 BOOL InitGAPI(HWND hWnd)
206 {
207 TaskBar(false);
208
209 // Attempt to take over the screen
210 if (GXOpenDisplay( hWnd, GX_FULLSCREEN) == 0)
211 return FALSE;
212
213 gxActive = TRUE;
214
215 // Get display properties
216 gx_displayprop = GXGetDisplayProperties();
217
218 #ifdef RESOLUTION_CHECK
219 if ((gx_displayprop.cyHeight!=320)||(gx_displayprop.cxWidth!=240))
220 {
221 // Only dealing with 240x320 resolution in this code
222 GXCloseDisplay();
223 MessageBox(hWnd,L"Sorry, only supporting 240x320 display devices",L"Sorry!", MB_OK);
224 return FALSE;
225 }
226 #endif
227
228 // Check for 16 bit color display
229 if (gx_displayprop.cBPP != 16)
230 {
231 // Only dealing with 16 bit color in this code
232 GXCloseDisplay();
233 MessageBox(hWnd,L"Sorry, only supporting 16bit color",L"Sorry!", MB_OK);
234 return FALSE;
235 }
236
237 // Take over button handling
238 GXOpenInput();
239
240 globalMutex = new PPMutex();
241
242 return TRUE;
243 }
244
245 //////////////////////////////////////////////////////////////////////////
246 // Dispose GAPI
247 //////////////////////////////////////////////////////////////////////////
ExitGAPI()248 void ExitGAPI()
249 {
250 if (gxActive)
251 {
252 // Clean up
253 GXSuspend();
254 GXCloseInput();
255 GXCloseDisplay();
256 TaskBar(true);
257 gxActive = false;
258 }
259 }
260
HandleCommandLine(LPCTSTR lpCmdLine)261 void HandleCommandLine(LPCTSTR lpCmdLine)
262 {
263 // Retrieve input file
264 PPSystemString fileInput(lpCmdLine);
265
266 // When there is something specified, check if it's an existing file
267 if (fileInput.length() && XMFile::exists(fileInput))
268 {
269 PPSystemString* strPtr = &fileInput;
270
271 PPEvent event(eFileDragDropped, &strPtr, sizeof(PPSystemString*));
272 myTrackerScreen->raiseEvent(&event);
273 }
274 }
275
WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)276 int WINAPI WinMain( HINSTANCE hInstance,
277 HINSTANCE hPrevInstance,
278 LPTSTR lpCmdLine,
279 int nCmdShow)
280 {
281 #ifdef DEBUG
282 SimpleString path(System::getConfigFileName(_T("milky.log")));
283 CLogger _logger(path);
284 logger = &_logger;
285 #endif
286
287 MSG msg;
288 HACCEL hAccelTable;
289
290 // Perform application initialization:
291 if (!InitInstance (hInstance, nCmdShow))
292 {
293 TaskBar(true);
294 return FALSE;
295 }
296
297 HandleCommandLine(lpCmdLine);
298
299 #ifndef WINDOWS_DEFAULT_TIMER
300 HANDLE hThread = GetCurrentThread();
301 SetThreadPriority(hThread, THREAD_PRIORITY_BELOW_NORMAL);
302 #endif
303
304 hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_FIRSTGX);
305
306 while (GetMessage(&msg, NULL, 0, 0))
307 {
308 TranslateMessage(&msg);
309 DispatchMessage(&msg);
310 }
311
312 delete myTracker;
313 delete myTrackerScreen;
314
315 ExitGAPI();
316
317 delete globalMutex;
318
319 return msg.wParam;
320 }
321
322
MyRegisterClass(HINSTANCE hInstance,LPTSTR szWindowClass)323 ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass)
324 {
325 WNDCLASS wc;
326
327 wc.style = CS_HREDRAW | CS_VREDRAW;
328 wc.lpfnWndProc = (WNDPROC) WndProc;
329 wc.cbClsExtra = 0;
330 wc.cbWndExtra = 0;
331 wc.hInstance = hInstance;
332 wc.hIcon = NULL;
333 //wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_GAPI1));
334 wc.hCursor = 0;
335 wc.hbrBackground = (HBRUSH) GetStockObject(HOLLOW_BRUSH);
336 wc.lpszMenuName = 0;
337 wc.lpszClassName = szWindowClass;
338
339 return RegisterClass(&wc);
340 }
341
InitInstance(HINSTANCE hInstance,int nCmdShow)342 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
343 {
344 TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
345 TCHAR szWindowClass[MAX_LOADSTRING]; // The window class name
346
347 hInst = hInstance; // Store instance handle in our global variable
348 // Initialize global strings
349 LoadString(hInstance, IDC_FIRSTGX, szWindowClass, MAX_LOADSTRING);
350 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
351
352 //If it is already running, then focus on the window
353 hWnd = FindWindow(szWindowClass, szTitle);
354 if (hWnd)
355 {
356 SetForegroundWindow ((HWND) (((DWORD)hWnd) | 0x01));
357 return 0;
358 }
359
360 MyRegisterClass(hInstance, szWindowClass);
361
362 RECT rect;
363 GetClientRect(hWnd, &rect);
364
365 hWnd = CreateWindow(szWindowClass,
366 szTitle,
367 WS_VISIBLE,
368 CW_USEDEFAULT,
369 CW_USEDEFAULT,
370 CW_USEDEFAULT,
371 CW_USEDEFAULT,
372 NULL,
373 NULL,
374 hInstance,
375 NULL);
376 if (!hWnd)
377 {
378 return FALSE;
379 }
380
381 // This will also load local WinCE config
382 InitButtonRemapper();
383
384 if (!InitGAPI(hWnd))
385 return FALSE;
386
387 TrackerCreate();
388
389 bool showSplash = myTracker->getShowSplashFlagFromDatabase();
390
391 TrackerInitGUI(showSplash);
392 TrackerStartUp(showSplash);
393
394 UpdateScreen();
395
396 // Create timers
397 #ifdef WINDOWS_DEFAULT_TIMER
398 SetTimer(hWnd, 10, 20, NULL);
399 #else
400 myThreadTimer.SetTimer (NULL, 1, 20, MyThreadTimerProc);
401 #endif
402 return TRUE;
403 }
404
405 //////////////////////////////////////////////////////////////////////////
406 // Convert final coordinates from current orientation
407 //////////////////////////////////////////////////////////////////////////
POINTFROMPARAM(PPPoint & point,int param)408 void POINTFROMPARAM(PPPoint& point, int param)
409 {
410 const unsigned int screenWidth = ::windowSize.width;
411 const unsigned int screenHeight = ::windowSize.height;
412
413 switch (orientation)
414 {
415 case eOrientation90CW:
416 {
417 int hCenter = (gx_displayprop.cxWidth >> 1) - ((screenHeight<<doublePixels) >> 1);
418 if (hCenter < 0) hCenter = 0;
419 int vCenter = (gx_displayprop.cyHeight >> 1) - ((screenWidth<<doublePixels) >> 1);
420 if (vCenter < 0) vCenter = 0;
421
422 point.y = LOWORD(param) - hCenter;
423 point.x = (gx_displayprop.cyHeight - 1 - (HIWORD(param) + vCenter));
424 break;
425 }
426
427 case eOrientation90CCW:
428 {
429 int hCenter = (gx_displayprop.cxWidth >> 1) - ((screenHeight<<doublePixels) >> 1);
430 if (hCenter < 0) hCenter = 0;
431 int vCenter = (gx_displayprop.cyHeight >> 1) - ((screenWidth<<doublePixels) >> 1);
432 if (vCenter < 0) vCenter = 0;
433
434 point.y = gx_displayprop.cxWidth - 1 - (LOWORD(param) + hCenter);
435 point.x = HIWORD(param) - vCenter;
436 break;
437 }
438
439 case eOrientationNormal:
440 int hCenter = (gx_displayprop.cxWidth >> 1) - ((screenWidth<<doublePixels) >> 1);
441 if (hCenter < 0) hCenter = 0;
442 int vCenter = (gx_displayprop.cyHeight >> 1) - ((screenHeight<<doublePixels) >> 1);
443 if (vCenter < 0) vCenter = 0;
444
445 point.x = LOWORD(param) - hCenter;
446 point.y = HIWORD(param) - vCenter;
447 break;
448 }
449
450 point.x >>= doublePixels;
451 point.y >>= doublePixels;
452 }
453
454
UpdateScreen(unsigned short * vScreen)455 void UpdateScreen(unsigned short* vScreen)
456 {
457 if (!gxActive)
458 return;
459
460 globalMutex->lock();
461
462 // Get the start of the screen memory from the GX function.
463 unsigned short * buffer = (unsigned short *) GXBeginDraw();
464 unsigned short * line_buffer = buffer;
465
466
467 if (buffer == NULL)
468 {
469 globalMutex->unlock();
470 return;
471 }
472
473 const unsigned int screenWidth = ::windowSize.width;
474 const unsigned int screenHeight = ::windowSize.height;
475
476 const unsigned int hcbxpitch = gx_displayprop.cbxPitch >> 1;
477 const unsigned int hcbypitch = gx_displayprop.cbyPitch >> 1;
478
479 const unsigned int hRes = gx_displayprop.cxWidth >> doublePixels;
480 const unsigned int vRes = gx_displayprop.cyHeight >> doublePixels;
481
482 unsigned short* vscr = vScreen;
483
484 if (gx_displayprop.ffFormat & kfDirect565)
485 {
486
487 switch (orientation)
488 {
489 case eOrientation90CW:
490 {
491 // PocketPC: gx_displayprop.cxWidth = 240, gx_displayprop.cyHeight = 320
492
493 const unsigned int width = hRes > screenHeight ? screenHeight : hRes;
494 const unsigned int height = vRes > screenWidth ? screenWidth : vRes;
495
496 int hCenter = (gx_displayprop.cxWidth >> 1) - ((screenHeight<<doublePixels) >> 1);
497 if (hCenter < 0) hCenter = 0;
498 int vCenter = (gx_displayprop.cyHeight >> 1) - ((screenWidth<<doublePixels) >> 1);
499 if (vCenter < 0) vCenter = 0;
500
501 if (!doublePixels)
502 {
503 for (unsigned int x=0; x<width; x++)
504 {
505 unsigned short* pixel = (buffer+(x+hCenter)*hcbxpitch)+((gx_displayprop.cyHeight-1+vCenter)*hcbypitch);
506
507 for (unsigned int y=0; y<height; y++)
508 {
509 *pixel = *vscr;
510 pixel-=hcbypitch;
511 vscr++;
512 }
513
514 vscr+=screenWidth-height;
515 }
516 }
517 else
518 {
519 for (unsigned int x=0; x<width; x++)
520 {
521 unsigned int y;
522
523 unsigned short* pixel = (buffer+(x*2+hCenter)*hcbxpitch)+((gx_displayprop.cyHeight-1+vCenter)*hcbypitch);
524 unsigned short* src = vscr;
525 for (y=0; y<height; y++)
526 {
527 *pixel = *vscr;
528 pixel-=hcbypitch;
529 *pixel = *vscr;
530 pixel-=hcbypitch;
531 vscr++;
532 }
533
534 pixel = buffer+((x*2+1+hCenter)*hcbxpitch)+((gx_displayprop.cyHeight-1+vCenter)*hcbypitch);
535 vscr = src;
536 for (y=0; y<height; y++)
537 {
538 *pixel = *vscr;
539 pixel-=hcbypitch;
540 *pixel = *vscr;
541 pixel-=hcbypitch;
542 vscr++;
543 }
544
545 vscr+=screenWidth-height;
546 }
547 }
548 break;
549 };
550
551 case eOrientation90CCW:
552 {
553 // PocketPC: gx_displayprop.cxWidth = 240, gx_displayprop.cyHeight = 320
554
555 const unsigned int width = hRes > screenHeight ? screenHeight : hRes;
556 const unsigned int height = vRes > screenWidth ? screenWidth : vRes;
557
558 int hCenter = (gx_displayprop.cxWidth >> 1) - ((screenHeight<<doublePixels) >> 1);
559 if (hCenter < 0) hCenter = 0;
560 int vCenter = (gx_displayprop.cyHeight >> 1) - ((screenWidth<<doublePixels) >> 1);
561 if (vCenter < 0) vCenter = 0;
562
563 if (!doublePixels)
564 {
565 for (unsigned int x=0; x<width; x++)
566 {
567 unsigned short* pixel = (buffer+(gx_displayprop.cxWidth-1-x-hCenter)*hcbxpitch + (vCenter*hcbypitch));
568
569 for (unsigned int y=0; y<height; y++)
570 {
571 *pixel = *vscr;
572 pixel+=hcbypitch;
573 vscr++;
574 }
575
576 vscr+=screenWidth-height;
577 }
578 }
579 else
580 {
581 for (unsigned int x=0; x<width; x++)
582 {
583 unsigned int y;
584
585 unsigned short* pixel = (buffer+(gx_displayprop.cxWidth-1-x*2-hCenter)*hcbxpitch + (vCenter*hcbypitch));
586 unsigned short* src = vscr;
587 for (y=0; y<height; y++)
588 {
589 *pixel = *vscr;
590 pixel+=hcbypitch;
591 *pixel = *vscr;
592 pixel+=hcbypitch;
593 vscr++;
594 }
595
596 pixel = (buffer+(gx_displayprop.cxWidth-1-(x*2+1)-hCenter)*hcbxpitch + (vCenter*hcbypitch));
597 vscr = src;
598 for (y=0; y<height; y++)
599 {
600 *pixel = *vscr;
601 pixel+=hcbypitch;
602 *pixel = *vscr;
603 pixel+=hcbypitch;
604 vscr++;
605 }
606
607 vscr+=screenWidth-height;
608 }
609 }
610
611 break;
612 };
613
614 case eOrientationNormal:
615 {
616 const unsigned int width = hRes > screenWidth ? screenWidth : hRes;
617 const unsigned int height = vRes > screenHeight ? screenHeight : vRes;
618
619 int hCenter = (gx_displayprop.cxWidth >> 1) - ((screenWidth<<doublePixels) >> 1);
620 if (hCenter < 0) hCenter = 0;
621 int vCenter = (gx_displayprop.cyHeight >> 1) - ((screenHeight<<doublePixels) >> 1);
622 if (vCenter < 0) vCenter = 0;
623
624 if (!doublePixels)
625 {
626 for (unsigned int y=0; y<height; y++)
627 {
628 unsigned short* pixel = buffer + hCenter*hcbxpitch + (vCenter+y)*hcbypitch;
629 for (unsigned int x=0; x<width; x++)
630 {
631 *pixel=*vscr;
632 pixel += hcbxpitch;
633 vscr++;
634 }
635
636 vscr+=screenWidth-width;
637 }
638 }
639 else
640 {
641 for (unsigned int y=0; y<height; y++)
642 {
643 unsigned int x;
644
645 unsigned short* pixel = buffer + (y*2 + vCenter)*hcbypitch + hCenter*hcbxpitch;
646 unsigned short* src = vscr;
647 for (x=0; x<width; x++)
648 {
649 *pixel=*vscr;
650 pixel += hcbxpitch;
651 *pixel=*vscr;
652 pixel += hcbxpitch;
653 vscr++;
654 }
655
656 pixel = buffer + ((y*2+1) + vCenter)*hcbypitch + hCenter*hcbxpitch;
657 vscr = src;
658 for (x=0; x<width; x++)
659 {
660 *pixel=*vscr;
661 pixel += hcbxpitch;
662 *pixel=*vscr;
663 pixel += hcbxpitch;
664 vscr++;
665 }
666
667 vscr+=screenWidth-width;
668 }
669
670 }
671
672 break;
673 };
674 }
675
676 }
677 else
678 {
679 // 15 bit color is not supported
680 }
681
682 // End the drawing code
683 GXEndDraw();
684
685 globalMutex->unlock();
686 }
687
UpdateScreenRegion(unsigned short * vScreen,const PPRect & rect)688 void UpdateScreenRegion(unsigned short* vScreen, const PPRect& rect)
689 {
690 if (!gxActive)
691 return;
692
693 globalMutex->lock();
694
695 // Get the start of the screen memory from the GX function.
696 unsigned short * buffer = (unsigned short *) GXBeginDraw();
697 unsigned short * line_buffer = buffer;
698
699 if (buffer == NULL)
700 {
701 globalMutex->unlock();
702 return;
703 }
704
705 const unsigned int screenWidth = ::windowSize.width;
706 const unsigned int screenHeight = ::windowSize.height;
707
708 const unsigned int hcbxpitch = gx_displayprop.cbxPitch >> 1;
709 const unsigned int hcbypitch = gx_displayprop.cbyPitch >> 1;
710
711 const unsigned int hRes = gx_displayprop.cxWidth >> doublePixels;
712 const unsigned int vRes = gx_displayprop.cyHeight >> doublePixels;
713
714 unsigned short* vscr = vScreen + rect.y1 * screenWidth + rect.x1;
715
716 if (gx_displayprop.ffFormat & kfDirect565)
717 {
718
719 switch (orientation)
720 {
721 case eOrientation90CW:
722 {
723 // PocketPC: gx_displayprop.cxWidth = 240, gx_displayprop.cyHeight = 320
724
725 const unsigned int width = hRes > screenHeight ? screenHeight : hRes;
726 const unsigned int height = vRes > screenWidth ? screenWidth : vRes;
727
728 if (rect.x1 >= (signed)height || rect.y1 >= (signed)width)
729 break;
730
731 int hCenter = (gx_displayprop.cxWidth >> 1) - ((screenHeight<<doublePixels) >> 1);
732 if (hCenter < 0) hCenter = 0;
733 int vCenter = (gx_displayprop.cyHeight >> 1) - ((screenWidth<<doublePixels) >> 1);
734 if (vCenter < 0) vCenter = 0;
735
736 int rx2 = rect.x2;
737 int ry2 = rect.y2;
738
739 if (rx2 > (signed)height) rx2 = height;
740 if (ry2 > (signed)width) ry2 = width;
741
742 if (!doublePixels)
743 {
744 for (int x=rect.y1; x<ry2; x++)
745 {
746 unsigned short* pixel = (buffer+(x+hCenter)*hcbxpitch)+((gx_displayprop.cyHeight-1+vCenter)*hcbypitch) - (rect.x1*hcbypitch);
747
748 for (int y=rect.x1; y<rx2; y++)
749 {
750 *pixel = *vscr;
751 pixel-=hcbypitch;
752 vscr++;
753 }
754
755 vscr+=screenWidth - (rx2 - rect.x1);
756 }
757 }
758 else
759 {
760 for (int x=rect.y1; x<ry2; x++)
761 {
762 int y;
763
764 unsigned short* pixel = (buffer+(x*2+hCenter)*hcbxpitch)+((gx_displayprop.cyHeight-1+vCenter)*hcbypitch) - (rect.x1*2*hcbypitch);
765 unsigned short* src = vscr;
766 for (y=rect.x1; y<rx2; y++)
767 {
768 *pixel = *vscr;
769 pixel-=hcbypitch;
770 *pixel = *vscr;
771 pixel-=hcbypitch;
772 vscr++;
773 }
774
775 pixel = (buffer+(x*2+1+hCenter)*hcbxpitch)+((gx_displayprop.cyHeight-1+vCenter)*hcbypitch) - ((rect.x1*2)*hcbypitch);
776 vscr = src;
777 for (y=rect.x1; y<rx2; y++)
778 {
779 *pixel = *vscr;
780 pixel-=hcbypitch;
781 *pixel = *vscr;
782 pixel-=hcbypitch;
783 vscr++;
784 }
785
786 vscr+=screenWidth - (rx2 - rect.x1);
787 }
788 }
789 break;
790 };
791
792 case eOrientation90CCW:
793 {
794 // PocketPC: gx_displayprop.cxWidth = 240, gx_displayprop.cyHeight = 320
795
796 const unsigned int width = hRes > screenHeight ? screenHeight : hRes;
797 const unsigned int height = vRes > screenWidth ? screenWidth : vRes;
798
799 if (rect.x1 >= (signed)height || rect.y1 >= (signed)width)
800 break;
801
802 int hCenter = (gx_displayprop.cxWidth >> 1) - ((screenHeight<<doublePixels) >> 1);
803 if (hCenter < 0) hCenter = 0;
804 int vCenter = (gx_displayprop.cyHeight >> 1) - ((screenWidth<<doublePixels) >> 1);
805 if (vCenter < 0) vCenter = 0;
806
807 int rx2 = rect.x2;
808 int ry2 = rect.y2;
809
810 if (rx2 > (signed)height) rx2 = height;
811 if (ry2 > (signed)width) ry2 = width;
812
813 if (!doublePixels)
814 {
815 for (int x=rect.y1; x<ry2; x++)
816 {
817 unsigned short* pixel = (buffer+(gx_displayprop.cxWidth-1-x-hCenter)*hcbxpitch) + ((rect.x1+vCenter)*hcbypitch);
818
819 for (int y=rect.x1; y<rx2; y++)
820 {
821 *pixel = *vscr;
822 pixel+=hcbypitch;
823 vscr++;
824 }
825
826 vscr+=screenWidth - (rx2 - rect.x1);
827 }
828 }
829 else
830 {
831 for (int x=rect.y1; x<ry2; x++)
832 {
833 int y;
834
835 unsigned short* pixel = (buffer+(gx_displayprop.cxWidth-1-x*2-hCenter)*hcbxpitch) + (((rect.x1*2)+vCenter)*hcbypitch);
836 unsigned short* src = vscr;
837 for (y=rect.x1; y<rx2; y++)
838 {
839 *pixel = *vscr;
840 pixel+=hcbypitch;
841 *pixel = *vscr;
842 pixel+=hcbypitch;
843 vscr++;
844 }
845
846 pixel = (buffer+(gx_displayprop.cxWidth-1-(x*2+1)-hCenter)*hcbxpitch) + (((rect.x1*2)+vCenter)*hcbypitch);
847 vscr = src;
848 for (y=rect.x1; y<rx2; y++)
849 {
850 *pixel = *vscr;
851 pixel+=hcbypitch;
852 *pixel = *vscr;
853 pixel+=hcbypitch;
854 vscr++;
855 }
856
857 vscr+=screenWidth - (rx2 - rect.x1);
858 }
859 }
860 break;
861 };
862
863 case eOrientationNormal:
864 {
865 int width = hRes > screenWidth ? screenWidth : hRes;
866 int height = vRes > screenHeight ? screenHeight : vRes;
867
868 if (rect.x1 >= width || rect.y1 >= height)
869 break;
870
871 int hCenter = (gx_displayprop.cxWidth >> 1) - ((screenWidth<<doublePixels) >> 1);
872 if (hCenter < 0) hCenter = 0;
873 int vCenter = (gx_displayprop.cyHeight >> 1) - ((screenHeight<<doublePixels) >> 1);
874 if (vCenter < 0) vCenter = 0;
875
876 int rx2 = rect.x2;
877 int ry2 = rect.y2;
878
879 if (rx2 > width) rx2 = width;
880 if (ry2 > height) ry2 = height;
881
882 if (!doublePixels)
883 {
884 for (int y=rect.y1; y<ry2; y++)
885 {
886 unsigned short* pixel = buffer+((rect.x1+hCenter)*hcbxpitch) + ((y+vCenter)*hcbypitch);
887 for (int x=rect.x1; x<rx2; x++)
888
889 {
890 *pixel = *vscr;
891 pixel+=hcbxpitch;
892 vscr++;
893 }
894
895 vscr+=screenWidth - (rx2 - rect.x1);
896 }
897 }
898 else
899 {
900 for (int y=rect.y1; y<ry2; y++)
901 {
902 int x;
903
904 unsigned short* pixel = buffer+((rect.x1*2+hCenter)*hcbxpitch) + ((y*2+vCenter)*hcbypitch);
905 unsigned short* src = vscr;
906 for (x=rect.x1; x<rx2; x++)
907 {
908 *pixel = *vscr;
909 pixel+=hcbxpitch;
910 *pixel = *vscr;
911 pixel+=hcbxpitch;
912 vscr++;
913 }
914
915 pixel = buffer+((rect.x1*2+hCenter)*hcbxpitch) + ((y*2+1+vCenter)*hcbypitch);
916 vscr = src;
917 for (x=rect.x1; x<rx2; x++)
918 {
919 *pixel = *vscr;
920 pixel+=hcbxpitch;
921 *pixel = *vscr;
922 pixel+=hcbxpitch;
923 vscr++;
924 }
925
926 vscr+=screenWidth - (rx2 - rect.x1);
927 }
928 }
929
930 break;
931 };
932 }
933
934 }
935 else
936 {
937 // 15 bit color is not supported
938 }
939
940 // End the drawing code
941 GXEndDraw();
942
943 globalMutex->unlock();
944 }
945
UpdateScreen()946 void UpdateScreen()
947 {
948 if (myTrackerScreen)
949 {
950 myTrackerScreen->paint();
951 }
952 UpdateScreen(vScreen);
953 }
954
DrawBackground(bool shade)955 void DrawBackground(bool shade)
956 {
957 if (!gxActive)
958 return;
959
960 globalMutex->lock();
961
962 // Get the start of the screen memory from the GX function.
963 unsigned short * buffer = (unsigned short *) GXBeginDraw();
964
965 if (buffer == NULL)
966 {
967 globalMutex->unlock();
968 return;
969 }
970
971 const unsigned int screenWidth = gx_displayprop.cxWidth;
972 const unsigned int screenHeight = gx_displayprop.cyHeight;
973
974 const unsigned int hcbxpitch = gx_displayprop.cbxPitch >> 1;
975 const unsigned int hcbypitch = gx_displayprop.cbyPitch >> 1;
976
977 if (shade)
978 {
979 PPColor col = GlobalColorConfig::getInstance()->getColor(GlobalColorConfig::ColorTheme);
980
981 PPColor srcCol = col, dstCol = col;
982 srcCol.scaleFixed(32768);
983
984 for (unsigned int y = 0; y < screenHeight; y++)
985 for (unsigned int x = 0; x < screenWidth; x++)
986 {
987 unsigned short* pixel = buffer+x*hcbxpitch+y*hcbypitch;
988
989 int r,g,b;
990
991 switch (orientation)
992 {
993 case eOrientation90CW:
994 {
995 int s = (x*65536) / screenWidth;
996
997 r = ((srcCol.r) * s + dstCol.r * (65535-s)) >> (16 + 3);
998 g = ((srcCol.g) * s + dstCol.g * (65535-s)) >> (16 + 2);
999 b = ((srcCol.b) * s + dstCol.b * (65535-s)) >> (16 + 3);
1000 break;
1001 }
1002
1003 case eOrientation90CCW:
1004 {
1005 int s = (x*65536) / screenWidth;
1006
1007 r = ((srcCol.r) * (65535-s) + dstCol.r * s) >> (16 + 3);
1008 g = ((srcCol.g) * (65535-s) + dstCol.g * s) >> (16 + 2);
1009 b = ((srcCol.b) * (65535-s) + dstCol.b * s) >> (16 + 3);
1010 break;
1011 }
1012
1013 case eOrientationNormal:
1014 {
1015 int s = (y*65536) / screenHeight;
1016
1017 r = ((srcCol.r) * s + dstCol.r * (65535-s)) >> (16 + 3);
1018 g = ((srcCol.g) * s + dstCol.g * (65535-s)) >> (16 + 2);
1019 b = ((srcCol.b) * s + dstCol.b * (65535-s)) >> (16 + 3);
1020 break;
1021 }
1022 }
1023
1024 *pixel = (r << 11) + (g << 5) + b;
1025 }
1026 }
1027 else
1028 {
1029 for (unsigned int y = 0; y < screenHeight; y++)
1030 for (unsigned int x = 0; x < screenWidth; x++)
1031 {
1032 unsigned short* pixel = buffer+x*hcbxpitch+y*hcbypitch;
1033 *pixel = 0;
1034 }
1035 }
1036
1037 // End the drawing code
1038 GXEndDraw();
1039
1040 globalMutex->unlock();
1041 }
1042
NeedsDrawBackground()1043 bool NeedsDrawBackground()
1044 {
1045 switch (orientation)
1046 {
1047 case eOrientation90CCW:
1048 case eOrientation90CW:
1049 {
1050 return (gx_displayprop.cxWidth != (unsigned)windowSize.height) || (gx_displayprop.cyHeight != (unsigned)windowSize.width);
1051 }
1052
1053 case eOrientationNormal:
1054 {
1055 return (gx_displayprop.cxWidth != (unsigned)windowSize.width) || (gx_displayprop.cyHeight != (unsigned)windowSize.height);
1056 }
1057 }
1058
1059 return false;
1060 }
1061
TrackerCreate()1062 void TrackerCreate()
1063 {
1064 myTracker = new Tracker();
1065
1066 windowSize = myTracker->getWindowSizeFromDatabase();
1067 #ifdef __LOWRES__
1068 windowSize.width = DISPLAYDEVICE_WIDTH;
1069 windowSize.height = DISPLAYDEVICE_HEIGHT;
1070 #endif
1071
1072 // Allocate virtual screen
1073 vScreen = new unsigned short[windowSize.width*windowSize.height];
1074
1075 // Clear virtual screen
1076 memset(vScreen, 0, windowSize.width*windowSize.height*sizeof(unsigned short));
1077
1078 myDisplayDevice = new PPDisplayDevice(hWnd, windowSize.width, windowSize.height);
1079
1080 myDisplayDevice->setSize(windowSize);
1081
1082 myTrackerScreen = new PPScreen(myDisplayDevice, myTracker);
1083 myTracker->setScreen(myTrackerScreen);
1084 }
1085
1086
TrackerStartUp(bool showSplash)1087 void TrackerStartUp(bool showSplash)
1088 {
1089 // Startup procedure
1090 myTracker->startUp(true);
1091
1092 WaitStateThread::getInstance()->activate(FALSE);
1093
1094 myTrackerScreen->enableDisplay(true);
1095
1096 if (showSplash)
1097 myTracker->hideSplash();
1098
1099 // clear screen with shade if necessary
1100 if (NeedsDrawBackground())
1101 DrawBackground();
1102
1103 myTrackerScreen->paint(false);
1104 }
1105
TrackerInitGUI(bool showSplash)1106 void TrackerInitGUI(bool showSplash)
1107 {
1108 // clear screen with black if necessary
1109 if (NeedsDrawBackground())
1110 DrawBackground(false);
1111
1112 if (showSplash)
1113 myTracker->showSplash();
1114
1115 myTrackerScreen->enableDisplay(false);
1116
1117 // Put init message on screen
1118 drawString("initializing", vScreen, windowSize.width, (windowSize.width>>1)-12*4, (windowSize.height>>1)-12, 0xFFFF);
1119
1120 WaitStateThread::getInstance()->setDisplayResolution(windowSize.width, windowSize.height);
1121
1122 WaitStateThread::getInstance()->activate(TRUE, TRUE, FALSE);
1123 }
1124
1125 #ifdef DEBUG
LogWinMsg(CLogger & logger,LPCTSTR msg,LPARAM lParam)1126 void LogWinMsg(CLogger& logger, LPCTSTR msg, LPARAM lParam)
1127 {
1128 TCHAR dummy[1024];
1129
1130 wsprintf(dummy, _T("%x"), lParam);
1131
1132 SimpleString logstr(msg);
1133 logstr.append(_T(": "));
1134 logstr.append(dummy);
1135
1136 logger.Log(logstr);
1137 }
1138
1139
LogMouseDown(CLogger & logger,LPARAM lParam,const PPPoint & point)1140 void LogMouseDown(CLogger& logger, LPARAM lParam, const PPPoint& point)
1141 {
1142 TCHAR dummy[1024];
1143
1144 wsprintf(dummy, _T("Before: %i, %i"), LOWORD(lParam), HIWORD(lParam));
1145
1146 SimpleString logstr(dummy);
1147 logstr.append(_T(" "));
1148 wsprintf(dummy, _T("After: %i, %i"), point.x, point.y);
1149 logstr.append(dummy);
1150
1151 logger.Log(logstr);
1152 }
1153 #endif
1154
WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)1155 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
1156 {
1157 static bool LMouseDrag = false;
1158 static PPPoint LMouseDragStartPoint;
1159 static bool RMouseDrag = false;
1160 static PPPoint RMouseDragStartPoint;
1161
1162 static DWORD ltime;
1163 static PPPoint llastClickPosition = PPPoint(0,0);
1164 static WORD lClickCount = 0;
1165
1166 static BOOL lMouseDown = FALSE;
1167 static DWORD lButtonDownStartTime;
1168
1169 static BOOL rMouseDown = FALSE;
1170 static DWORD rtime;
1171 static PPPoint rlastClickPosition = PPPoint(0,0);
1172 static WORD rClickCount = 0;
1173
1174 static DWORD rButtonDownStartTime;
1175
1176 static DWORD timerTicker = 0;
1177 static DWORD idleResetCounter = 1;
1178
1179 static PPPoint p;
1180
1181 if (lClickCount > 4)
1182 {
1183 lClickCount = 0;
1184 }
1185 if (rClickCount > 4)
1186 {
1187 rClickCount = 0;
1188 }
1189
1190 switch (msg)
1191 {
1192 #ifdef WINDOWS_DEFAULT_TIMER
1193 case WM_PAINT:
1194 DefWindowProc(hWnd, msg, wParam, lParam);
1195 return 0;
1196 #else
1197 case WM_PAINT:
1198 return 0;
1199 #endif
1200
1201 case WM_SIZE:
1202 {
1203 #ifdef DEBUG
1204 LogWinMsg(*logger, _T("WM_SIZE"), lParam);
1205 #endif
1206 break;
1207 }
1208
1209 // ----- left mousebutton -------------------------------
1210 case WM_LBUTTONDOWN:
1211 {
1212 if (!myTrackerScreen || rMouseDown)
1213 break;
1214
1215 POINTFROMPARAM(p, lParam);
1216
1217 #ifdef DEBUG
1218 LogWinMsg(*logger, _T("WM_LBUTTONDOWN"), lParam);
1219 LogMouseDown(*logger, lParam, p);
1220 #endif
1221
1222 PPEvent myEvent(eLMouseDown, &p, sizeof(PPPoint));
1223 myTrackerScreen->raiseEvent(&myEvent);
1224
1225 lMouseDown = TRUE;
1226 //lButtonDownStartTime = timerTicker;
1227 lButtonDownStartTime = GetTickCount();
1228
1229 if (!lClickCount)
1230 {
1231 ltime = GetTickCount();
1232 POINTFROMPARAM(llastClickPosition, lParam);
1233 }
1234 else if (lClickCount == 2)
1235 {
1236 DWORD deltat = GetTickCount() - ltime;
1237 if (deltat > DBLCLKTIME)
1238 {
1239 lClickCount = 0;
1240 ltime = GetTickCount();
1241 POINTFROMPARAM(llastClickPosition, lParam);
1242 }
1243 }
1244 lClickCount++;
1245 break;
1246 }
1247
1248 // ----- right mousebutton -------------------------------
1249 case WM_RBUTTONDOWN:
1250 {
1251 if (!myTrackerScreen || lMouseDown)
1252 break;
1253
1254 POINTFROMPARAM(p, lParam);
1255
1256 PPEvent myEvent(eRMouseDown, &p, sizeof(PPPoint));
1257 myTrackerScreen->raiseEvent(&myEvent);
1258
1259 rMouseDown = TRUE;
1260 //rButtonDownStartTime = timerTicker;
1261 rButtonDownStartTime = GetTickCount();
1262
1263 if (!rClickCount)
1264 {
1265 rtime = GetTickCount();
1266 POINTFROMPARAM(rlastClickPosition, lParam);
1267 }
1268 else if (rClickCount == 2)
1269 {
1270 DWORD deltat = GetTickCount() - rtime;
1271 if (deltat > DBLCLKTIME)
1272 {
1273 rClickCount = 0;
1274 rtime = GetTickCount();
1275 POINTFROMPARAM(rlastClickPosition, lParam);
1276 }
1277 }
1278 rClickCount++;
1279 break;
1280 }
1281
1282 // ----- left mousebutton -------------------------------
1283 case WM_LBUTTONUP:
1284 {
1285 LMouseDrag = false;
1286
1287 if (!myTrackerScreen || !lMouseDown)
1288 break;
1289
1290 lClickCount++;
1291
1292 if (lClickCount == 4)
1293 {
1294 DWORD deltat = GetTickCount() - ltime;
1295
1296 if (deltat < DBLCLKTIME)
1297 {
1298 POINTFROMPARAM(p, lParam);
1299
1300 if (abs(p.x - llastClickPosition.x) < 4 &&
1301 abs(p.y - llastClickPosition.y) < 4)
1302 {
1303
1304 PPEvent myEvent(eLMouseDoubleClick, &p, sizeof(PPPoint));
1305 myTrackerScreen->raiseEvent(&myEvent);
1306 }
1307 }
1308
1309 lClickCount = 0;
1310
1311 }
1312
1313 POINTFROMPARAM(p, lParam);
1314 PPEvent myEvent(eLMouseUp, &p, sizeof(PPPoint));
1315 myTrackerScreen->raiseEvent(&myEvent);
1316 lMouseDown = FALSE;
1317 break;
1318 }
1319
1320 // ----- right mousebutton -------------------------------
1321 case WM_RBUTTONUP:
1322 {
1323 RMouseDrag = false;
1324
1325 if (!myTrackerScreen || !rMouseDown)
1326 break;
1327
1328 rClickCount++;
1329
1330 if (rClickCount == 4)
1331 {
1332 DWORD deltat = GetTickCount() - rtime;
1333 if (deltat < DBLCLKTIME)
1334 {
1335 POINTFROMPARAM(p, lParam);
1336 if (abs(p.x - rlastClickPosition.x) < 4 &&
1337 abs(p.y - rlastClickPosition.y) < 4)
1338 {
1339 PPEvent myEvent(eRMouseDoubleClick, &p, sizeof(PPPoint));
1340 myTrackerScreen->raiseEvent(&myEvent);
1341 }
1342 }
1343
1344 rClickCount = 0;
1345 }
1346
1347 POINTFROMPARAM(p, lParam);
1348 PPEvent myEvent(eRMouseUp, &p, sizeof(PPPoint));
1349 myTrackerScreen->raiseEvent(&myEvent);
1350 rMouseDown = FALSE;
1351 break;
1352 }
1353
1354 case WM_MOUSEMOVE:
1355 {
1356 if (!myTrackerScreen)
1357 break;
1358
1359 if ((wParam&MK_LBUTTON) && lMouseDown)
1360 {
1361 POINTFROMPARAM(p, lParam);
1362
1363 if (!LMouseDrag)
1364 {
1365 LMouseDragStartPoint = p;
1366 LMouseDrag = true;
1367 }
1368
1369 if (LMouseDrag && (abs(LMouseDragStartPoint.x - p.x) >= DRAGSENSITIVITY ||
1370 abs(LMouseDragStartPoint.y - p.y) >= DRAGSENSITIVITY))
1371 {
1372 PPEvent myEvent(eLMouseDrag, &p, sizeof(PPPoint));
1373 myTrackerScreen->raiseEvent(&myEvent);
1374 }
1375
1376 }
1377 else if ((wParam&MK_RBUTTON) && rMouseDown)
1378 {
1379 POINTFROMPARAM(p, lParam);
1380
1381 if (!RMouseDrag)
1382 {
1383 RMouseDragStartPoint = p;
1384 RMouseDrag = true;
1385 }
1386
1387 if (RMouseDrag && (abs(RMouseDragStartPoint.x - p.x) >= DRAGSENSITIVITY ||
1388 abs(RMouseDragStartPoint.y - p.y) >= DRAGSENSITIVITY))
1389 {
1390
1391 PPEvent myEvent(eRMouseDrag, &p, sizeof(PPPoint));
1392 myTrackerScreen->raiseEvent(&myEvent);
1393 }
1394
1395 }
1396 else
1397 {
1398 POINTFROMPARAM(p, lParam);
1399 PPEvent myEvent(eMouseMoved, &p, sizeof(PPPoint));
1400 myTrackerScreen->raiseEvent(&myEvent);
1401 }
1402 break;
1403 }
1404
1405 #ifdef WINDOWS_DEFAULT_TIMER
1406 case WM_TIMER:
1407 #else
1408 case WM_MYTIMER:
1409 #endif
1410 {
1411 if (!myTrackerScreen)
1412 break;
1413
1414 if (!(timerTicker % 1))
1415 {
1416 PPEvent myEvent(eTimer);
1417 myTrackerScreen->raiseEvent(&myEvent);
1418 }
1419
1420 // reset idle timer, so the device will not turn off
1421 // automatically
1422 // handle with care and use only when forced to do so
1423 if (!(idleResetCounter & 1023) && dontTurnOffDevice)
1424 {
1425 SystemIdleTimerReset();
1426 }
1427
1428 idleResetCounter++;
1429 timerTicker++;
1430 DWORD currentTime = GetTickCount();
1431
1432 if (lMouseDown &&
1433 (currentTime - lButtonDownStartTime) > 500)
1434 {
1435 PPEvent myEvent(eLMouseRepeat, &p, sizeof(PPPoint));
1436 myTrackerScreen->raiseEvent(&myEvent);
1437 }
1438 else if (rMouseDown &&
1439 (currentTime - rButtonDownStartTime) > 500)
1440 {
1441 PPEvent myEvent(eRMouseRepeat, &p, sizeof(PPPoint));
1442 myTrackerScreen->raiseEvent(&myEvent);
1443 }
1444
1445 break;
1446 }
1447
1448 case WM_CLOSE:
1449 {
1450 if (myTrackerScreen && myTracker)
1451 {
1452 PPEvent e(eAppQuit);
1453 myTrackerScreen->raiseEvent(&e);
1454
1455 bool res = myTracker->shutDown();
1456
1457 if (res)
1458 DestroyWindow(hWnd);
1459 }
1460 else
1461 {
1462 DestroyWindow(hWnd);
1463 }
1464
1465 break;
1466 }
1467
1468 case WM_SETTINGCHANGE:
1469 TaskBar(false);
1470 break;
1471
1472
1473 case WM_KEYDOWN:
1474 case WM_SYSKEYDOWN:
1475
1476 #ifdef DEBUG
1477 ::PostMessage(hWnd, WM_CLOSE, 0, 0);
1478 #endif
1479
1480 if (wParam < 256)
1481 {
1482 if (mappings[wParam].keyModifiers != 0xFFFF &&
1483 mappings[wParam].virtualKeyCode != 0xFFFF)
1484 {
1485 pp_int32 i;
1486
1487 WORD vkModifiers[3] = {VK_ALT, VK_SHIFT, VK_CONTROL};
1488
1489 for (i = 0; i < 3; i++)
1490 if (mappings[wParam].keyModifiers & (1 << i))
1491 {
1492 // modifier key:
1493 // scan code and character code remains zero
1494 pp_uint16 vk[3] = {vkModifiers[i], 0, 0};
1495 PPEvent eventKeyDown(eKeyDown, &vk, sizeof(vk));
1496 myTrackerScreen->raiseEvent(&eventKeyDown);
1497 }
1498
1499 setForceKeyModifier((KeyModifiers)mappings[wParam].keyModifiers);
1500
1501 // functionality key:
1502 // scan code and character code remains zero
1503 pp_uint16 vk[3] = {mappings[wParam].virtualKeyCode, 0, 0};
1504 PPEvent eventKeyDown(eKeyDown, &vk, sizeof(vk));
1505 myTrackerScreen->raiseEvent(&eventKeyDown);
1506 }
1507 else if (allowVirtualKeys)
1508 {
1509 QueryKeyModifiers();
1510
1511 WORD character = MapVirtualKey(wParam & 0xFFFF, 2);
1512
1513 // Check for right ALT key
1514 if (::GetAsyncKeyState(VK_RMENU)>>15)
1515 wParam = VK_RMENU;
1516 // Check for right CTRL key
1517 else if (::GetAsyncKeyState(VK_RCONTROL)>>15)
1518 wParam = VK_RCONTROL;
1519
1520 if (wParam == VK_MENU)
1521 wParam = VK_ALT;
1522
1523 // Since scancodes probably differ from desktop keyboards
1524 // we do some virtual key => scancode transformation here
1525 WORD chr[3] = {wParam, vkeyToScancode[wParam&255], character};
1526
1527 PPEvent myEvent(eKeyDown, &chr, sizeof(chr));
1528
1529 myTrackerScreen->raiseEvent(&myEvent);
1530 }
1531 }
1532
1533 break;
1534
1535 case WM_KEYUP:
1536 case WM_SYSKEYUP:
1537 if (wParam < 256)
1538 {
1539 if (mappings[wParam].keyModifiers != 0xFFFF &&
1540 mappings[wParam].virtualKeyCode != 0xFFFF)
1541 {
1542 pp_int32 i;
1543
1544 WORD vkModifiers[3] = {VK_ALT, VK_SHIFT, VK_CONTROL};
1545
1546 // functionality key:
1547 // scan code and character code remains zero
1548 pp_uint16 vk[3] = {mappings[wParam].virtualKeyCode, 0, 0};
1549 PPEvent eventKeyUp(eKeyUp, &vk, sizeof(vk));
1550 myTrackerScreen->raiseEvent(&eventKeyUp);
1551
1552 for (i = 0; i < 3; i++)
1553 if (mappings[wParam].keyModifiers & (1 << (2-i)))
1554 {
1555 // modifier key:
1556 // scan code and character code remains zero
1557 pp_uint16 vk[3] = {vkModifiers[i], 0, 0};
1558 PPEvent eventKeyUp(eKeyUp, &vk, sizeof(vk));
1559 myTrackerScreen->raiseEvent(&eventKeyUp);
1560 }
1561
1562 clearForceKeyModifier((KeyModifiers)mappings[wParam].keyModifiers);
1563 }
1564 else if (allowVirtualKeys)
1565 {
1566 WORD character = MapVirtualKey(wParam & 0xFFFF, 2);
1567
1568 if (wParam == VK_MENU)
1569 wParam = VK_ALT;
1570
1571 // Since scancodes probably differ from desktop keyboards
1572 // we do some virtual key => scancode transformation here
1573 WORD chr[3] = {wParam, vkeyToScancode[wParam&255], character};
1574
1575 PPEvent myEvent(eKeyUp, &chr, sizeof(chr));
1576
1577 myTrackerScreen->raiseEvent(&myEvent);
1578 }
1579 }
1580
1581 break;
1582
1583 case WM_CHAR:
1584 {
1585 WORD chr = wParam;
1586
1587 if (chr < 32 || chr > 127)
1588 break;
1589
1590 PPEvent myEvent(eKeyChar, &chr, sizeof(chr));
1591
1592 myTrackerScreen->raiseEvent(&myEvent);
1593
1594 break;
1595 }
1596
1597 case WM_DESTROY:
1598 PostQuitMessage(0);
1599 break;
1600
1601 case WM_KILLFOCUS:
1602 GXSuspend();
1603 break;
1604
1605 case WM_SETFOCUS:
1606 GXResume();
1607 break;
1608
1609 /*case WM_SETTINGCHANGE:
1610 SHHandleWMSettingChange(hWnd, wParam,lParam,&s_sai);
1611 break;*/
1612 }
1613
1614 return DefWindowProc(hWnd, msg, wParam, lParam);
1615 }
1616
1617 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1618 // -------------------------- debugging --------------------------------------------------------------------- //
1619 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
drawChar(unsigned short * buffer,unsigned int pitch,unsigned int chr,unsigned int tx,unsigned int ty,unsigned short col)1620 void drawChar(unsigned short* buffer, unsigned int pitch, unsigned int chr,unsigned int tx,unsigned int ty,unsigned short col)
1621 {
1622 PPFont* font = PPFont::getFont(PPFont::FONT_SYSTEM);
1623
1624 unsigned int x,y;
1625
1626 for (y=0;y<8;y++)
1627 for (x=0;x<8;x++)
1628 if (font->getPixelBit(chr, x, y))
1629 buffer[((ty+y)*pitch+(tx+x))]=col;
1630 }
1631
drawString(const char * textBuffer,unsigned short * drawBuffer,unsigned int pitch,unsigned int posx,unsigned int posy,unsigned short col)1632 void drawString(const char* textBuffer,unsigned short* drawBuffer, unsigned int pitch, unsigned int posx,unsigned int posy, unsigned short col)
1633 {
1634 unsigned int x = posx;
1635 while (*textBuffer)
1636 {
1637 drawChar(drawBuffer, pitch, *textBuffer,x,posy,col);
1638 textBuffer++;
1639 x+=8;
1640 }
1641 }
1642