soc-2008-mxcurioni: implemented (without testing) StrokeShader, Stroke and MediumType...
[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         /* Disable scaling on high DPI displays on Vista */
306         HMODULE user32 = ::LoadLibraryA("user32.dll");
307         typedef BOOL (WINAPI * LPFNSETPROCESSDPIAWARE)();
308         LPFNSETPROCESSDPIAWARE SetProcessDPIAware =
309                 (LPFNSETPROCESSDPIAWARE)GetProcAddress(user32, "SetProcessDPIAware");
310         if (SetProcessDPIAware)
311                 SetProcessDPIAware();
312         FreeLibrary(user32);
313
314         // Determine whether this system has a high frequency performance counter. */
315         m_hasPerformanceCounter = ::QueryPerformanceFrequency((LARGE_INTEGER*)&m_freq) == TRUE;
316         if (m_hasPerformanceCounter) {
317                 GHOST_PRINT("GHOST_SystemWin32::init: High Frequency Performance Timer available\n")
318                 ::QueryPerformanceCounter((LARGE_INTEGER*)&m_start);
319         }
320         else {
321                 GHOST_PRINT("GHOST_SystemWin32::init: High Frequency Performance Timer not available\n")
322         }
323
324         if (success) {
325                 WNDCLASS wc;
326                 wc.style= CS_HREDRAW | CS_VREDRAW;
327                 wc.lpfnWndProc= s_wndProc;
328                 wc.cbClsExtra= 0;
329                 wc.cbWndExtra= 0;
330                 wc.hInstance= ::GetModuleHandle(0);
331                 wc.hIcon = ::LoadIcon(wc.hInstance, "APPICON");
332                 
333                 if (!wc.hIcon) {
334                         ::LoadIcon(NULL, IDI_APPLICATION);
335                 }
336                 wc.hCursor = ::LoadCursor(0, IDC_ARROW);
337                 wc.hbrBackground= (HBRUSH)::GetStockObject(BLACK_BRUSH);
338                 wc.lpszMenuName = 0;
339                 wc.lpszClassName= GHOST_WindowWin32::getWindowClassName();
340     
341                 // Use RegisterClassEx for setting small icon
342                 if (::RegisterClass(&wc) == 0) {
343                         success = GHOST_kFailure;
344                 }
345         }
346         return success;
347 }
348
349
350 GHOST_TSuccess GHOST_SystemWin32::exit()
351 {
352         return GHOST_System::exit();
353 }
354
355
356 GHOST_TKey GHOST_SystemWin32::convertKey(WPARAM wParam, LPARAM lParam) const
357 {
358         GHOST_TKey key;
359         bool isExtended = (lParam&(1<<24))?true:false;
360
361         if ((wParam >= '0') && (wParam <= '9')) {
362                 // VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39)
363                 key = (GHOST_TKey)(wParam - '0' + GHOST_kKey0);
364         }
365         else if ((wParam >= 'A') && (wParam <= 'Z')) {
366                 // VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A)
367                 key = (GHOST_TKey)(wParam - 'A' + GHOST_kKeyA);
368         }
369         else if ((wParam >= VK_F1) && (wParam <= VK_F24)) {
370                 key = (GHOST_TKey)(wParam - VK_F1 + GHOST_kKeyF1);
371         }
372         else {
373                 switch (wParam) {
374                 case VK_RETURN:
375                         key = isExtended?GHOST_kKeyNumpadEnter:GHOST_kKeyEnter;
376                         break;
377
378                 case VK_BACK:     key = GHOST_kKeyBackSpace;            break;
379                 case VK_TAB:      key = GHOST_kKeyTab;                          break;
380                 case VK_ESCAPE:   key = GHOST_kKeyEsc;                          break;
381                 case VK_SPACE:    key = GHOST_kKeySpace;                        break;
382                 case VK_PRIOR:    key = GHOST_kKeyUpPage;                       break;
383                 case VK_NEXT:     key = GHOST_kKeyDownPage;                     break;
384                 case VK_END:      key = GHOST_kKeyEnd;                          break;
385                 case VK_HOME:     key = GHOST_kKeyHome;                         break;
386                 case VK_INSERT:   key = GHOST_kKeyInsert;                       break;
387                 case VK_DELETE:   key = GHOST_kKeyDelete;                       break;
388                 case VK_LEFT:     key = GHOST_kKeyLeftArrow;            break;
389                 case VK_RIGHT:    key = GHOST_kKeyRightArrow;           break;
390                 case VK_UP:       key = GHOST_kKeyUpArrow;                      break;
391                 case VK_DOWN:     key = GHOST_kKeyDownArrow;            break;
392                 case VK_NUMPAD0:  key = GHOST_kKeyNumpad0;                      break;
393                 case VK_NUMPAD1:  key = GHOST_kKeyNumpad1;                      break;
394                 case VK_NUMPAD2:  key = GHOST_kKeyNumpad2;                      break;
395                 case VK_NUMPAD3:  key = GHOST_kKeyNumpad3;                      break;
396                 case VK_NUMPAD4:  key = GHOST_kKeyNumpad4;                      break;
397                 case VK_NUMPAD5:  key = GHOST_kKeyNumpad5;                      break;
398                 case VK_NUMPAD6:  key = GHOST_kKeyNumpad6;                      break;
399                 case VK_NUMPAD7:  key = GHOST_kKeyNumpad7;                      break;
400                 case VK_NUMPAD8:  key = GHOST_kKeyNumpad8;                      break;
401                 case VK_NUMPAD9:  key = GHOST_kKeyNumpad9;                      break;
402                 case VK_SNAPSHOT: key = GHOST_kKeyPrintScreen;          break;
403                 case VK_PAUSE:    key = GHOST_kKeyPause;                        break;
404                 case VK_MULTIPLY: key = GHOST_kKeyNumpadAsterisk;        break;
405                 case VK_SUBTRACT: key = GHOST_kKeyNumpadMinus;          break;
406                 case VK_DECIMAL:  key = GHOST_kKeyNumpadPeriod;         break;
407                 case VK_DIVIDE:   key = GHOST_kKeyNumpadSlash;          break;
408                 case VK_ADD:      key = GHOST_kKeyNumpadPlus;           break;
409
410                 case VK_SEMICOLON:              key = GHOST_kKeySemicolon;              break;
411                 case VK_EQUALS:                 key = GHOST_kKeyEqual;                  break;
412                 case VK_COMMA:                  key = GHOST_kKeyComma;                  break;
413                 case VK_MINUS:                  key = GHOST_kKeyMinus;                  break;
414                 case VK_PERIOD:                 key = GHOST_kKeyPeriod;                 break;
415                 case VK_SLASH:                  key = GHOST_kKeySlash;                  break;
416                 case VK_BACK_QUOTE:             key = GHOST_kKeyAccentGrave;    break;
417                 case VK_OPEN_BRACKET:   key = GHOST_kKeyLeftBracket;    break;
418                 case VK_BACK_SLASH:             key = GHOST_kKeyBackslash;              break;
419                 case VK_CLOSE_BRACKET:  key = GHOST_kKeyRightBracket;   break;
420                 case VK_QUOTE:                  key = GHOST_kKeyQuote;                  break;
421                 case VK_GR_LESS:                key = GHOST_kKeyGrLess;                 break;
422
423                 // Process these keys separately because we need to distinguish right from left modifier keys
424                 case VK_SHIFT:
425                 case VK_CONTROL:
426                 case VK_MENU:
427
428                 // Ignore these keys
429                 case VK_NUMLOCK:
430                 case VK_SCROLL:
431                 case VK_CAPITAL:
432                 default:
433                         key = GHOST_kKeyUnknown;
434                         break;
435                 }
436         }
437         return key;
438 }
439
440
441 void GHOST_SystemWin32::processModifierKeys(GHOST_IWindow *window)
442 {
443         GHOST_ModifierKeys oldModifiers, newModifiers;
444         // Retrieve old state of the modifier keys
445         ((GHOST_SystemWin32*)getSystem())->retrieveModifierKeys(oldModifiers);
446         // Retrieve current state of the modifier keys
447         ((GHOST_SystemWin32*)getSystem())->getModifierKeys(newModifiers);
448
449         // Compare the old and the new
450         if (!newModifiers.equals(oldModifiers)) {
451                 // Create events for the masks that changed
452                 for (int i = 0; i < GHOST_kModifierKeyNumMasks; i++) {
453                         if (newModifiers.get((GHOST_TModifierKeyMask)i) != oldModifiers.get((GHOST_TModifierKeyMask)i)) {
454                                 // Convert the mask to a key code
455                                 GHOST_TKey key = GHOST_ModifierKeys::getModifierKeyCode((GHOST_TModifierKeyMask)i);
456                                 bool keyDown = newModifiers.get((GHOST_TModifierKeyMask)i);
457                                 GHOST_EventKey* event;
458                                 if (key != GHOST_kKeyUnknown) {
459                                         // Create an event
460                                         event = new GHOST_EventKey(getSystem()->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown: GHOST_kEventKeyUp, window, key);
461                                         pushEvent(event);
462                                 }
463                         }
464                 }
465         }
466
467         // Store new modifier keys state
468         ((GHOST_SystemWin32*)getSystem())->storeModifierKeys(newModifiers);
469 }
470
471
472 GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask)
473 {
474         return new GHOST_EventButton (getSystem()->getMilliSeconds(), type, window, mask);
475 }
476
477
478 GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *window)
479 {
480         GHOST_TInt32 x, y;
481         getSystem()->getCursorPosition(x, y);
482         return new GHOST_EventCursor (getSystem()->getMilliSeconds(), type, window, x, y);
483 }
484
485
486 GHOST_EventWheel* GHOST_SystemWin32::processWheelEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam)
487 {
488         // short fwKeys = LOWORD(wParam);                       // key flags
489         int zDelta = (short) HIWORD(wParam);    // wheel rotation
490         
491         // zDelta /= WHEEL_DELTA;
492         // temporary fix below: microsoft now has added more precision, making the above division not work
493         if (zDelta <= 0 ) zDelta= -1; else zDelta= 1;   
494         
495         // short xPos = (short) LOWORD(lParam); // horizontal position of pointer
496         // short yPos = (short) HIWORD(lParam); // vertical position of pointer
497         return new GHOST_EventWheel (getSystem()->getMilliSeconds(), window, zDelta);
498 }
499
500
501 GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, bool keyDown, WPARAM wParam, LPARAM lParam)
502 {
503         GHOST_TKey key = ((GHOST_SystemWin32*)getSystem())->convertKey(wParam, lParam);
504         GHOST_EventKey* event;
505         if (key != GHOST_kKeyUnknown) {
506                 MSG keyMsg;
507                 char ascii = '\0';
508
509                         /* Eat any character related messages */
510                 if (::PeekMessage(&keyMsg, NULL, WM_CHAR, WM_SYSDEADCHAR, PM_REMOVE)) {
511                         ascii = (char) keyMsg.wParam;
512                 }
513
514                 event = new GHOST_EventKey(getSystem()->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown: GHOST_kEventKeyUp, window, key, ascii);
515         }
516         else {
517                 event = 0;
518         }
519         return event;
520 }
521
522
523 GHOST_Event* GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window)
524 {
525         return new GHOST_Event(getSystem()->getMilliSeconds(), type, window);
526 }
527
528
529 LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
530 {
531         GHOST_Event* event = 0;
532         LRESULT lResult;
533         GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem());
534         GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized")
535
536         if (hwnd) {
537                 GHOST_WindowWin32* window = (GHOST_WindowWin32*)::GetWindowLong(hwnd, GWL_USERDATA);
538                 if (window) {
539                         switch (msg) {
540                                 ////////////////////////////////////////////////////////////////////////
541                                 // Keyboard events, processed
542                                 ////////////////////////////////////////////////////////////////////////
543                                 case WM_KEYDOWN:
544                                         /* The WM_KEYDOWN message is posted to the window with the keyboard focus when a 
545                                          * nonsystem key is pressed. A nonsystem key is a key that is pressed when the alt
546                                          * key is not pressed. 
547                                          */
548                                 case WM_SYSKEYDOWN:
549                                         /* The WM_SYSKEYDOWN message is posted to the window with the keyboard focus when 
550                                          * the user presses the F10 key (which activates the menu bar) or holds down the 
551                                          * alt key and then presses another key. It also occurs when no window currently 
552                                          * has the keyboard focus; in this case, the WM_SYSKEYDOWN message is sent to the 
553                                          * active window. The window that receives the message can distinguish between these 
554                                          * two contexts by checking the context code in the lKeyData parameter. 
555                                          */
556                                         switch (wParam) {
557                                                 case VK_SHIFT:
558                                                 case VK_CONTROL:
559                                                 case VK_MENU:
560                                                         if (!system->m_seperateLeftRightInitialized) {
561                                                                 // Check whether this system supports seperate left and right keys
562                                                                 switch (wParam) {
563                                                                         case VK_SHIFT:
564                                                                                 system->m_seperateLeftRight = 
565                                                                                         (HIBYTE(::GetKeyState(VK_LSHIFT)) != 0) ||
566                                                                                         (HIBYTE(::GetKeyState(VK_RSHIFT)) != 0) ?
567                                                                                         true : false;
568                                                                                 break;
569                                                                         case VK_CONTROL:
570                                                                                 system->m_seperateLeftRight = 
571                                                                                         (HIBYTE(::GetKeyState(VK_LCONTROL)) != 0) ||
572                                                                                         (HIBYTE(::GetKeyState(VK_RCONTROL)) != 0) ?
573                                                                                         true : false;
574                                                                                 break;
575                                                                         case VK_MENU:
576                                                                                 system->m_seperateLeftRight = 
577                                                                                         (HIBYTE(::GetKeyState(VK_LMENU)) != 0) ||
578                                                                                         (HIBYTE(::GetKeyState(VK_RMENU)) != 0) ?
579                                                                                         true : false;
580                                                                                 break;
581                                                                 }
582                                                                 system->m_seperateLeftRightInitialized = true;
583                                                         }
584                                                         system->processModifierKeys(window);
585                                                         // Bypass call to DefWindowProc
586                                                         return 0;
587                                                 default:
588                                                         event = processKeyEvent(window, true, wParam, lParam);
589                                                         if (!event) {
590                                                                 GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
591                                                                 GHOST_PRINT(msg)
592                                                                 GHOST_PRINT(" key ignored\n")
593                                                         }
594                                                         break;
595                                                 }
596                                         break;
597
598                                 case WM_KEYUP:
599                                 case WM_SYSKEYUP:
600                                         switch (wParam) {
601                                                 case VK_SHIFT:
602                                                 case VK_CONTROL:
603                                                 case VK_MENU:
604                                                         system->processModifierKeys(window);
605                                                         // Bypass call to DefWindowProc
606                                                         return 0;
607                                                 default:
608                                                         event = processKeyEvent(window, false, wParam, lParam);
609                                                         if (!event) {
610                                                                 GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
611                                                                 GHOST_PRINT(msg)
612                                                                 GHOST_PRINT(" key ignored\n")
613                                                         }
614                                                         break;
615                                         }
616                                         break;
617
618                                 ////////////////////////////////////////////////////////////////////////
619                                 // Keyboard events, ignored
620                                 ////////////////////////////////////////////////////////////////////////
621                                 case WM_CHAR:
622                                         /* The WM_CHAR message is posted to the window with the keyboard focus when 
623                                          * a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR 
624                                          * contains the character code of the key that was pressed. 
625                                          */
626                                 case WM_DEADCHAR:
627                                         /* The WM_DEADCHAR message is posted to the window with the keyboard focus when a
628                                          * WM_KEYUP message is translated by the TranslateMessage function. WM_DEADCHAR 
629                                          * specifies a character code generated by a dead key. A dead key is a key that 
630                                          * generates a character, such as the umlaut (double-dot), that is combined with 
631                                          * another character to form a composite character. For example, the umlaut-O 
632                                          * character (Ù) is generated by typing the dead key for the umlaut character, and 
633                                          * then typing the O key.
634                                          */
635                                 case WM_SYSDEADCHAR:
636                                         /* The WM_SYSDEADCHAR message is sent to the window with the keyboard focus when 
637                                          * a WM_SYSKEYDOWN message is translated by the TranslateMessage function. 
638                                          * WM_SYSDEADCHAR specifies the character code of a system dead key - that is, 
639                                          * a dead key that is pressed while holding down the alt key. 
640                                          */
641                                         break;
642                                 ////////////////////////////////////////////////////////////////////////
643                                 // Tablet events, processed
644                                 ////////////////////////////////////////////////////////////////////////
645                                 case WT_PACKET:
646                                         ((GHOST_WindowWin32*)window)->processWin32TabletEvent(wParam, lParam);
647                                         break;
648                                 case WT_CSRCHANGE:
649                                 case WT_PROXIMITY:
650                                         ((GHOST_WindowWin32*)window)->processWin32TabletInitEvent();
651                                         break;
652                                 ////////////////////////////////////////////////////////////////////////
653                                 // Mouse events, processed
654                                 ////////////////////////////////////////////////////////////////////////
655                                 case WM_LBUTTONDOWN:
656                                         window->registerMouseClickEvent(true);
657                                         event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskLeft);
658                                         break;
659                                 case WM_MBUTTONDOWN:
660                                         window->registerMouseClickEvent(true);
661                                         event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskMiddle);
662                                         break;
663                                 case WM_RBUTTONDOWN:
664                                         window->registerMouseClickEvent(true);
665                                         event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskRight);
666                                         break;
667                                 case WM_LBUTTONUP:
668                                         window->registerMouseClickEvent(false);
669                                         event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft);
670                                         break;
671                                 case WM_MBUTTONUP:
672                                         window->registerMouseClickEvent(false);
673                                         event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskMiddle);
674                                         break;
675                                 case WM_RBUTTONUP:
676                                         window->registerMouseClickEvent(false);
677                                         event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskRight);
678                                         break;
679                                 case WM_MOUSEMOVE:
680                                         event = processCursorEvent(GHOST_kEventCursorMove, window);
681                                         break;
682                                 case WM_MOUSEWHEEL:
683                                         /* The WM_MOUSEWHEEL message is sent to the focus window 
684                                          * when the mouse wheel is rotated. The DefWindowProc 
685                                          * function propagates the message to the window's parent.
686                                          * There should be no internal forwarding of the message, 
687                                          * since DefWindowProc propagates it up the parent chain 
688                                          * until it finds a window that processes it.
689                                          */
690                                         event = processWheelEvent(window, wParam, lParam);
691                                         break;
692                                 case WM_SETCURSOR:
693                                         /* The WM_SETCURSOR message is sent to a window if the mouse causes the cursor
694                                          * to move within a window and mouse input is not captured.
695                                          * This means we have to set the cursor shape every time the mouse moves!
696                                          * The DefWindowProc function uses this message to set the cursor to an 
697                                          * arrow if it is not in the client area.
698                                          */
699                                         if (LOWORD(lParam) == HTCLIENT) {
700                                                 // Load the current cursor
701                                                 window->loadCursor(window->getCursorVisibility(), window->getCursorShape());
702                                                 // Bypass call to DefWindowProc
703                                                 return 0;
704                                         } 
705                                         else {
706                                                 // Outside of client area show standard cursor
707                                                 window->loadCursor(true, GHOST_kStandardCursorDefault);
708                                         }
709                                         break;
710
711                                 ////////////////////////////////////////////////////////////////////////
712                                 // Mouse events, ignored
713                                 ////////////////////////////////////////////////////////////////////////
714                                 case WM_NCMOUSEMOVE:
715                                         /* The WM_NCMOUSEMOVE message is posted to a window when the cursor is moved 
716                                          * within the nonclient area of the window. This message is posted to the window 
717                                          * that contains the cursor. If a window has captured the mouse, this message is not posted.
718                                          */
719                                 case WM_NCHITTEST:
720                                         /* The WM_NCHITTEST message is sent to a window when the cursor moves, or 
721                                          * when a mouse button is pressed or released. If the mouse is not captured, 
722                                          * the message is sent to the window beneath the cursor. Otherwise, the message 
723                                          * is sent to the window that has captured the mouse. 
724                                          */
725                                         break;
726
727                                 ////////////////////////////////////////////////////////////////////////
728                                 // Window events, processed
729                                 ////////////////////////////////////////////////////////////////////////
730                                 case WM_CLOSE:
731                                         /* The WM_CLOSE message is sent as a signal that a window or an application should terminate. */
732                                         event = processWindowEvent(GHOST_kEventWindowClose, window);
733                                         break;
734                                 case WM_ACTIVATE:
735                                         /* The WM_ACTIVATE message is sent to both the window being activated and the window being 
736                                          * deactivated. If the windows use the same input queue, the message is sent synchronously, 
737                                          * first to the window procedure of the top-level window being deactivated, then to the window
738                                          * procedure of the top-level window being activated. If the windows use different input queues,
739                                          * the message is sent asynchronously, so the window is activated immediately. 
740                                          */
741                                         event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window);
742                                         break;
743                                 case WM_PAINT:
744                                         /* An application sends the WM_PAINT message when the system or another application 
745                                          * makes a request to paint a portion of an application's window. The message is sent
746                                          * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage 
747                                          * function when the application obtains a WM_PAINT message by using the GetMessage or 
748                                          * PeekMessage function. 
749                                          */
750                                         event = processWindowEvent(GHOST_kEventWindowUpdate, window);
751                                         ::ValidateRect(hwnd, NULL);
752                                         break;
753                                 case WM_SIZE:
754                                         /* The WM_SIZE message is sent to a window after its size has changed.
755                                          * The WM_SIZE and WM_MOVE messages are not sent if an application handles the 
756                                          * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
757                                          * to perform any move or size change processing during the WM_WINDOWPOSCHANGED 
758                                          * message without calling DefWindowProc.
759                                          */
760                                         event = processWindowEvent(GHOST_kEventWindowSize, window);
761                                 case WM_CAPTURECHANGED:
762                                         window->lostMouseCapture();
763                                         break;
764
765                                 ////////////////////////////////////////////////////////////////////////
766                                 // Window events, ignored
767                                 ////////////////////////////////////////////////////////////////////////
768                                 case WM_WINDOWPOSCHANGED:
769                                         /* The WM_WINDOWPOSCHANGED message is sent to a window whose size, position, or place
770                                          * in the Z order has changed as a result of a call to the SetWindowPos function or 
771                                          * another window-management function.
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_MOVE:
778                                         /* The WM_SIZE and WM_MOVE messages are not sent if an application handles the 
779                                          * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
780                                          * to perform any move or size change processing during the WM_WINDOWPOSCHANGED 
781                                          * message without calling DefWindowProc. 
782                                          */
783                                 case WM_ERASEBKGND:
784                                         /* An application sends the WM_ERASEBKGND message when the window background must be 
785                                          * erased (for example, when a window is resized). The message is sent to prepare an 
786                                          * invalidated portion of a window for painting. 
787                                          */
788                                 case WM_NCPAINT:
789                                         /* An application sends the WM_NCPAINT message to a window when its frame must be painted. */
790                                 case WM_NCACTIVATE:
791                                         /* The WM_NCACTIVATE message is sent to a window when its nonclient area needs to be changed 
792                                          * to indicate an active or inactive state. 
793                                          */
794                                 case WM_DESTROY:
795                                         /* The WM_DESTROY message is sent when a window is being destroyed. It is sent to the window 
796                                          * procedure of the window being destroyed after the window is removed from the screen. 
797                                          * This message is sent first to the window being destroyed and then to the child windows 
798                                          * (if any) as they are destroyed. During the processing of the message, it can be assumed 
799                                          * that all child windows still exist. 
800                                          */
801                                 case WM_NCDESTROY:
802                                         /* The WM_NCDESTROY message informs a window that its nonclient area is being destroyed. The 
803                                          * DestroyWindow function sends the WM_NCDESTROY message to the window following the WM_DESTROY
804                                          * message. WM_DESTROY is used to free the allocated memory object associated with the window. 
805                                          */
806                                 case WM_KILLFOCUS:
807                                         /* The WM_KILLFOCUS message is sent to a window immediately before it loses the keyboard focus. */
808                                 case WM_SHOWWINDOW:
809                                         /* The WM_SHOWWINDOW message is sent to a window when the window is about to be hidden or shown. */
810                                 case WM_WINDOWPOSCHANGING:
811                                         /* The WM_WINDOWPOSCHANGING message is sent to a window whose size, position, or place in 
812                                          * the Z order is about to change as a result of a call to the SetWindowPos function or 
813                                          * another window-management function. 
814                                          */
815                                 case WM_SETFOCUS:
816                                         /* The WM_SETFOCUS message is sent to a window after it has gained the keyboard focus. */
817                                 case WM_MOVING:
818                                         /* The WM_MOVING message is sent to a window that the user is moving. By processing 
819                                          * this message, an application can monitor the size and position of the drag rectangle
820                                          * and, if needed, change its size or position.
821                                          */
822                                 case WM_ENTERSIZEMOVE:
823                                         /* The WM_ENTERSIZEMOVE message is sent one time to a window after it enters the moving 
824                                          * or sizing modal loop. The window enters the moving or sizing modal loop when the user 
825                                          * clicks the window's title bar or sizing border, or when the window passes the 
826                                          * WM_SYSCOMMAND message to the DefWindowProc function and the wParam parameter of the 
827                                          * message specifies the SC_MOVE or SC_SIZE value. The operation is complete when 
828                                          * DefWindowProc returns. 
829                                          */
830                                         break;
831                                         
832                                 ////////////////////////////////////////////////////////////////////////
833                                 // Other events
834                                 ////////////////////////////////////////////////////////////////////////
835                                 case WM_GETTEXT:
836                                         /* An application sends a WM_GETTEXT message to copy the text that 
837                                          * corresponds to a window into a buffer provided by the caller. 
838                                          */
839                                 case WM_ACTIVATEAPP:
840                                         /* The WM_ACTIVATEAPP message is sent when a window belonging to a 
841                                          * different application than the active window is about to be activated.
842                                          * The message is sent to the application whose window is being activated
843                                          * and to the application whose window is being deactivated. 
844                                          */
845                                 case WM_TIMER:
846                                         /* The WIN32 docs say:
847                                          * The WM_TIMER message is posted to the installing thread's message queue
848                                          * when a timer expires. You can process the message by providing a WM_TIMER
849                                          * case in the window procedure. Otherwise, the default window procedure will
850                                          * call the TimerProc callback function specified in the call to the SetTimer
851                                          * function used to install the timer. 
852                                          *
853                                          * In GHOST, we let DefWindowProc call the timer callback.
854                                          */
855                                         break;
856                                 case WM_BLND_NDOF_AXIS:
857                                         {
858                                                 GHOST_TEventNDOFData ndofdata;
859                                                 system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata);
860                                                 system->m_eventManager->
861                                                         pushEvent(new GHOST_EventNDOF(
862                                                                 system->getMilliSeconds(), 
863                                                                 GHOST_kEventNDOFMotion, 
864                                                                 window, ndofdata));
865                                         }
866                                         break;
867                                 case WM_BLND_NDOF_BTN:
868                                         {
869                                                 GHOST_TEventNDOFData ndofdata;
870                                                 system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata);
871                                                 system->m_eventManager->
872                                                         pushEvent(new GHOST_EventNDOF(
873                                                                 system->getMilliSeconds(), 
874                                                                 GHOST_kEventNDOFButton, 
875                                                                 window, ndofdata));
876                                         }
877                                         break;
878                         }
879                 }
880                 else {
881                         // Event found for a window before the pointer to the class has been set.
882                         GHOST_PRINT("GHOST_SystemWin32::wndProc: GHOST window event before creation\n")
883                         /* These are events we typically miss at this point:
884                            WM_GETMINMAXINFO     0x24
885                            WM_NCCREATE                  0x81
886                            WM_NCCALCSIZE                0x83
887                            WM_CREATE                    0x01
888                            We let DefWindowProc do the work.
889                         */
890                 }
891         }
892         else {
893                 // Events without valid hwnd
894                 GHOST_PRINT("GHOST_SystemWin32::wndProc: event without window\n")
895         }
896
897         if (event) {
898                 system->pushEvent(event);
899                 lResult = 0;
900         }
901         else {
902                 lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
903         }
904         return lResult;
905 }
906
907 GHOST_TUns8* GHOST_SystemWin32::getClipboard(int flag) const 
908 {
909         char *buffer;
910         char *temp_buff;
911         
912         if ( OpenClipboard(NULL) ) {
913                 HANDLE hData = GetClipboardData( CF_TEXT );
914                 buffer = (char*)GlobalLock( hData );
915                 
916                 temp_buff = (char*) malloc(strlen(buffer)+1);
917                 strcpy(temp_buff, buffer);
918                 
919                 GlobalUnlock( hData );
920                 CloseClipboard();
921                 
922                 temp_buff[strlen(buffer)] = '\0';
923                 if (buffer) {
924                         return (GHOST_TUns8*)temp_buff;
925                 } else {
926                         return NULL;
927                 }
928         } else {
929                 return NULL;
930         }
931 }
932
933 void GHOST_SystemWin32::putClipboard(GHOST_TInt8 *buffer, int flag) const
934 {
935         if(flag == 1) {return;} //If Flag is 1 means the selection and is used on X11
936         if (OpenClipboard(NULL)) {
937                 HLOCAL clipbuffer;
938                 char *data;
939                 
940                 if (buffer) {
941                         EmptyClipboard();
942                         
943                         clipbuffer = LocalAlloc(LMEM_FIXED,((strlen(buffer)+1)));
944                         data = (char*)GlobalLock(clipbuffer);
945
946                         strcpy(data, (char*)buffer);
947                         data[strlen(buffer)] = '\0';
948                         LocalUnlock(clipbuffer);
949                         SetClipboardData(CF_TEXT,clipbuffer);
950                 }
951                 CloseClipboard();
952         } else {
953                 return;
954         }
955 }
956