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