Hides console on win32 even if python path is 2 or more lines
[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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 /** \file ghost/intern/GHOST_SystemWin32.cpp
30  *  \ingroup GHOST
31  */
32
33
34 /**
35
36  * $Id$
37  * Copyright (C) 2001 NaN Technologies B.V.
38  * @author      Maarten Gribnau
39  * @date        May 7, 2001
40  */
41
42 #include <iostream>
43
44 #ifdef FREE_WINDOWS
45 #  define WINVER 0x0501 /* GetConsoleWindow() for MinGW */
46 #endif
47
48 #include "GHOST_SystemWin32.h"
49 #include "GHOST_EventDragnDrop.h"
50
51 #define WIN32_LEAN_AND_MEAN
52 #ifdef _WIN32_IE
53 #undef _WIN32_IE
54 #endif
55 #define _WIN32_IE 0x0501
56 #include <windows.h>
57 #include <shlobj.h>
58 #include <tlhelp32.h>
59
60 // win64 doesn't define GWL_USERDATA
61 #ifdef WIN32
62 #ifndef GWL_USERDATA
63 #define GWL_USERDATA GWLP_USERDATA
64 #define GWL_WNDPROC GWLP_WNDPROC 
65 #endif
66 #endif
67
68 /*
69  * According to the docs the mouse wheel message is supported from windows 98 
70  * upwards. Leaving WINVER at default value, the WM_MOUSEWHEEL message and the 
71  * wheel detent value are undefined.
72  */
73 #ifndef WM_MOUSEWHEEL
74 #define WM_MOUSEWHEEL 0x020A
75 #endif // WM_MOUSEWHEEL
76 #ifndef WHEEL_DELTA
77 #define WHEEL_DELTA 120 /* Value for rolling one detent, (old convention! MS changed it) */
78 #endif // WHEEL_DELTA
79
80 /* 
81  * Defines for mouse buttons 4 and 5 aka xbutton1 and xbutton2.
82  * MSDN: Declared in Winuser.h, include Windows.h 
83  * This does not seem to work with MinGW so we define our own here.
84  */
85 #ifndef XBUTTON1
86 #define XBUTTON1 0x0001
87 #endif // XBUTTON1
88 #ifndef XBUTTON2
89 #define XBUTTON2 0x0002
90 #endif // XBUTTON2
91 #ifndef WM_XBUTTONUP
92 #define WM_XBUTTONUP 524
93 #endif // WM_XBUTTONUP
94 #ifndef WM_XBUTTONDOWN
95 #define WM_XBUTTONDOWN 523
96 #endif // WM_XBUTTONDOWN
97
98 #include "GHOST_Debug.h"
99 #include "GHOST_DisplayManagerWin32.h"
100 #include "GHOST_EventButton.h"
101 #include "GHOST_EventCursor.h"
102 #include "GHOST_EventKey.h"
103 #include "GHOST_EventWheel.h"
104 #include "GHOST_EventNDOF.h"
105 #include "GHOST_TimerTask.h"
106 #include "GHOST_TimerManager.h"
107 #include "GHOST_WindowManager.h"
108 #include "GHOST_WindowWin32.h"
109 #include "GHOST_NDOFManager.h"
110
111 // Key code values not found in winuser.h
112 #ifndef VK_MINUS
113 #define VK_MINUS 0xBD
114 #endif // VK_MINUS
115 #ifndef VK_SEMICOLON
116 #define VK_SEMICOLON 0xBA
117 #endif // VK_SEMICOLON
118 #ifndef VK_PERIOD
119 #define VK_PERIOD 0xBE
120 #endif // VK_PERIOD
121 #ifndef VK_COMMA
122 #define VK_COMMA 0xBC
123 #endif // VK_COMMA
124 #ifndef VK_QUOTE
125 #define VK_QUOTE 0xDE
126 #endif // VK_QUOTE
127 #ifndef VK_BACK_QUOTE
128 #define VK_BACK_QUOTE 0xC0
129 #endif // VK_BACK_QUOTE
130 #ifndef VK_SLASH
131 #define VK_SLASH 0xBF
132 #endif // VK_SLASH
133 #ifndef VK_BACK_SLASH
134 #define VK_BACK_SLASH 0xDC
135 #endif // VK_BACK_SLASH
136 #ifndef VK_EQUALS
137 #define VK_EQUALS 0xBB
138 #endif // VK_EQUALS
139 #ifndef VK_OPEN_BRACKET
140 #define VK_OPEN_BRACKET 0xDB
141 #endif // VK_OPEN_BRACKET
142 #ifndef VK_CLOSE_BRACKET
143 #define VK_CLOSE_BRACKET 0xDD
144 #endif // VK_CLOSE_BRACKET
145 #ifndef VK_GR_LESS
146 #define VK_GR_LESS 0xE2
147 #endif // VK_GR_LESS
148
149 #ifndef VK_MEDIA_NEXT_TRACK
150 #define VK_MEDIA_NEXT_TRACK     0xB0
151 #endif // VK_MEDIA_NEXT_TRACK
152 #ifndef VK_MEDIA_PREV_TRACK
153 #define VK_MEDIA_PREV_TRACK     0xB1
154 #endif // VK_MEDIA_PREV_TRACK
155 #ifndef VK_MEDIA_STOP
156 #define VK_MEDIA_STOP   0xB2
157 #endif // VK_MEDIA_STOP
158 #ifndef VK_MEDIA_PLAY_PAUSE
159 #define VK_MEDIA_PLAY_PAUSE     0xB3
160 #endif // VK_MEDIA_PLAY_PAUSE
161
162 /*
163         Initiates WM_INPUT messages from keyboard
164         That way GHOST can retrieve true keys
165 */
166 GHOST_TInt32 GHOST_SystemWin32::initKeyboardRawInput(void)
167 {
168         RAWINPUTDEVICE device = {0};
169         device.usUsagePage      = 0x01; /* usUsagePage & usUsage for keyboard*/
170         device.usUsage          = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */
171
172         return RegisterRawInputDevices(&device, 1, sizeof(device));
173 };
174
175 GHOST_SystemWin32::GHOST_SystemWin32()
176 : m_hasPerformanceCounter(false), m_freq(0), m_start(0)
177 {
178         m_displayManager = new GHOST_DisplayManagerWin32 ();
179         GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n");
180         m_displayManager->initialize();
181
182         m_consoleStatus = 1;
183
184         // Check if current keyboard layout uses AltGr and save keylayout ID for
185         // specialized handling if keys like VK_OEM_*. I.e. french keylayout
186         // generates VK_OEM_8 for their exclamation key (key left of right shift)
187         this->handleKeyboardChange();
188         // Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32.
189         OleInitialize(0);
190 }
191
192 GHOST_SystemWin32::~GHOST_SystemWin32()
193 {
194         // Shutdown COM
195         OleUninitialize();
196         toggleConsole(1);
197 }
198
199
200 GHOST_TUns64 GHOST_SystemWin32::getMilliSeconds() const
201 {
202         // Hardware does not support high resolution timers. We will use GetTickCount instead then.
203         if (!m_hasPerformanceCounter) {
204                 return ::GetTickCount();
205         }
206
207         // Retrieve current count
208         __int64 count = 0;
209         ::QueryPerformanceCounter((LARGE_INTEGER*)&count);
210
211         // Calculate the time passed since system initialization.
212         __int64 delta = 1000*(count-m_start);
213
214         GHOST_TUns64 t = (GHOST_TUns64)(delta/m_freq);
215         return t; 
216 }
217
218
219 GHOST_TUns8 GHOST_SystemWin32::getNumDisplays() const
220 {
221         GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::getNumDisplays(): m_displayManager==0\n");
222         GHOST_TUns8 numDisplays;
223         m_displayManager->getNumDisplays(numDisplays);
224         return numDisplays;
225 }
226
227
228 void GHOST_SystemWin32::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const
229 {
230         width = ::GetSystemMetrics(SM_CXSCREEN);
231         height= ::GetSystemMetrics(SM_CYSCREEN);
232 }
233
234
235 GHOST_IWindow* GHOST_SystemWin32::createWindow(
236         const STR_String& title, 
237         GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height,
238         GHOST_TWindowState state, GHOST_TDrawingContextType type,
239         bool stereoVisual, const GHOST_TUns16 numOfAASamples, const GHOST_TEmbedderWindowID parentWindow )
240 {
241         GHOST_Window* window = 0;
242         window = new GHOST_WindowWin32 (this, title, left, top, width, height, state, type, stereoVisual, numOfAASamples, parentWindow);
243         if (window) {
244                 if (window->getValid()) {
245                         // Store the pointer to the window
246 //                      if (state != GHOST_kWindowStateFullScreen) {
247                                 m_windowManager->addWindow(window);
248 //                      }
249                 }
250                 else {
251
252                         // Invalid parent window hwnd
253                         if (((GHOST_WindowWin32*)window)->getNextWindow() == NULL) {
254                                 delete window;
255                                 window = 0;
256                                 return window;
257                         }
258
259                         // An invalid window could be one that was used to test for AA
260                         window = ((GHOST_WindowWin32*)window)->getNextWindow();
261                         
262                         // If another window is found, let the wm know about that one, but not the old one
263                         if (window->getValid()) {
264                                 m_windowManager->addWindow(window);
265                         }
266                         else {
267                                 delete window;
268                                 window = 0;
269                         }
270
271                 }
272         }
273         return window;
274 }
275
276
277 bool GHOST_SystemWin32::processEvents(bool waitForEvent)
278 {
279         MSG msg;
280         bool anyProcessed = false;
281
282         do {
283                 GHOST_TimerManager* timerMgr = getTimerManager();
284
285                 if (waitForEvent && !::PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE)) {
286 #if 1
287                         ::Sleep(1);
288 #else
289                         GHOST_TUns64 next = timerMgr->nextFireTime();
290                         GHOST_TInt64 maxSleep = next - getMilliSeconds();
291                         
292                         if (next == GHOST_kFireTimeNever) {
293                                 ::WaitMessage();
294                         } else if(maxSleep >= 0.0) {
295                                 ::SetTimer(NULL, 0, maxSleep, NULL);
296                                 ::WaitMessage();
297                                 ::KillTimer(NULL, 0);
298                         }
299 #endif
300                 }
301
302                 if (timerMgr->fireTimers(getMilliSeconds())) {
303                         anyProcessed = true;
304                 }
305
306                 // Process all the events waiting for us
307                 while (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE) != 0) {
308                         ::DispatchMessage(&msg);
309                         anyProcessed = true;
310                 }
311         } while (waitForEvent && !anyProcessed);
312
313         return anyProcessed;
314 }
315
316
317 GHOST_TSuccess GHOST_SystemWin32::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const
318 {
319         POINT point;
320         if(::GetCursorPos(&point)){
321                 x = point.x;
322                 y = point.y;
323                 return GHOST_kSuccess;
324         }
325         return GHOST_kFailure;
326 }
327
328
329 GHOST_TSuccess GHOST_SystemWin32::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y)
330 {
331         if (!GetActiveWindow())
332                 return GHOST_kFailure;
333         return ::SetCursorPos(x, y) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
334 }
335
336
337 GHOST_TSuccess GHOST_SystemWin32::getModifierKeys(GHOST_ModifierKeys& keys) const
338 {
339         bool down = HIBYTE(::GetKeyState(VK_LSHIFT)) != 0;
340         keys.set(GHOST_kModifierKeyLeftShift, down);
341         down = HIBYTE(::GetKeyState(VK_RSHIFT)) != 0;
342         keys.set(GHOST_kModifierKeyRightShift, down);
343         
344         down = HIBYTE(::GetKeyState(VK_LMENU)) != 0;
345         keys.set(GHOST_kModifierKeyLeftAlt, down);
346         down = HIBYTE(::GetKeyState(VK_RMENU)) != 0;
347         keys.set(GHOST_kModifierKeyRightAlt, down);
348         
349         down = HIBYTE(::GetKeyState(VK_LCONTROL)) != 0;
350         keys.set(GHOST_kModifierKeyLeftControl, down);
351         down = HIBYTE(::GetKeyState(VK_RCONTROL)) != 0;
352         keys.set(GHOST_kModifierKeyRightControl, down);
353         
354         bool lwindown = HIBYTE(::GetKeyState(VK_LWIN)) != 0;
355         bool rwindown = HIBYTE(::GetKeyState(VK_RWIN)) != 0;
356         if(lwindown || rwindown)
357                 keys.set(GHOST_kModifierKeyOS, true);
358         else
359                 keys.set(GHOST_kModifierKeyOS, false);
360         return GHOST_kSuccess;
361 }
362
363
364 GHOST_TSuccess GHOST_SystemWin32::getButtons(GHOST_Buttons& buttons) const
365 {
366         /* Check for swapped buttons (left-handed mouse buttons)
367          * GetAsyncKeyState() will give back the state of the physical mouse buttons.
368          */
369         bool swapped = ::GetSystemMetrics(SM_SWAPBUTTON) == TRUE;
370
371         bool down = HIBYTE(::GetKeyState(VK_LBUTTON)) != 0;
372         buttons.set(swapped ? GHOST_kButtonMaskRight : GHOST_kButtonMaskLeft, down);
373
374         down = HIBYTE(::GetKeyState(VK_MBUTTON)) != 0;
375         buttons.set(GHOST_kButtonMaskMiddle, down);
376
377         down = HIBYTE(::GetKeyState(VK_RBUTTON)) != 0;
378         buttons.set(swapped ? GHOST_kButtonMaskLeft : GHOST_kButtonMaskRight, down);
379         return GHOST_kSuccess;
380 }
381
382
383 GHOST_TSuccess GHOST_SystemWin32::init()
384 {
385         GHOST_TSuccess success = GHOST_System::init();
386         
387         /* Disable scaling on high DPI displays on Vista */
388         user32 = ::LoadLibraryA("user32.dll");
389         typedef BOOL (WINAPI * LPFNSETPROCESSDPIAWARE)();
390         LPFNSETPROCESSDPIAWARE SetProcessDPIAware =
391                 (LPFNSETPROCESSDPIAWARE)GetProcAddress(user32, "SetProcessDPIAware");
392         if (SetProcessDPIAware)
393                 SetProcessDPIAware();
394         #ifdef NEED_RAW_PROC
395                 pRegisterRawInputDevices = (LPFNDLLRRID)GetProcAddress(user32, "RegisterRawInputDevices");
396                 pGetRawInputData = (LPFNDLLGRID)GetProcAddress(user32, "GetRawInputData");
397         #else
398                 FreeLibrary(user32);
399         #endif
400
401         /*      Initiates WM_INPUT messages from keyboard */
402         initKeyboardRawInput();
403
404
405         // Determine whether this system has a high frequency performance counter. */
406         m_hasPerformanceCounter = ::QueryPerformanceFrequency((LARGE_INTEGER*)&m_freq) == TRUE;
407         if (m_hasPerformanceCounter) {
408                 GHOST_PRINT("GHOST_SystemWin32::init: High Frequency Performance Timer available\n")
409                 ::QueryPerformanceCounter((LARGE_INTEGER*)&m_start);
410         }
411         else {
412                 GHOST_PRINT("GHOST_SystemWin32::init: High Frequency Performance Timer not available\n")
413         }
414
415         if (success) {
416                 WNDCLASS wc;
417                 wc.style= CS_HREDRAW | CS_VREDRAW;
418                 wc.lpfnWndProc= s_wndProc;
419                 wc.cbClsExtra= 0;
420                 wc.cbWndExtra= 0;
421                 wc.hInstance= ::GetModuleHandle(0);
422                 wc.hIcon = ::LoadIcon(wc.hInstance, "APPICON");
423                 
424                 if (!wc.hIcon) {
425                         ::LoadIcon(NULL, IDI_APPLICATION);
426                 }
427                 wc.hCursor = ::LoadCursor(0, IDC_ARROW);
428                 wc.hbrBackground= (HBRUSH)::GetStockObject(BLACK_BRUSH);
429                 wc.lpszMenuName = 0;
430                 wc.lpszClassName= GHOST_WindowWin32::getWindowClassName();
431
432                 // Use RegisterClassEx for setting small icon
433                 if (::RegisterClass(&wc) == 0) {
434                         success = GHOST_kFailure;
435                 }
436         }
437         
438         return success;
439 }
440
441
442 GHOST_TSuccess GHOST_SystemWin32::exit()
443 {
444         #ifdef NEED_RAW_PROC
445         FreeLibrary(user32);
446         #endif
447
448         return GHOST_System::exit();
449 }
450
451 GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam, int * keyDown, char * vk)
452 {
453         unsigned int size = 0;
454         char * data;
455         GHOST_TKey key = GHOST_kKeyUnknown;
456
457
458         if(!keyDown)
459                 return GHOST_kKeyUnknown;
460
461         GetRawInputData((HRAWINPUT)lParam, RID_INPUT, 0, &size, sizeof(RAWINPUTHEADER));
462
463
464         if((data = (char*)malloc(size)) &&
465                 GetRawInputData((HRAWINPUT)lParam, RID_INPUT, data, &size, sizeof(RAWINPUTHEADER)))
466         {
467                 RAWINPUT ri;
468                 memcpy(&ri,data,(size < sizeof(ri)) ? size : sizeof(ri));
469
470                 if (ri.header.dwType == RIM_TYPEKEYBOARD)
471                 {
472                         GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
473                         
474                         GHOST_ModifierKeys modifiers;
475                         system->retrieveModifierKeys(modifiers);
476                         
477                         *keyDown = !(ri.data.keyboard.Flags & RI_KEY_BREAK);
478                         key = this->convertKey(window, ri.data.keyboard.VKey, ri.data.keyboard.MakeCode, (ri.data.keyboard.Flags&(RI_KEY_E1|RI_KEY_E0)));
479                         
480                         // extra handling of modifier keys: don't send repeats out from GHOST
481                         if(key >= GHOST_kKeyLeftShift && key <= GHOST_kKeyRightAlt)
482                         {
483                                 bool changed = false;
484                                 GHOST_TModifierKeyMask modifier;
485                                 switch(key) {
486                                         case GHOST_kKeyLeftShift:
487                                                 {
488                                                         changed = (modifiers.get(GHOST_kModifierKeyLeftShift) != (bool)*keyDown);
489                                                         modifier = GHOST_kModifierKeyLeftShift;
490                                                 }
491                                                 break;
492                                         case GHOST_kKeyRightShift:
493                                                 {
494                                                         changed = (modifiers.get(GHOST_kModifierKeyRightShift) != (bool)*keyDown);
495                                                         modifier = GHOST_kModifierKeyRightShift;
496                                                 }
497                                                 break;
498                                         case GHOST_kKeyLeftControl:
499                                                 {
500                                                         changed = (modifiers.get(GHOST_kModifierKeyLeftControl) != (bool)*keyDown);
501                                                         modifier = GHOST_kModifierKeyLeftControl;
502                                                 }
503                                                 break;
504                                         case GHOST_kKeyRightControl:
505                                                 {
506                                                         changed = (modifiers.get(GHOST_kModifierKeyRightControl) != (bool)*keyDown);
507                                                         modifier = GHOST_kModifierKeyRightControl;
508                                                 }
509                                                 break;
510                                         case GHOST_kKeyLeftAlt:
511                                                 {
512                                                         changed = (modifiers.get(GHOST_kModifierKeyLeftAlt) != (bool)*keyDown);
513                                                         modifier = GHOST_kModifierKeyLeftAlt;
514                                                 }
515                                                 break;
516                                         case GHOST_kKeyRightAlt:
517                                                 {
518                                                         changed = (modifiers.get(GHOST_kModifierKeyRightAlt) != (bool)*keyDown);
519                                                         modifier = GHOST_kModifierKeyRightAlt;
520                                                 }
521                                                 break;
522                                         default: break;
523                                 }
524                                 
525                                 if(changed)
526                                 {
527                                         modifiers.set(modifier, (bool)*keyDown);
528                                         system->storeModifierKeys(modifiers);
529                                 }
530                                 else
531                                 {
532                                         key = GHOST_kKeyUnknown;
533                                 }
534                         }
535                         
536         
537                         if(vk) *vk = ri.data.keyboard.VKey;
538                 };
539
540         };
541         free(data);
542
543         return key;
544 }
545
546 //! note: this function can be extended to include other exotic cases as they arise.
547 // This function was added in response to bug [#25715]
548 GHOST_TKey GHOST_SystemWin32::processSpecialKey(GHOST_IWindow *window, short vKey, short scanCode) const
549 {
550         GHOST_TKey key = GHOST_kKeyUnknown;
551         switch(PRIMARYLANGID(m_langId)) {
552                 case LANG_FRENCH:
553                         if(vKey==VK_OEM_8) key = GHOST_kKeyF13; // oem key; used purely for shortcuts .
554                         break;
555         }
556
557         return key;
558 }
559
560 GHOST_TKey GHOST_SystemWin32::convertKey(GHOST_IWindow *window, short vKey, short scanCode, short extend) const
561 {
562         GHOST_TKey key;
563
564         if ((vKey >= '0') && (vKey <= '9')) {
565                 // VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39)
566                 key = (GHOST_TKey)(vKey - '0' + GHOST_kKey0);
567         }
568         else if ((vKey >= 'A') && (vKey <= 'Z')) {
569                 // VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A)
570                 key = (GHOST_TKey)(vKey - 'A' + GHOST_kKeyA);
571         }
572         else if ((vKey >= VK_F1) && (vKey <= VK_F24)) {
573                 key = (GHOST_TKey)(vKey - VK_F1 + GHOST_kKeyF1);
574         }
575         else {
576                 switch (vKey) {
577                 case VK_RETURN:
578                                 key = (extend)?GHOST_kKeyNumpadEnter : GHOST_kKeyEnter; break;
579                         
580                 case VK_BACK:     key = GHOST_kKeyBackSpace;            break;
581                 case VK_TAB:      key = GHOST_kKeyTab;                          break;
582                 case VK_ESCAPE:   key = GHOST_kKeyEsc;                          break;
583                 case VK_SPACE:    key = GHOST_kKeySpace;                        break;
584                 
585                 case VK_INSERT:
586                 case VK_NUMPAD0:
587                         key = (extend) ? GHOST_kKeyInsert : GHOST_kKeyNumpad0;  break;
588                 case VK_END:
589                 case VK_NUMPAD1:        
590                         key = (extend) ? GHOST_kKeyEnd : GHOST_kKeyNumpad1;     break;
591                 case VK_DOWN:
592                 case VK_NUMPAD2:
593                         key = (extend) ? GHOST_kKeyDownArrow : GHOST_kKeyNumpad2;       break;
594                 case VK_NEXT:
595                 case VK_NUMPAD3:
596                         key = (extend) ?  GHOST_kKeyDownPage : GHOST_kKeyNumpad3;       break;
597                 case VK_LEFT:
598                 case VK_NUMPAD4:
599                         key = (extend) ? GHOST_kKeyLeftArrow : GHOST_kKeyNumpad4;       break;
600                 case VK_CLEAR:
601                 case VK_NUMPAD5:
602                         key = (extend) ? GHOST_kKeyUnknown: GHOST_kKeyNumpad5;  break;
603                 case VK_RIGHT:
604                 case VK_NUMPAD6:
605                         key = (extend) ? GHOST_kKeyRightArrow : GHOST_kKeyNumpad6;      break;
606                 case VK_HOME:
607                 case VK_NUMPAD7:
608                         key = (extend) ? GHOST_kKeyHome : GHOST_kKeyNumpad7;    break;
609                 case VK_UP:
610                 case VK_NUMPAD8:
611                         key = (extend) ? GHOST_kKeyUpArrow : GHOST_kKeyNumpad8; break;
612                 case VK_PRIOR:
613                 case VK_NUMPAD9:
614                         key = (extend) ? GHOST_kKeyUpPage : GHOST_kKeyNumpad9;  break;
615                 case VK_DECIMAL:
616                 case VK_DELETE:
617                         key = (extend) ? GHOST_kKeyDelete : GHOST_kKeyNumpadPeriod;     break;
618
619                 case VK_SNAPSHOT: key = GHOST_kKeyPrintScreen;          break;
620                 case VK_PAUSE:    key = GHOST_kKeyPause;                        break;
621                 case VK_MULTIPLY: key = GHOST_kKeyNumpadAsterisk;       break;
622                 case VK_SUBTRACT: key = GHOST_kKeyNumpadMinus;          break;
623                 case VK_DIVIDE:   key = GHOST_kKeyNumpadSlash;          break;
624                 case VK_ADD:      key = GHOST_kKeyNumpadPlus;           break;
625
626                 case VK_SEMICOLON:              key = GHOST_kKeySemicolon;              break;
627                 case VK_EQUALS:                 key = GHOST_kKeyEqual;                  break;
628                 case VK_COMMA:                  key = GHOST_kKeyComma;                  break;
629                 case VK_MINUS:                  key = GHOST_kKeyMinus;                  break;
630                 case VK_PERIOD:                 key = GHOST_kKeyPeriod;                 break;
631                 case VK_SLASH:                  key = GHOST_kKeySlash;                  break;
632                 case VK_BACK_QUOTE:             key = GHOST_kKeyAccentGrave;    break;
633                 case VK_OPEN_BRACKET:   key = GHOST_kKeyLeftBracket;    break;
634                 case VK_BACK_SLASH:             key = GHOST_kKeyBackslash;              break;
635                 case VK_CLOSE_BRACKET:  key = GHOST_kKeyRightBracket;   break;
636                 case VK_QUOTE:                  key = GHOST_kKeyQuote;                  break;
637                 case VK_GR_LESS:                key = GHOST_kKeyGrLess;                 break;
638
639                 case VK_SHIFT:
640                         key = (scanCode == 0x36)? GHOST_kKeyRightShift : GHOST_kKeyLeftShift;
641                         break;
642                 case VK_CONTROL:
643                         key = (extend)? GHOST_kKeyRightControl : GHOST_kKeyLeftControl;
644                         break;
645                 case VK_MENU:
646                         key = (extend)? GHOST_kKeyRightAlt : GHOST_kKeyLeftAlt;
647                         break;
648                 case VK_LWIN:
649                 case VK_RWIN:
650                         key = GHOST_kKeyOS;
651                         break;
652                 case VK_NUMLOCK: key = GHOST_kKeyNumLock; break;
653                 case VK_SCROLL: key = GHOST_kKeyScrollLock; break;
654                 case VK_CAPITAL: key = GHOST_kKeyCapsLock; break;
655                 case VK_OEM_8:
656                         key = ((GHOST_SystemWin32*)getSystem())->processSpecialKey(window, vKey, scanCode);
657                         break;
658                 case VK_MEDIA_PLAY_PAUSE: key = GHOST_kKeyMediaPlay; break;
659                 case VK_MEDIA_STOP: key = GHOST_kKeyMediaStop; break;
660                 case VK_MEDIA_PREV_TRACK: key = GHOST_kKeyMediaFirst; break;
661                 case VK_MEDIA_NEXT_TRACK: key = GHOST_kKeyMediaLast; break;
662                 default:
663                         key = GHOST_kKeyUnknown;
664                         break;
665                 }
666         }
667         
668         return key;
669 }
670
671 GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask)
672 {
673         return new GHOST_EventButton (getSystem()->getMilliSeconds(), type, window, mask);
674 }
675
676
677 GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow)
678 {
679         GHOST_TInt32 x_screen, y_screen;
680         GHOST_SystemWin32 * system = ((GHOST_SystemWin32 * ) getSystem());
681         GHOST_WindowWin32 * window = ( GHOST_WindowWin32 * ) Iwindow;
682         
683         system->getCursorPosition(x_screen, y_screen);
684
685         if(window->getCursorGrabMode() != GHOST_kGrabDisable && window->getCursorGrabMode() != GHOST_kGrabNormal)
686         {
687                 GHOST_TInt32 x_new= x_screen;
688                 GHOST_TInt32 y_new= y_screen;
689                 GHOST_TInt32 x_accum, y_accum;
690                 GHOST_Rect bounds;
691
692                 /* fallback to window bounds */
693                 if(window->getCursorGrabBounds(bounds)==GHOST_kFailure){
694                         window->getClientBounds(bounds);
695                 }
696
697                 /* could also clamp to screen bounds
698                  * wrap with a window outside the view will fail atm  */
699
700                 bounds.wrapPoint(x_new, y_new, 2); /* offset of one incase blender is at screen bounds */
701
702                 window->getCursorGrabAccum(x_accum, y_accum);
703                 if(x_new != x_screen|| y_new != y_screen) {
704                         /* when wrapping we don't need to add an event because the
705                          * setCursorPosition call will cause a new event after */
706                         system->setCursorPosition(x_new, y_new); /* wrap */
707                         window->setCursorGrabAccum(x_accum + (x_screen - x_new), y_accum + (y_screen - y_new));
708                 }else{
709                         return new GHOST_EventCursor(system->getMilliSeconds(),
710                                                                                  GHOST_kEventCursorMove,
711                                                                                  window,
712                                                                                  x_screen + x_accum,
713                                                                                  y_screen + y_accum
714                         );
715                 }
716
717         }
718         else {
719                 return new GHOST_EventCursor(system->getMilliSeconds(),
720                                                                          GHOST_kEventCursorMove,
721                                                                          window,
722                                                                          x_screen,
723                                                                          y_screen
724                 );
725         }
726         return NULL;
727 }
728
729
730 GHOST_EventWheel* GHOST_SystemWin32::processWheelEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam)
731 {
732         // short fwKeys = LOWORD(wParam);                       // key flags
733         int zDelta = (short) HIWORD(wParam);    // wheel rotation
734         
735         // zDelta /= WHEEL_DELTA;
736         // temporary fix below: microsoft now has added more precision, making the above division not work
737         if (zDelta <= 0 ) zDelta= -1; else zDelta= 1;   
738         
739         // short xPos = (short) LOWORD(lParam); // horizontal position of pointer
740         // short yPos = (short) HIWORD(lParam); // vertical position of pointer
741         return new GHOST_EventWheel (getSystem()->getMilliSeconds(), window, zDelta);
742 }
743
744
745 GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam)
746 {
747         int keyDown=0;
748         char vk;
749         GHOST_SystemWin32 * system = (GHOST_SystemWin32 *)getSystem();
750         GHOST_TKey key = system->hardKey(window, wParam, lParam, &keyDown, &vk);
751         GHOST_EventKey* event;
752         if (key != GHOST_kKeyUnknown) {
753                 char ascii = '\0';
754
755                 unsigned short utf16[2]={0};
756                 BYTE state[256];
757                 GetKeyboardState((PBYTE)state);
758
759                 if(ToAsciiEx(vk, 0, state, utf16, 0, system->m_keylayout))
760                                 WideCharToMultiByte(CP_ACP, 0x00000400, 
761                                                                         (wchar_t*)utf16, 1,
762                                                                         (LPSTR) &ascii, 1,
763                                                                         NULL,NULL);
764
765                 event = new GHOST_EventKey(system->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown: GHOST_kEventKeyUp, window, key, ascii);
766                 
767 #ifdef GHOST_DEBUG
768                 std::cout << ascii << std::endl;
769 #endif
770         }
771         else {
772                 event = 0;
773         }
774         return event;
775 }
776
777
778 GHOST_Event* GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window)
779 {
780         return new GHOST_Event(getSystem()->getMilliSeconds(), type, window);
781 }
782
783 GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType, 
784                                                                                                         GHOST_TDragnDropTypes draggedObjectType,
785                                                                                                         GHOST_IWindow* window,
786                                                                                                         int mouseX, int mouseY,
787                                                                                                         void* data)
788 {
789         GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem());
790         return system->pushEvent(new GHOST_EventDragnDrop(system->getMilliSeconds(),
791                                                                                                           eventType,
792                                                                                                           draggedObjectType,
793                                                                                                           window,mouseX,mouseY,data)
794                         );
795 }
796
797 void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax)
798 {
799         minmax->ptMinTrackSize.x=320;
800         minmax->ptMinTrackSize.y=240;
801 }
802
803 LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
804 {
805         GHOST_Event* event = 0;
806         LRESULT lResult = 0;
807         GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem());
808         GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized")
809
810         if (hwnd) {
811                 GHOST_WindowWin32* window = (GHOST_WindowWin32*)::GetWindowLong(hwnd, GWL_USERDATA);
812                 if (window) {
813                         switch (msg) {
814                                 // we need to check if new key layout has AltGr
815                                 case WM_INPUTLANGCHANGE:
816                                         system->handleKeyboardChange();
817                                         break;
818                                 ////////////////////////////////////////////////////////////////////////
819                                 // Keyboard events, processed
820                                 ////////////////////////////////////////////////////////////////////////
821                                 case WM_INPUT:
822                                         // check WM_INPUT from input sink when ghost window is not in the foreground
823                                         if (wParam == RIM_INPUTSINK) {
824                                                 if (GetFocus() != hwnd) // WM_INPUT message not for this window
825                                                         return 0;
826                                         } //else wPAram == RIM_INPUT
827                                         event = processKeyEvent(window, wParam, lParam);
828                                         if (!event) {
829                                                 GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
830                                                 GHOST_PRINT(msg)
831                                                 GHOST_PRINT(" key ignored\n")
832                                         }
833                                         break;
834                                 ////////////////////////////////////////////////////////////////////////
835                                 // Keyboard events, ignored
836                                 ////////////////////////////////////////////////////////////////////////
837                                 case WM_KEYDOWN:
838                                 case WM_SYSKEYDOWN:
839                                 case WM_KEYUP:
840                                 case WM_SYSKEYUP:
841                                         /* These functions were replaced by WM_INPUT*/
842                                 case WM_CHAR:
843                                         /* The WM_CHAR message is posted to the window with the keyboard focus when 
844                                          * a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR 
845                                          * contains the character code of the key that was pressed. 
846                                          */
847                                 case WM_DEADCHAR:
848                                         /* The WM_DEADCHAR message is posted to the window with the keyboard focus when a
849                                          * WM_KEYUP message is translated by the TranslateMessage function. WM_DEADCHAR 
850                                          * specifies a character code generated by a dead key. A dead key is a key that 
851                                          * generates a character, such as the umlaut (double-dot), that is combined with 
852                                          * another character to form a composite character. For example, the umlaut-O 
853                                          * character (Ö) is generated by typing the dead key for the umlaut character, and
854                                          * then typing the O key.
855                                          */
856                                         break;
857                                 case WM_SYSDEADCHAR:
858                                         /* The WM_SYSDEADCHAR message is sent to the window with the keyboard focus when 
859                                          * a WM_SYSKEYDOWN message is translated by the TranslateMessage function. 
860                                          * WM_SYSDEADCHAR specifies the character code of a system dead key - that is, 
861                                          * a dead key that is pressed while holding down the alt key. 
862                                          */
863                                 case WM_SYSCHAR:
864                                         /* The WM_SYSCHAR message is sent to the window with the keyboard focus when 
865                                          * a WM_SYSCHAR message is translated by the TranslateMessage function. 
866                                          * WM_SYSCHAR specifies the character code of a dead key - that is, 
867                                          * a dead key that is pressed while holding down the alt key.
868                                          * To prevent the sound, DefWindowProc must be avoided by return
869                                          */
870                                         break;
871                                 case WM_SYSCOMMAND:
872                                         /* The WM_SYSCHAR message is sent to the window when system commands such as 
873                                          * maximize, minimize  or close the window are triggered. Also it is sent when ALT 
874                                          * button is press for menu. To prevent this we must return preventing DefWindowProc.
875                                          */
876                                         if(wParam==SC_KEYMENU) return 0;
877                                         break;
878                                 ////////////////////////////////////////////////////////////////////////
879                                 // Tablet events, processed
880                                 ////////////////////////////////////////////////////////////////////////
881                                 case WT_PACKET:
882                                         ((GHOST_WindowWin32*)window)->processWin32TabletEvent(wParam, lParam);
883                                         break;
884                                 case WT_CSRCHANGE:
885                                 case WT_PROXIMITY:
886                                         ((GHOST_WindowWin32*)window)->processWin32TabletInitEvent();
887                                         break;
888                                 ////////////////////////////////////////////////////////////////////////
889                                 // Mouse events, processed
890                                 ////////////////////////////////////////////////////////////////////////
891                                 case WM_LBUTTONDOWN:
892                                         window->registerMouseClickEvent(0);
893                                         event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskLeft);
894                                         break;
895                                 case WM_MBUTTONDOWN:
896                                         window->registerMouseClickEvent(0);
897                                         event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskMiddle);
898                                         break;
899                                 case WM_RBUTTONDOWN:
900                                         window->registerMouseClickEvent(0);
901                                         event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskRight);
902                                         break;
903                                 case WM_XBUTTONDOWN:
904                                         window->registerMouseClickEvent(0);
905                                         if ((short) HIWORD(wParam) == XBUTTON1){
906                                                 event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton4);
907                                         }else if((short) HIWORD(wParam) == XBUTTON2){
908                                                 event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton5);
909                                         }
910                                         break;
911                                 case WM_LBUTTONUP:
912                                         window->registerMouseClickEvent(1);
913                                         event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft);
914                                         break;
915                                 case WM_MBUTTONUP:
916                                         window->registerMouseClickEvent(1);
917                                         event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskMiddle);
918                                         break;
919                                 case WM_RBUTTONUP:
920                                         window->registerMouseClickEvent(1);
921                                         event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskRight);
922                                         break;
923                                 case WM_XBUTTONUP:
924                                         window->registerMouseClickEvent(1);
925                                         if ((short) HIWORD(wParam) == XBUTTON1){
926                                                 event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton4);
927                                         }else if((short) HIWORD(wParam) == XBUTTON2){
928                                                 event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton5);
929                                         }
930                                         break;
931                                 case WM_MOUSEMOVE:
932                                         event = processCursorEvent(GHOST_kEventCursorMove, window);
933                                         break;
934                                 case WM_MOUSEWHEEL:
935                                         /* The WM_MOUSEWHEEL message is sent to the focus window 
936                                          * when the mouse wheel is rotated. The DefWindowProc 
937                                          * function propagates the message to the window's parent.
938                                          * There should be no internal forwarding of the message, 
939                                          * since DefWindowProc propagates it up the parent chain 
940                                          * until it finds a window that processes it.
941                                          */
942                                         event = processWheelEvent(window, wParam, lParam);
943                                         break;
944                                 case WM_SETCURSOR:
945                                         /* The WM_SETCURSOR message is sent to a window if the mouse causes the cursor
946                                          * to move within a window and mouse input is not captured.
947                                          * This means we have to set the cursor shape every time the mouse moves!
948                                          * The DefWindowProc function uses this message to set the cursor to an 
949                                          * arrow if it is not in the client area.
950                                          */
951                                         if (LOWORD(lParam) == HTCLIENT) {
952                                                 // Load the current cursor
953                                                 window->loadCursor(window->getCursorVisibility(), window->getCursorShape());
954                                                 // Bypass call to DefWindowProc
955                                                 return 0;
956                                         } 
957                                         else {
958                                                 // Outside of client area show standard cursor
959                                                 window->loadCursor(true, GHOST_kStandardCursorDefault);
960                                         }
961                                         break;
962
963                                 ////////////////////////////////////////////////////////////////////////
964                                 // Mouse events, ignored
965                                 ////////////////////////////////////////////////////////////////////////
966                                 case WM_NCMOUSEMOVE:
967                                         /* The WM_NCMOUSEMOVE message is posted to a window when the cursor is moved 
968                                          * within the nonclient area of the window. This message is posted to the window 
969                                          * that contains the cursor. If a window has captured the mouse, this message is not posted.
970                                          */
971                                 case WM_NCHITTEST:
972                                         /* The WM_NCHITTEST message is sent to a window when the cursor moves, or 
973                                          * when a mouse button is pressed or released. If the mouse is not captured, 
974                                          * the message is sent to the window beneath the cursor. Otherwise, the message 
975                                          * is sent to the window that has captured the mouse. 
976                                          */
977                                         break;
978
979                                 ////////////////////////////////////////////////////////////////////////
980                                 // Window events, processed
981                                 ////////////////////////////////////////////////////////////////////////
982                                 case WM_CLOSE:
983                                         /* The WM_CLOSE message is sent as a signal that a window or an application should terminate. */
984                                         event = processWindowEvent(GHOST_kEventWindowClose, window);
985                                         break;
986                                 case WM_ACTIVATE:
987                                         /* The WM_ACTIVATE message is sent to both the window being activated and the window being 
988                                          * deactivated. If the windows use the same input queue, the message is sent synchronously, 
989                                          * first to the window procedure of the top-level window being deactivated, then to the window
990                                          * procedure of the top-level window being activated. If the windows use different input queues,
991                                          * the message is sent asynchronously, so the window is activated immediately. 
992                                          */
993                                         {
994                                         GHOST_ModifierKeys modifiers;
995                                         modifiers.clear();
996                                         system->storeModifierKeys(modifiers);
997                                         event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window);
998                                         /* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL
999                                         will not be dispatched to OUR active window if we minimize one of OUR windows. */
1000                                         lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
1001                                         break;
1002                                         }
1003                                 case WM_PAINT:
1004                                         /* An application sends the WM_PAINT message when the system or another application 
1005                                          * makes a request to paint a portion of an application's window. The message is sent
1006                                          * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage 
1007                                          * function when the application obtains a WM_PAINT message by using the GetMessage or 
1008                                          * PeekMessage function. 
1009                                          */
1010                                         event = processWindowEvent(GHOST_kEventWindowUpdate, window);
1011                                         ::ValidateRect(hwnd, NULL);
1012                                         break;
1013                                 case WM_GETMINMAXINFO:
1014                                         /* The WM_GETMINMAXINFO message is sent to a window when the size or 
1015                                          * position of the window is about to change. An application can use 
1016                                          * this message to override the window's default maximized size and 
1017                                          * position, or its default minimum or maximum tracking size. 
1018                                          */
1019                                         processMinMaxInfo((MINMAXINFO *) lParam);
1020                                         /* Let DefWindowProc handle it. */
1021                                         break;
1022                                 case WM_SIZE:
1023                                         /* The WM_SIZE message is sent to a window after its size has changed.
1024                                          * The WM_SIZE and WM_MOVE messages are not sent if an application handles the 
1025                                          * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
1026                                          * to perform any move or size change processing during the WM_WINDOWPOSCHANGED 
1027                                          * message without calling DefWindowProc.
1028                                          */
1029                                         event = processWindowEvent(GHOST_kEventWindowSize, window);
1030                                         break;
1031                                 case WM_CAPTURECHANGED:
1032                                         window->lostMouseCapture();
1033                                         break;
1034                                 case WM_MOVING:
1035                                         /* The WM_MOVING message is sent to a window that the user is moving. By processing 
1036                                          * this message, an application can monitor the size and position of the drag rectangle
1037                                          * and, if needed, change its size or position.
1038                                          */
1039                                 case WM_MOVE:
1040                                         /* The WM_SIZE and WM_MOVE messages are not sent if an application handles the 
1041                                          * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
1042                                          * to perform any move or size change processing during the WM_WINDOWPOSCHANGED 
1043                                          * message without calling DefWindowProc. 
1044                                          */
1045                                         event = processWindowEvent(GHOST_kEventWindowMove, window);
1046                                         break;
1047                                 ////////////////////////////////////////////////////////////////////////
1048                                 // Window events, ignored
1049                                 ////////////////////////////////////////////////////////////////////////
1050                                 case WM_WINDOWPOSCHANGED:
1051                                         /* The WM_WINDOWPOSCHANGED message is sent to a window whose size, position, or place
1052                                          * in the Z order has changed as a result of a call to the SetWindowPos function or 
1053                                          * another window-management function.
1054                                          * The WM_SIZE and WM_MOVE messages are not sent if an application handles the 
1055                                          * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
1056                                          * to perform any move or size change processing during the WM_WINDOWPOSCHANGED 
1057                                          * message without calling DefWindowProc.
1058                                          */
1059                                 case WM_ERASEBKGND:
1060                                         /* An application sends the WM_ERASEBKGND message when the window background must be 
1061                                          * erased (for example, when a window is resized). The message is sent to prepare an 
1062                                          * invalidated portion of a window for painting. 
1063                                          */
1064                                 case WM_NCPAINT:
1065                                         /* An application sends the WM_NCPAINT message to a window when its frame must be painted. */
1066                                 case WM_NCACTIVATE:
1067                                         /* The WM_NCACTIVATE message is sent to a window when its nonclient area needs to be changed 
1068                                          * to indicate an active or inactive state. 
1069                                          */
1070                                 case WM_DESTROY:
1071                                         /* The WM_DESTROY message is sent when a window is being destroyed. It is sent to the window 
1072                                          * procedure of the window being destroyed after the window is removed from the screen. 
1073                                          * This message is sent first to the window being destroyed and then to the child windows 
1074                                          * (if any) as they are destroyed. During the processing of the message, it can be assumed 
1075                                          * that all child windows still exist. 
1076                                          */
1077                                 case WM_NCDESTROY:
1078                                         /* The WM_NCDESTROY message informs a window that its nonclient area is being destroyed. The 
1079                                          * DestroyWindow function sends the WM_NCDESTROY message to the window following the WM_DESTROY
1080                                          * message. WM_DESTROY is used to free the allocated memory object associated with the window. 
1081                                          */
1082                                         break;
1083                                 case WM_KILLFOCUS:
1084                                         /* The WM_KILLFOCUS message is sent to a window immediately before it loses the keyboard focus. 
1085                                          * We want to prevent this if a window is still active and it loses focus to nowhere*/
1086                                         if(!wParam && hwnd==GetActiveWindow())
1087                                                 SetFocus(hwnd);
1088                                 case WM_SHOWWINDOW:
1089                                         /* The WM_SHOWWINDOW message is sent to a window when the window is about to be hidden or shown. */
1090                                 case WM_WINDOWPOSCHANGING:
1091                                         /* The WM_WINDOWPOSCHANGING message is sent to a window whose size, position, or place in 
1092                                          * the Z order is about to change as a result of a call to the SetWindowPos function or 
1093                                          * another window-management function. 
1094                                          */
1095                                 case WM_SETFOCUS:
1096                                         /* The WM_SETFOCUS message is sent to a window after it has gained the keyboard focus. */
1097                                 case WM_ENTERSIZEMOVE:
1098                                         /* The WM_ENTERSIZEMOVE message is sent one time to a window after it enters the moving 
1099                                          * or sizing modal loop. The window enters the moving or sizing modal loop when the user 
1100                                          * clicks the window's title bar or sizing border, or when the window passes the 
1101                                          * WM_SYSCOMMAND message to the DefWindowProc function and the wParam parameter of the 
1102                                          * message specifies the SC_MOVE or SC_SIZE value. The operation is complete when 
1103                                          * DefWindowProc returns. 
1104                                          */
1105                                         break;
1106                                         
1107                                 ////////////////////////////////////////////////////////////////////////
1108                                 // Other events
1109                                 ////////////////////////////////////////////////////////////////////////
1110                                 case WM_GETTEXT:
1111                                         /* An application sends a WM_GETTEXT message to copy the text that 
1112                                          * corresponds to a window into a buffer provided by the caller. 
1113                                          */
1114                                 case WM_ACTIVATEAPP:
1115                                         /* The WM_ACTIVATEAPP message is sent when a window belonging to a 
1116                                          * different application than the active window is about to be activated.
1117                                          * The message is sent to the application whose window is being activated
1118                                          * and to the application whose window is being deactivated. 
1119                                          */
1120                                 case WM_TIMER:
1121                                         /* The WIN32 docs say:
1122                                          * The WM_TIMER message is posted to the installing thread's message queue
1123                                          * when a timer expires. You can process the message by providing a WM_TIMER
1124                                          * case in the window procedure. Otherwise, the default window procedure will
1125                                          * call the TimerProc callback function specified in the call to the SetTimer
1126                                          * function used to install the timer. 
1127                                          *
1128                                          * In GHOST, we let DefWindowProc call the timer callback.
1129                                          */
1130                                         break;
1131                                 case WM_BLND_NDOF_AXIS:
1132                                         {
1133                                                 GHOST_TEventNDOFData ndofdata;
1134                                                 system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata);
1135                                                 system->m_eventManager->
1136                                                         pushEvent(new GHOST_EventNDOF(
1137                                                                 system->getMilliSeconds(), 
1138                                                                 GHOST_kEventNDOFMotion, 
1139                                                                 window, ndofdata));
1140                                         }
1141                                         break;
1142                                 case WM_BLND_NDOF_BTN:
1143                                         {
1144                                                 GHOST_TEventNDOFData ndofdata;
1145                                                 system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata);
1146                                                 system->m_eventManager->
1147                                                         pushEvent(new GHOST_EventNDOF(
1148                                                                 system->getMilliSeconds(), 
1149                                                                 GHOST_kEventNDOFButton, 
1150                                                                 window, ndofdata));
1151                                         }
1152                                         break;
1153                         }
1154                 }
1155                 else {
1156                         // Event found for a window before the pointer to the class has been set.
1157                         GHOST_PRINT("GHOST_SystemWin32::wndProc: GHOST window event before creation\n")
1158                         /* These are events we typically miss at this point:
1159                            WM_GETMINMAXINFO     0x24
1160                            WM_NCCREATE                  0x81
1161                            WM_NCCALCSIZE                0x83
1162                            WM_CREATE                    0x01
1163                            We let DefWindowProc do the work.
1164                         */
1165                 }
1166         }
1167         else {
1168                 // Events without valid hwnd
1169                 GHOST_PRINT("GHOST_SystemWin32::wndProc: event without window\n")
1170         }
1171
1172         if (event) {
1173                 system->pushEvent(event);
1174         }
1175         else {
1176                 lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
1177         }
1178         return lResult;
1179 }
1180
1181 GHOST_TUns8* GHOST_SystemWin32::getClipboard(bool selection) const 
1182 {
1183         char *buffer;
1184         char *temp_buff;
1185         
1186         if ( IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL) ) {
1187                 size_t len = 0;
1188                 HANDLE hData = GetClipboardData( CF_TEXT );
1189                 if (hData == NULL) {
1190                         CloseClipboard();
1191                         return NULL;
1192                 }
1193                 buffer = (char*)GlobalLock( hData );
1194                 if (!buffer) {
1195                         CloseClipboard();
1196                         return NULL;
1197                 }
1198                 
1199                 len = strlen(buffer);
1200                 temp_buff = (char*) malloc(len+1);
1201                 strncpy(temp_buff, buffer, len);
1202                 temp_buff[len] = '\0';
1203                 
1204                 /* Buffer mustn't be accessed after CloseClipboard
1205                    it would like accessing free-d memory */
1206                 GlobalUnlock( hData );
1207                 CloseClipboard();
1208                 
1209                 return (GHOST_TUns8*)temp_buff;
1210         } else {
1211                 return NULL;
1212         }
1213 }
1214
1215 void GHOST_SystemWin32::putClipboard(GHOST_TInt8 *buffer, bool selection) const
1216 {
1217         if(selection) {return;} // for copying the selection, used on X11
1218
1219         if (OpenClipboard(NULL)) {
1220                 HLOCAL clipbuffer;
1221                 char *data;
1222                 
1223                 if (buffer) {
1224                         EmptyClipboard();
1225                         
1226                         clipbuffer = LocalAlloc(LMEM_FIXED,((strlen(buffer)+1)));
1227                         data = (char*)GlobalLock(clipbuffer);
1228
1229                         strcpy(data, (char*)buffer);
1230                         data[strlen(buffer)] = '\0';
1231                         LocalUnlock(clipbuffer);
1232                         SetClipboardData(CF_TEXT,clipbuffer);
1233                 }
1234                 CloseClipboard();
1235         } else {
1236                 return;
1237         }
1238 }
1239
1240 int GHOST_SystemWin32::toggleConsole(int action)
1241 {
1242         switch(action)
1243         {
1244                 case 3: //hide if no console
1245                         {
1246                                 DWORD sp = GetCurrentProcessId();
1247                                 HANDLE ptree = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1248                                 PROCESSENTRY32 e = {0}; e.dwSize = sizeof(PROCESSENTRY32);
1249                                 
1250                                 if( Process32First(ptree, &e)) {
1251                                         do { //Searches for Blender's PROCESSENTRY32
1252                                                         if (e.th32ProcessID == sp) {
1253                                                                 sp = e.th32ParentProcessID;
1254                                                                 Process32First(ptree, &e);
1255                                                                         do { //Got parent id, searches for its PROCESSENTRY32
1256                                                                                 if (e.th32ProcessID == sp) {
1257                                                                                         if(strcmp("explorer.exe",e.szExeFile)==0)
1258                                                                                         { //If explorer, hide cmd
1259                                                                                                 ShowWindow(GetConsoleWindow(),SW_HIDE);
1260                                                                                                 m_consoleStatus = 0;
1261                                                                                         }
1262                                                                                         break;
1263                                                                                 }
1264
1265                                                                         } while( Process32Next(ptree, &e));
1266                                                                 break;
1267                                                         }
1268                                         } while( Process32Next(ptree, &e));
1269                                 }
1270
1271                                 CloseHandle(ptree);
1272                                 break;
1273                         }
1274                 case 0: //hide
1275                         ShowWindow(GetConsoleWindow(),SW_HIDE);
1276                         m_consoleStatus = 0;
1277                         break;
1278                 case 1: //show
1279                         ShowWindow(GetConsoleWindow(),SW_SHOW);
1280                         m_consoleStatus = 1;
1281                         break;
1282                 case 2: //toggle
1283                         ShowWindow(GetConsoleWindow(),m_consoleStatus?SW_HIDE:SW_SHOW);
1284                         m_consoleStatus=!m_consoleStatus;
1285                         break;
1286
1287         };
1288
1289
1290         return m_consoleStatus;
1291 }