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