svn merge -r 13452:14721 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / intern / ghost / intern / GHOST_SystemWin32.cpp
1 /**
2  * $Id$
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /**
30
31  * $Id$
32  * Copyright (C) 2001 NaN Technologies B.V.
33  * @author      Maarten Gribnau
34  * @date        May 7, 2001
35  */
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
42
43 #include "GHOST_SystemWin32.h"
44
45 /*
46  * According to the docs the mouse wheel message is supported from windows 98 
47  * upwards. Leaving WINVER at default value, the WM_MOUSEWHEEL message and the 
48  * wheel detent value are undefined.
49  */
50 #ifndef WM_MOUSEWHEEL
51 #define WM_MOUSEWHEEL 0x020A
52 #endif // WM_MOUSEWHEEL
53 #ifndef WHEEL_DELTA
54 #define WHEEL_DELTA 120 /* Value for rolling one detent, (old convention! MS changed it) */
55 #endif // WHEEL_DELTA
56
57
58 #include "GHOST_Debug.h"
59 #include "GHOST_DisplayManagerWin32.h"
60 #include "GHOST_EventButton.h"
61 #include "GHOST_EventCursor.h"
62 #include "GHOST_EventKey.h"
63 #include "GHOST_EventWheel.h"
64 #include "GHOST_EventNDOF.h"
65 #include "GHOST_TimerTask.h"
66 #include "GHOST_TimerManager.h"
67 #include "GHOST_WindowManager.h"
68 #include "GHOST_WindowWin32.h"
69 #include "GHOST_NDOFManager.h"
70
71 // Key code values not found in winuser.h
72 #ifndef VK_MINUS
73 #define VK_MINUS 0xBD
74 #endif // VK_MINUS
75 #ifndef VK_SEMICOLON
76 #define VK_SEMICOLON 0xBA
77 #endif // VK_SEMICOLON
78 #ifndef VK_PERIOD
79 #define VK_PERIOD 0xBE
80 #endif // VK_PERIOD
81 #ifndef VK_COMMA
82 #define VK_COMMA 0xBC
83 #endif // VK_COMMA
84 #ifndef VK_QUOTE
85 #define VK_QUOTE 0xDE
86 #endif // VK_QUOTE
87 #ifndef VK_BACK_QUOTE
88 #define VK_BACK_QUOTE 0xC0
89 #endif // VK_BACK_QUOTE
90 #ifndef VK_SLASH
91 #define VK_SLASH 0xBF
92 #endif // VK_SLASH
93 #ifndef VK_BACK_SLASH
94 #define VK_BACK_SLASH 0xDC
95 #endif // VK_BACK_SLASH
96 #ifndef VK_EQUALS
97 #define VK_EQUALS 0xBB
98 #endif // VK_EQUALS
99 #ifndef VK_OPEN_BRACKET
100 #define VK_OPEN_BRACKET 0xDB
101 #endif // VK_OPEN_BRACKET
102 #ifndef VK_CLOSE_BRACKET
103 #define VK_CLOSE_BRACKET 0xDD
104 #endif // VK_CLOSE_BRACKET
105 #ifndef VK_GR_LESS
106 #define VK_GR_LESS 0xE2
107 #endif // VK_GR_LESS
108
109
110 GHOST_SystemWin32::GHOST_SystemWin32()
111 : m_hasPerformanceCounter(false), m_freq(0), m_start(0),
112   m_seperateLeftRight(false),
113   m_seperateLeftRightInitialized(false)
114 {
115         m_displayManager = new GHOST_DisplayManagerWin32 ();
116         GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n");
117         m_displayManager->initialize();
118 }
119
120 GHOST_SystemWin32::~GHOST_SystemWin32()
121 {
122 }
123
124
125 GHOST_TUns64 GHOST_SystemWin32::getMilliSeconds() const
126 {
127         // Hardware does not support high resolution timers. We will use GetTickCount instead then.
128         if (!m_hasPerformanceCounter) {
129                 return ::GetTickCount();
130         }
131
132         // Retrieve current count
133         __int64 count = 0;
134         ::QueryPerformanceCounter((LARGE_INTEGER*)&count);
135
136         // Calculate the time passed since system initialization.
137         __int64 delta = 1000*(count-m_start);
138
139         GHOST_TUns64 t = (GHOST_TUns64)(delta/m_freq);
140         return t; 
141 }
142
143
144 GHOST_TUns8 GHOST_SystemWin32::getNumDisplays() const
145 {
146         GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::getNumDisplays(): m_displayManager==0\n");
147         GHOST_TUns8 numDisplays;
148         m_displayManager->getNumDisplays(numDisplays);
149         return numDisplays;
150 }
151
152
153 void GHOST_SystemWin32::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const
154 {
155         width = ::GetSystemMetrics(SM_CXSCREEN);
156         height= ::GetSystemMetrics(SM_CYSCREEN);
157 }
158
159
160 GHOST_IWindow* GHOST_SystemWin32::createWindow(
161         const STR_String& title, 
162         GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height,
163         GHOST_TWindowState state, GHOST_TDrawingContextType type,
164         bool stereoVisual)
165 {
166         GHOST_Window* window = 0;
167         window = new GHOST_WindowWin32 (title, left, top, width, height, state, type, stereoVisual);
168         if (window) {
169                 if (window->getValid()) {
170                         // Store the pointer to the window
171 //                      if (state != GHOST_kWindowStateFullScreen) {
172                                 m_windowManager->addWindow(window);
173 //                      }
174                 }
175                 else {
176                         delete window;
177                         window = 0;
178                 }
179         }
180         return window;
181 }
182
183
184 bool GHOST_SystemWin32::processEvents(bool waitForEvent)
185 {
186         MSG msg;
187         bool anyProcessed = false;
188
189         do {
190                 GHOST_TimerManager* timerMgr = getTimerManager();
191
192                 if (waitForEvent && !::PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE)) {
193 #if 1
194                         ::Sleep(1);
195 #else
196                         GHOST_TUns64 next = timerMgr->nextFireTime();
197                         
198                         if (next == GHOST_kFireTimeNever) {
199                                 ::WaitMessage();
200                         } else {
201                                 ::SetTimer(NULL, 0, next - getMilliSeconds(), NULL);
202                                 ::WaitMessage();
203                                 ::KillTimer(NULL, 0);
204                         }
205 #endif
206                 }
207
208                 if (timerMgr->fireTimers(getMilliSeconds())) {
209                         anyProcessed = true;
210                 }
211
212                 // Process all the events waiting for us
213                 while (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE) != 0) {
214                         ::TranslateMessage(&msg);
215                         ::DispatchMessage(&msg);
216                         anyProcessed = true;
217                 }
218         } while (waitForEvent && !anyProcessed);
219
220         return anyProcessed;
221 }
222
223
224 GHOST_TSuccess GHOST_SystemWin32::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const
225 {
226         POINT point;
227         bool success = ::GetCursorPos(&point) == TRUE;
228         x = point.x;
229         y = point.y;
230         return GHOST_kSuccess;
231 }
232
233
234 GHOST_TSuccess GHOST_SystemWin32::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) const
235 {
236         return ::SetCursorPos(x, y) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
237 }
238
239
240 GHOST_TSuccess GHOST_SystemWin32::getModifierKeys(GHOST_ModifierKeys& keys) const
241 {
242         /*
243         GetKeyState and GetAsyncKeyState only work with Win95, Win98, NT4,
244         Terminal Server and Windows 2000.
245         But on WinME it always returns zero. These two functions are simply
246         skipped by Millenium Edition!
247
248         Official explanation from Microsoft:
249         Intentionally disabled.
250         It didn't work all that well on some newer hardware, and worked less 
251         well with the passage of time, so it was fully disabled in ME.
252         */
253         if (m_seperateLeftRight && m_seperateLeftRightInitialized) {
254                 bool down = HIBYTE(::GetKeyState(VK_LSHIFT)) != 0;
255                 keys.set(GHOST_kModifierKeyLeftShift, down);
256                 down = HIBYTE(::GetKeyState(VK_RSHIFT)) != 0;
257                 keys.set(GHOST_kModifierKeyRightShift, down);
258                 down = HIBYTE(::GetKeyState(VK_LMENU)) != 0;
259                 keys.set(GHOST_kModifierKeyLeftAlt, down);
260                 down = HIBYTE(::GetKeyState(VK_RMENU)) != 0;
261                 keys.set(GHOST_kModifierKeyRightAlt, down);
262                 down = HIBYTE(::GetKeyState(VK_LCONTROL)) != 0;
263                 keys.set(GHOST_kModifierKeyLeftControl, down);
264                 down = HIBYTE(::GetKeyState(VK_RCONTROL)) != 0;
265                 keys.set(GHOST_kModifierKeyRightControl, down);
266         }
267         else {
268                 bool down = HIBYTE(::GetKeyState(VK_SHIFT)) != 0;
269                 keys.set(GHOST_kModifierKeyLeftShift, down);
270                 keys.set(GHOST_kModifierKeyRightShift, down);
271                 down = HIBYTE(::GetKeyState(VK_MENU)) != 0;
272                 keys.set(GHOST_kModifierKeyLeftAlt, down);
273                 keys.set(GHOST_kModifierKeyRightAlt, down);
274                 down = HIBYTE(::GetKeyState(VK_CONTROL)) != 0;
275                 keys.set(GHOST_kModifierKeyLeftControl, down);
276                 keys.set(GHOST_kModifierKeyRightControl, down);
277         }
278         return GHOST_kSuccess;
279 }
280
281
282 GHOST_TSuccess GHOST_SystemWin32::getButtons(GHOST_Buttons& buttons) const
283 {
284         /* Check for swapped buttons (left-handed mouse buttons)
285          * GetAsyncKeyState() will give back the state of the physical mouse buttons.
286          */
287         bool swapped = ::GetSystemMetrics(SM_SWAPBUTTON) == TRUE;
288
289         bool down = HIBYTE(::GetKeyState(VK_LBUTTON)) != 0;
290         buttons.set(swapped ? GHOST_kButtonMaskRight : GHOST_kButtonMaskLeft, down);
291
292         down = HIBYTE(::GetKeyState(VK_MBUTTON)) != 0;
293         buttons.set(GHOST_kButtonMaskMiddle, down);
294
295         down = HIBYTE(::GetKeyState(VK_RBUTTON)) != 0;
296         buttons.set(swapped ? GHOST_kButtonMaskLeft : GHOST_kButtonMaskRight, down);
297         return GHOST_kSuccess;
298 }
299
300
301 GHOST_TSuccess GHOST_SystemWin32::init()
302 {
303         GHOST_TSuccess success = GHOST_System::init();
304
305         // Determine whether this system has a high frequency performance counter. */
306         m_hasPerformanceCounter = ::QueryPerformanceFrequency((LARGE_INTEGER*)&m_freq) == TRUE;
307         if (m_hasPerformanceCounter) {
308                 GHOST_PRINT("GHOST_SystemWin32::init: High Frequency Performance Timer available\n")
309                 ::QueryPerformanceCounter((LARGE_INTEGER*)&m_start);
310         }
311         else {
312                 GHOST_PRINT("GHOST_SystemWin32::init: High Frequency Performance Timer not available\n")
313         }
314
315         if (success) {
316                 WNDCLASS wc;
317                 wc.style= CS_HREDRAW | CS_VREDRAW;
318                 wc.lpfnWndProc= s_wndProc;
319                 wc.cbClsExtra= 0;
320                 wc.cbWndExtra= 0;
321                 wc.hInstance= ::GetModuleHandle(0);
322                 wc.hIcon = ::LoadIcon(wc.hInstance, "APPICON");
323                 
324                 if (!wc.hIcon) {
325                         ::LoadIcon(NULL, IDI_APPLICATION);
326                 }
327                 wc.hCursor = ::LoadCursor(0, IDC_ARROW);
328                 wc.hbrBackground= (HBRUSH)::GetStockObject(BLACK_BRUSH);
329                 wc.lpszMenuName = 0;
330                 wc.lpszClassName= GHOST_WindowWin32::getWindowClassName();
331     
332                 // Use RegisterClassEx for setting small icon
333                 if (::RegisterClass(&wc) == 0) {
334                         success = GHOST_kFailure;
335                 }
336         }
337         return success;
338 }
339
340
341 GHOST_TSuccess GHOST_SystemWin32::exit()
342 {
343         return GHOST_System::exit();
344 }
345
346
347 GHOST_TKey GHOST_SystemWin32::convertKey(WPARAM wParam, LPARAM lParam) const
348 {
349         GHOST_TKey key;
350         bool isExtended = (lParam&(1<<24))?true:false;
351
352         if ((wParam >= '0') && (wParam <= '9')) {
353                 // VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39)
354                 key = (GHOST_TKey)(wParam - '0' + GHOST_kKey0);
355         }
356         else if ((wParam >= 'A') && (wParam <= 'Z')) {
357                 // VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A)
358                 key = (GHOST_TKey)(wParam - 'A' + GHOST_kKeyA);
359         }
360         else if ((wParam >= VK_F1) && (wParam <= VK_F24)) {
361                 key = (GHOST_TKey)(wParam - VK_F1 + GHOST_kKeyF1);
362         }
363         else {
364                 switch (wParam) {
365                 case VK_RETURN:
366                         key = isExtended?GHOST_kKeyNumpadEnter:GHOST_kKeyEnter;
367                         break;
368
369                 case VK_BACK:     key = GHOST_kKeyBackSpace;            break;
370                 case VK_TAB:      key = GHOST_kKeyTab;                          break;
371                 case VK_ESCAPE:   key = GHOST_kKeyEsc;                          break;
372                 case VK_SPACE:    key = GHOST_kKeySpace;                        break;
373                 case VK_PRIOR:    key = GHOST_kKeyUpPage;                       break;
374                 case VK_NEXT:     key = GHOST_kKeyDownPage;                     break;
375                 case VK_END:      key = GHOST_kKeyEnd;                          break;
376                 case VK_HOME:     key = GHOST_kKeyHome;                         break;
377                 case VK_INSERT:   key = GHOST_kKeyInsert;                       break;
378                 case VK_DELETE:   key = GHOST_kKeyDelete;                       break;
379                 case VK_LEFT:     key = GHOST_kKeyLeftArrow;            break;
380                 case VK_RIGHT:    key = GHOST_kKeyRightArrow;           break;
381                 case VK_UP:       key = GHOST_kKeyUpArrow;                      break;
382                 case VK_DOWN:     key = GHOST_kKeyDownArrow;            break;
383                 case VK_NUMPAD0:  key = GHOST_kKeyNumpad0;                      break;
384                 case VK_NUMPAD1:  key = GHOST_kKeyNumpad1;                      break;
385                 case VK_NUMPAD2:  key = GHOST_kKeyNumpad2;                      break;
386                 case VK_NUMPAD3:  key = GHOST_kKeyNumpad3;                      break;
387                 case VK_NUMPAD4:  key = GHOST_kKeyNumpad4;                      break;
388                 case VK_NUMPAD5:  key = GHOST_kKeyNumpad5;                      break;
389                 case VK_NUMPAD6:  key = GHOST_kKeyNumpad6;                      break;
390                 case VK_NUMPAD7:  key = GHOST_kKeyNumpad7;                      break;
391                 case VK_NUMPAD8:  key = GHOST_kKeyNumpad8;                      break;
392                 case VK_NUMPAD9:  key = GHOST_kKeyNumpad9;                      break;
393                 case VK_SNAPSHOT: key = GHOST_kKeyPrintScreen;          break;
394                 case VK_PAUSE:    key = GHOST_kKeyPause;                        break;
395                 case VK_MULTIPLY: key = GHOST_kKeyNumpadAsterisk;        break;
396                 case VK_SUBTRACT: key = GHOST_kKeyNumpadMinus;          break;
397                 case VK_DECIMAL:  key = GHOST_kKeyNumpadPeriod;         break;
398                 case VK_DIVIDE:   key = GHOST_kKeyNumpadSlash;          break;
399                 case VK_ADD:      key = GHOST_kKeyNumpadPlus;           break;
400
401                 case VK_SEMICOLON:              key = GHOST_kKeySemicolon;              break;
402                 case VK_EQUALS:                 key = GHOST_kKeyEqual;                  break;
403                 case VK_COMMA:                  key = GHOST_kKeyComma;                  break;
404                 case VK_MINUS:                  key = GHOST_kKeyMinus;                  break;
405                 case VK_PERIOD:                 key = GHOST_kKeyPeriod;                 break;
406                 case VK_SLASH:                  key = GHOST_kKeySlash;                  break;
407                 case VK_BACK_QUOTE:             key = GHOST_kKeyAccentGrave;    break;
408                 case VK_OPEN_BRACKET:   key = GHOST_kKeyLeftBracket;    break;
409                 case VK_BACK_SLASH:             key = GHOST_kKeyBackslash;              break;
410                 case VK_CLOSE_BRACKET:  key = GHOST_kKeyRightBracket;   break;
411                 case VK_QUOTE:                  key = GHOST_kKeyQuote;                  break;
412                 case VK_GR_LESS:                key = GHOST_kKeyGrLess;                 break;
413
414                 // Process these keys separately because we need to distinguish right from left modifier keys
415                 case VK_SHIFT:
416                 case VK_CONTROL:
417                 case VK_MENU:
418
419                 // Ignore these keys
420                 case VK_NUMLOCK:
421                 case VK_SCROLL:
422                 case VK_CAPITAL:
423                 default:
424                         key = GHOST_kKeyUnknown;
425                         break;
426                 }
427         }
428         return key;
429 }
430
431
432 void GHOST_SystemWin32::processModifierKeys(GHOST_IWindow *window)
433 {
434         GHOST_ModifierKeys oldModifiers, newModifiers;
435         // Retrieve old state of the modifier keys
436         ((GHOST_SystemWin32*)getSystem())->retrieveModifierKeys(oldModifiers);
437         // Retrieve current state of the modifier keys
438         ((GHOST_SystemWin32*)getSystem())->getModifierKeys(newModifiers);
439
440         // Compare the old and the new
441         if (!newModifiers.equals(oldModifiers)) {
442                 // Create events for the masks that changed
443                 for (int i = 0; i < GHOST_kModifierKeyNumMasks; i++) {
444                         if (newModifiers.get((GHOST_TModifierKeyMask)i) != oldModifiers.get((GHOST_TModifierKeyMask)i)) {
445                                 // Convert the mask to a key code
446                                 GHOST_TKey key = GHOST_ModifierKeys::getModifierKeyCode((GHOST_TModifierKeyMask)i);
447                                 bool keyDown = newModifiers.get((GHOST_TModifierKeyMask)i);
448                                 GHOST_EventKey* event;
449                                 if (key != GHOST_kKeyUnknown) {
450                                         // Create an event
451                                         event = new GHOST_EventKey(getSystem()->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown: GHOST_kEventKeyUp, window, key);
452                                         pushEvent(event);
453                                 }
454                         }
455                 }
456         }
457
458         // Store new modifier keys state
459         ((GHOST_SystemWin32*)getSystem())->storeModifierKeys(newModifiers);
460 }
461
462
463 GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask)
464 {
465         return new GHOST_EventButton (getSystem()->getMilliSeconds(), type, window, mask);
466 }
467
468
469 GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *window)
470 {
471         GHOST_TInt32 x, y;
472         getSystem()->getCursorPosition(x, y);
473         return new GHOST_EventCursor (getSystem()->getMilliSeconds(), type, window, x, y);
474 }
475
476
477 GHOST_EventWheel* GHOST_SystemWin32::processWheelEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam)
478 {
479         // short fwKeys = LOWORD(wParam);                       // key flags
480         int zDelta = (short) HIWORD(wParam);    // wheel rotation
481         
482         // zDelta /= WHEEL_DELTA;
483         // temporary fix below: microsoft now has added more precision, making the above division not work
484         if (zDelta <= 0 ) zDelta= -1; else zDelta= 1;   
485         
486         // short xPos = (short) LOWORD(lParam); // horizontal position of pointer
487         // short yPos = (short) HIWORD(lParam); // vertical position of pointer
488         return new GHOST_EventWheel (getSystem()->getMilliSeconds(), window, zDelta);
489 }
490
491
492 GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, bool keyDown, WPARAM wParam, LPARAM lParam)
493 {
494         GHOST_TKey key = ((GHOST_SystemWin32*)getSystem())->convertKey(wParam, lParam);
495         GHOST_EventKey* event;
496         if (key != GHOST_kKeyUnknown) {
497                 MSG keyMsg;
498                 char ascii = '\0';
499
500                         /* Eat any character related messages */
501                 if (::PeekMessage(&keyMsg, NULL, WM_CHAR, WM_SYSDEADCHAR, PM_REMOVE)) {
502                         ascii = (char) keyMsg.wParam;
503                 }
504
505                 event = new GHOST_EventKey(getSystem()->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown: GHOST_kEventKeyUp, window, key, ascii);
506         }
507         else {
508                 event = 0;
509         }
510         return event;
511 }
512
513
514 GHOST_Event* GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window)
515 {
516         return new GHOST_Event(getSystem()->getMilliSeconds(), type, window);
517 }
518
519
520 LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
521 {
522         GHOST_Event* event = 0;
523         LRESULT lResult;
524         GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem());
525         GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized")
526
527         if (hwnd) {
528                 GHOST_WindowWin32* window = (GHOST_WindowWin32*)::GetWindowLong(hwnd, GWL_USERDATA);
529                 if (window) {
530                         switch (msg) {
531                                 ////////////////////////////////////////////////////////////////////////
532                                 // Keyboard events, processed
533                                 ////////////////////////////////////////////////////////////////////////
534                                 case WM_KEYDOWN:
535                                         /* The WM_KEYDOWN message is posted to the window with the keyboard focus when a 
536                                          * nonsystem key is pressed. A nonsystem key is a key that is pressed when the alt
537                                          * key is not pressed. 
538                                          */
539                                 case WM_SYSKEYDOWN:
540                                         /* The WM_SYSKEYDOWN message is posted to the window with the keyboard focus when 
541                                          * the user presses the F10 key (which activates the menu bar) or holds down the 
542                                          * alt key and then presses another key. It also occurs when no window currently 
543                                          * has the keyboard focus; in this case, the WM_SYSKEYDOWN message is sent to the 
544                                          * active window. The window that receives the message can distinguish between these 
545                                          * two contexts by checking the context code in the lKeyData parameter. 
546                                          */
547                                         switch (wParam) {
548                                                 case VK_SHIFT:
549                                                 case VK_CONTROL:
550                                                 case VK_MENU:
551                                                         if (!system->m_seperateLeftRightInitialized) {
552                                                                 // Check whether this system supports seperate left and right keys
553                                                                 switch (wParam) {
554                                                                         case VK_SHIFT:
555                                                                                 system->m_seperateLeftRight = 
556                                                                                         (HIBYTE(::GetKeyState(VK_LSHIFT)) != 0) ||
557                                                                                         (HIBYTE(::GetKeyState(VK_RSHIFT)) != 0) ?
558                                                                                         true : false;
559                                                                                 break;
560                                                                         case VK_CONTROL:
561                                                                                 system->m_seperateLeftRight = 
562                                                                                         (HIBYTE(::GetKeyState(VK_LCONTROL)) != 0) ||
563                                                                                         (HIBYTE(::GetKeyState(VK_RCONTROL)) != 0) ?
564                                                                                         true : false;
565                                                                                 break;
566                                                                         case VK_MENU:
567                                                                                 system->m_seperateLeftRight = 
568                                                                                         (HIBYTE(::GetKeyState(VK_LMENU)) != 0) ||
569                                                                                         (HIBYTE(::GetKeyState(VK_RMENU)) != 0) ?
570                                                                                         true : false;
571                                                                                 break;
572                                                                 }
573                                                                 system->m_seperateLeftRightInitialized = true;
574                                                         }
575                                                         system->processModifierKeys(window);
576                                                         // Bypass call to DefWindowProc
577                                                         return 0;
578                                                 default:
579                                                         event = processKeyEvent(window, true, wParam, lParam);
580                                                         if (!event) {
581                                                                 GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
582                                                                 GHOST_PRINT(msg)
583                                                                 GHOST_PRINT(" key ignored\n")
584                                                         }
585                                                         break;
586                                                 }
587                                         break;
588
589                                 case WM_KEYUP:
590                                 case WM_SYSKEYUP:
591                                         switch (wParam) {
592                                                 case VK_SHIFT:
593                                                 case VK_CONTROL:
594                                                 case VK_MENU:
595                                                         system->processModifierKeys(window);
596                                                         // Bypass call to DefWindowProc
597                                                         return 0;
598                                                 default:
599                                                         event = processKeyEvent(window, false, wParam, lParam);
600                                                         if (!event) {
601                                                                 GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
602                                                                 GHOST_PRINT(msg)
603                                                                 GHOST_PRINT(" key ignored\n")
604                                                         }
605                                                         break;
606                                         }
607                                         break;
608
609                                 ////////////////////////////////////////////////////////////////////////
610                                 // Keyboard events, ignored
611                                 ////////////////////////////////////////////////////////////////////////
612                                 case WM_CHAR:
613                                         /* The WM_CHAR message is posted to the window with the keyboard focus when 
614                                          * a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR 
615                                          * contains the character code of the key that was pressed. 
616                                          */
617                                 case WM_DEADCHAR:
618                                         /* The WM_DEADCHAR message is posted to the window with the keyboard focus when a
619                                          * WM_KEYUP message is translated by the TranslateMessage function. WM_DEADCHAR 
620                                          * specifies a character code generated by a dead key. A dead key is a key that 
621                                          * generates a character, such as the umlaut (double-dot), that is combined with 
622                                          * another character to form a composite character. For example, the umlaut-O 
623                                          * character (Ù) is generated by typing the dead key for the umlaut character, and 
624                                          * then typing the O key.
625                                          */
626                                 case WM_SYSDEADCHAR:
627                                         /* The WM_SYSDEADCHAR message is sent to the window with the keyboard focus when 
628                                          * a WM_SYSKEYDOWN message is translated by the TranslateMessage function. 
629                                          * WM_SYSDEADCHAR specifies the character code of a system dead key - that is, 
630                                          * a dead key that is pressed while holding down the alt key. 
631                                          */
632                                         break;
633                                 ////////////////////////////////////////////////////////////////////////
634                                 // Tablet events, processed
635                                 ////////////////////////////////////////////////////////////////////////
636                                 case WT_PACKET:
637                                         ((GHOST_WindowWin32*)window)->processWin32TabletEvent(wParam, lParam);
638                                         break;
639                                 case WT_CSRCHANGE:
640                                 case WT_PROXIMITY:
641                                         ((GHOST_WindowWin32*)window)->processWin32TabletInitEvent();
642                                         break;
643                                 ////////////////////////////////////////////////////////////////////////
644                                 // Mouse events, processed
645                                 ////////////////////////////////////////////////////////////////////////
646                                 case WM_LBUTTONDOWN:
647                                         window->registerMouseClickEvent(true);
648                                         event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskLeft);
649                                         break;
650                                 case WM_MBUTTONDOWN:
651                                         window->registerMouseClickEvent(true);
652                                         event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskMiddle);
653                                         break;
654                                 case WM_RBUTTONDOWN:
655                                         window->registerMouseClickEvent(true);
656                                         event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskRight);
657                                         break;
658                                 case WM_LBUTTONUP:
659                                         window->registerMouseClickEvent(false);
660                                         event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft);
661                                         break;
662                                 case WM_MBUTTONUP:
663                                         window->registerMouseClickEvent(false);
664                                         event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskMiddle);
665                                         break;
666                                 case WM_RBUTTONUP:
667                                         window->registerMouseClickEvent(false);
668                                         event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskRight);
669                                         break;
670                                 case WM_MOUSEMOVE:
671                                         event = processCursorEvent(GHOST_kEventCursorMove, window);
672                                         break;
673                                 case WM_MOUSEWHEEL:
674                                         /* The WM_MOUSEWHEEL message is sent to the focus window 
675                                          * when the mouse wheel is rotated. The DefWindowProc 
676                                          * function propagates the message to the window's parent.
677                                          * There should be no internal forwarding of the message, 
678                                          * since DefWindowProc propagates it up the parent chain 
679                                          * until it finds a window that processes it.
680                                          */
681                                         event = processWheelEvent(window, wParam, lParam);
682                                         break;
683                                 case WM_SETCURSOR:
684                                         /* The WM_SETCURSOR message is sent to a window if the mouse causes the cursor
685                                          * to move within a window and mouse input is not captured.
686                                          * This means we have to set the cursor shape every time the mouse moves!
687                                          * The DefWindowProc function uses this message to set the cursor to an 
688                                          * arrow if it is not in the client area.
689                                          */
690                                         if (LOWORD(lParam) == HTCLIENT) {
691                                                 // Load the current cursor
692                                                 window->loadCursor(window->getCursorVisibility(), window->getCursorShape());
693                                                 // Bypass call to DefWindowProc
694                                                 return 0;
695                                         } 
696                                         else {
697                                                 // Outside of client area show standard cursor
698                                                 window->loadCursor(true, GHOST_kStandardCursorDefault);
699                                         }
700                                         break;
701
702                                 ////////////////////////////////////////////////////////////////////////
703                                 // Mouse events, ignored
704                                 ////////////////////////////////////////////////////////////////////////
705                                 case WM_NCMOUSEMOVE:
706                                         /* The WM_NCMOUSEMOVE message is posted to a window when the cursor is moved 
707                                          * within the nonclient area of the window. This message is posted to the window 
708                                          * that contains the cursor. If a window has captured the mouse, this message is not posted.
709                                          */
710                                 case WM_NCHITTEST:
711                                         /* The WM_NCHITTEST message is sent to a window when the cursor moves, or 
712                                          * when a mouse button is pressed or released. If the mouse is not captured, 
713                                          * the message is sent to the window beneath the cursor. Otherwise, the message 
714                                          * is sent to the window that has captured the mouse. 
715                                          */
716                                         break;
717
718                                 ////////////////////////////////////////////////////////////////////////
719                                 // Window events, processed
720                                 ////////////////////////////////////////////////////////////////////////
721                                 case WM_CLOSE:
722                                         /* The WM_CLOSE message is sent as a signal that a window or an application should terminate. */
723                                         event = processWindowEvent(GHOST_kEventWindowClose, window);
724                                         break;
725                                 case WM_ACTIVATE:
726                                         /* The WM_ACTIVATE message is sent to both the window being activated and the window being 
727                                          * deactivated. If the windows use the same input queue, the message is sent synchronously, 
728                                          * first to the window procedure of the top-level window being deactivated, then to the window
729                                          * procedure of the top-level window being activated. If the windows use different input queues,
730                                          * the message is sent asynchronously, so the window is activated immediately. 
731                                          */
732                                         event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window);
733                                         break;
734                                 case WM_PAINT:
735                                         /* An application sends the WM_PAINT message when the system or another application 
736                                          * makes a request to paint a portion of an application's window. The message is sent
737                                          * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage 
738                                          * function when the application obtains a WM_PAINT message by using the GetMessage or 
739                                          * PeekMessage function. 
740                                          */
741                                         event = processWindowEvent(GHOST_kEventWindowUpdate, window);
742                                         ::ValidateRect(hwnd, NULL);
743                                         break;
744                                 case WM_SIZE:
745                                         /* The WM_SIZE message is sent to a window after its size has changed.
746                                          * The WM_SIZE and WM_MOVE messages are not sent if an application handles the 
747                                          * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
748                                          * to perform any move or size change processing during the WM_WINDOWPOSCHANGED 
749                                          * message without calling DefWindowProc.
750                                          */
751                                         event = processWindowEvent(GHOST_kEventWindowSize, window);
752                                 case WM_CAPTURECHANGED:
753                                         window->lostMouseCapture();
754                                         break;
755
756                                 ////////////////////////////////////////////////////////////////////////
757                                 // Window events, ignored
758                                 ////////////////////////////////////////////////////////////////////////
759                                 case WM_WINDOWPOSCHANGED:
760                                         /* The WM_WINDOWPOSCHANGED message is sent to a window whose size, position, or place
761                                          * in the Z order has changed as a result of a call to the SetWindowPos function or 
762                                          * another window-management function.
763                                          * The WM_SIZE and WM_MOVE messages are not sent if an application handles the 
764                                          * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
765                                          * to perform any move or size change processing during the WM_WINDOWPOSCHANGED 
766                                          * message without calling DefWindowProc.
767                                          */
768                                 case WM_MOVE:
769                                         /* The WM_SIZE and WM_MOVE messages are not sent if an application handles the 
770                                          * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
771                                          * to perform any move or size change processing during the WM_WINDOWPOSCHANGED 
772                                          * message without calling DefWindowProc. 
773                                          */
774                                 case WM_ERASEBKGND:
775                                         /* An application sends the WM_ERASEBKGND message when the window background must be 
776                                          * erased (for example, when a window is resized). The message is sent to prepare an 
777                                          * invalidated portion of a window for painting. 
778                                          */
779                                 case WM_NCPAINT:
780                                         /* An application sends the WM_NCPAINT message to a window when its frame must be painted. */
781                                 case WM_NCACTIVATE:
782                                         /* The WM_NCACTIVATE message is sent to a window when its nonclient area needs to be changed 
783                                          * to indicate an active or inactive state. 
784                                          */
785                                 case WM_DESTROY:
786                                         /* The WM_DESTROY message is sent when a window is being destroyed. It is sent to the window 
787                                          * procedure of the window being destroyed after the window is removed from the screen. 
788                                          * This message is sent first to the window being destroyed and then to the child windows 
789                                          * (if any) as they are destroyed. During the processing of the message, it can be assumed 
790                                          * that all child windows still exist. 
791                                          */
792                                 case WM_NCDESTROY:
793                                         /* The WM_NCDESTROY message informs a window that its nonclient area is being destroyed. The 
794                                          * DestroyWindow function sends the WM_NCDESTROY message to the window following the WM_DESTROY
795                                          * message. WM_DESTROY is used to free the allocated memory object associated with the window. 
796                                          */
797                                 case WM_KILLFOCUS:
798                                         /* The WM_KILLFOCUS message is sent to a window immediately before it loses the keyboard focus. */
799                                 case WM_SHOWWINDOW:
800                                         /* The WM_SHOWWINDOW message is sent to a window when the window is about to be hidden or shown. */
801                                 case WM_WINDOWPOSCHANGING:
802                                         /* The WM_WINDOWPOSCHANGING message is sent to a window whose size, position, or place in 
803                                          * the Z order is about to change as a result of a call to the SetWindowPos function or 
804                                          * another window-management function. 
805                                          */
806                                 case WM_SETFOCUS:
807                                         /* The WM_SETFOCUS message is sent to a window after it has gained the keyboard focus. */
808                                 case WM_MOVING:
809                                         /* The WM_MOVING message is sent to a window that the user is moving. By processing 
810                                          * this message, an application can monitor the size and position of the drag rectangle
811                                          * and, if needed, change its size or position.
812                                          */
813                                 case WM_ENTERSIZEMOVE:
814                                         /* The WM_ENTERSIZEMOVE message is sent one time to a window after it enters the moving 
815                                          * or sizing modal loop. The window enters the moving or sizing modal loop when the user 
816                                          * clicks the window's title bar or sizing border, or when the window passes the 
817                                          * WM_SYSCOMMAND message to the DefWindowProc function and the wParam parameter of the 
818                                          * message specifies the SC_MOVE or SC_SIZE value. The operation is complete when 
819                                          * DefWindowProc returns. 
820                                          */
821                                         break;
822                                         
823                                 ////////////////////////////////////////////////////////////////////////
824                                 // Other events
825                                 ////////////////////////////////////////////////////////////////////////
826                                 case WM_GETTEXT:
827                                         /* An application sends a WM_GETTEXT message to copy the text that 
828                                          * corresponds to a window into a buffer provided by the caller. 
829                                          */
830                                 case WM_ACTIVATEAPP:
831                                         /* The WM_ACTIVATEAPP message is sent when a window belonging to a 
832                                          * different application than the active window is about to be activated.
833                                          * The message is sent to the application whose window is being activated
834                                          * and to the application whose window is being deactivated. 
835                                          */
836                                 case WM_TIMER:
837                                         /* The WIN32 docs say:
838                                          * The WM_TIMER message is posted to the installing thread's message queue
839                                          * when a timer expires. You can process the message by providing a WM_TIMER
840                                          * case in the window procedure. Otherwise, the default window procedure will
841                                          * call the TimerProc callback function specified in the call to the SetTimer
842                                          * function used to install the timer. 
843                                          *
844                                          * In GHOST, we let DefWindowProc call the timer callback.
845                                          */
846                                         break;
847                                 case WM_BLND_NDOF_AXIS:
848                                         {
849                                                 GHOST_TEventNDOFData ndofdata;
850                                                 system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata);
851                                                 system->m_eventManager->
852                                                         pushEvent(new GHOST_EventNDOF(
853                                                                 system->getMilliSeconds(), 
854                                                                 GHOST_kEventNDOFMotion, 
855                                                                 window, ndofdata));
856                                         }
857                                         break;
858                                 case WM_BLND_NDOF_BTN:
859                                         {
860                                                 GHOST_TEventNDOFData ndofdata;
861                                                 system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata);
862                                                 system->m_eventManager->
863                                                         pushEvent(new GHOST_EventNDOF(
864                                                                 system->getMilliSeconds(), 
865                                                                 GHOST_kEventNDOFButton, 
866                                                                 window, ndofdata));
867                                         }
868                                         break;
869                         }
870                 }
871                 else {
872                         // Event found for a window before the pointer to the class has been set.
873                         GHOST_PRINT("GHOST_SystemWin32::wndProc: GHOST window event before creation\n")
874                         /* These are events we typically miss at this point:
875                            WM_GETMINMAXINFO     0x24
876                            WM_NCCREATE                  0x81
877                            WM_NCCALCSIZE                0x83
878                            WM_CREATE                    0x01
879                            We let DefWindowProc do the work.
880                         */
881                 }
882         }
883         else {
884                 // Events without valid hwnd
885                 GHOST_PRINT("GHOST_SystemWin32::wndProc: event without window\n")
886         }
887
888         if (event) {
889                 system->pushEvent(event);
890                 lResult = 0;
891         }
892         else {
893                 lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
894         }
895         return lResult;
896 }
897
898 GHOST_TUns8* GHOST_SystemWin32::getClipboard(int flag) const 
899 {
900         char *buffer;
901         char *temp_buff;
902         
903         if ( OpenClipboard(NULL) ) {
904                 HANDLE hData = GetClipboardData( CF_TEXT );
905                 buffer = (char*)GlobalLock( hData );
906                 
907                 temp_buff = (char*) malloc(strlen(buffer)+1);
908                 strcpy(temp_buff, buffer);
909                 
910                 GlobalUnlock( hData );
911                 CloseClipboard();
912                 
913                 temp_buff[strlen(buffer)] = '\0';
914                 if (buffer) {
915                         return (GHOST_TUns8*)temp_buff;
916                 } else {
917                         return NULL;
918                 }
919         } else {
920                 return NULL;
921         }
922 }
923
924 void GHOST_SystemWin32::putClipboard(GHOST_TInt8 *buffer, int flag) const
925 {
926         if(flag == 1) {return;} //If Flag is 1 means the selection and is used on X11
927         if (OpenClipboard(NULL)) {
928                 HLOCAL clipbuffer;
929                 char *data;
930                 
931                 if (buffer) {
932                         EmptyClipboard();
933                         
934                         clipbuffer = LocalAlloc(LMEM_FIXED,((strlen(buffer)+1)));
935                         data = (char*)GlobalLock(clipbuffer);
936
937                         strcpy(data, (char*)buffer);
938                         data[strlen(buffer)] = '\0';
939                         LocalUnlock(clipbuffer);
940                         SetClipboardData(CF_TEXT,clipbuffer);
941                 }
942                 CloseClipboard();
943         } else {
944                 return;
945         }
946 }
947