33c7a7f15a2b9dbf2ab7618e5692c5c91c71304a
[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         /*
291         GetKeyState and GetAsyncKeyState only work with Win95, Win98, NT4,
292         Terminal Server and Windows 2000.
293         But on WinME it always returns zero. These two functions are simply
294         skipped by Millenium Edition!
295
296         Official explanation from Microsoft:
297         Intentionally disabled.
298         It didn't work all that well on some newer hardware, and worked less 
299         well with the passage of time, so it was fully disabled in ME.
300         */
301         if (m_separateLeftRight && m_separateLeftRightInitialized) {
302                 bool down = HIBYTE(::GetKeyState(VK_LSHIFT)) != 0;
303                 keys.set(GHOST_kModifierKeyLeftShift, down);
304                 down = HIBYTE(::GetKeyState(VK_RSHIFT)) != 0;
305                 keys.set(GHOST_kModifierKeyRightShift, down);
306                 down = HIBYTE(::GetKeyState(VK_LMENU)) != 0;
307                 keys.set(GHOST_kModifierKeyLeftAlt, down);
308                 down = HIBYTE(::GetKeyState(VK_RMENU)) != 0;
309                 keys.set(GHOST_kModifierKeyRightAlt, down);
310                 down = HIBYTE(::GetKeyState(VK_LCONTROL)) != 0;
311                 keys.set(GHOST_kModifierKeyLeftControl, down);
312                 down = HIBYTE(::GetKeyState(VK_RCONTROL)) != 0;
313                 keys.set(GHOST_kModifierKeyRightControl, down);
314         }
315         else {
316                 bool down = HIBYTE(::GetKeyState(VK_SHIFT)) != 0;
317                 keys.set(GHOST_kModifierKeyLeftShift, down);
318                 keys.set(GHOST_kModifierKeyRightShift, down);
319                 down = HIBYTE(::GetKeyState(VK_MENU)) != 0;
320                 keys.set(GHOST_kModifierKeyLeftAlt, down);
321                 keys.set(GHOST_kModifierKeyRightAlt, down);
322                 down = HIBYTE(::GetKeyState(VK_CONTROL)) != 0;
323                 keys.set(GHOST_kModifierKeyLeftControl, down);
324                 keys.set(GHOST_kModifierKeyRightControl, down);
325         }
326         return GHOST_kSuccess;
327 }
328
329
330 GHOST_TSuccess GHOST_SystemWin32::getButtons(GHOST_Buttons& buttons) const
331 {
332         /* Check for swapped buttons (left-handed mouse buttons)
333          * GetAsyncKeyState() will give back the state of the physical mouse buttons.
334          */
335         bool swapped = ::GetSystemMetrics(SM_SWAPBUTTON) == TRUE;
336
337         bool down = HIBYTE(::GetKeyState(VK_LBUTTON)) != 0;
338         buttons.set(swapped ? GHOST_kButtonMaskRight : GHOST_kButtonMaskLeft, down);
339
340         down = HIBYTE(::GetKeyState(VK_MBUTTON)) != 0;
341         buttons.set(GHOST_kButtonMaskMiddle, down);
342
343         down = HIBYTE(::GetKeyState(VK_RBUTTON)) != 0;
344         buttons.set(swapped ? GHOST_kButtonMaskLeft : GHOST_kButtonMaskRight, down);
345         return GHOST_kSuccess;
346 }
347
348
349 GHOST_TSuccess GHOST_SystemWin32::init()
350 {
351         GHOST_TSuccess success = GHOST_System::init();
352
353         /* Disable scaling on high DPI displays on Vista */
354         HMODULE user32 = ::LoadLibraryA("user32.dll");
355         typedef BOOL (WINAPI * LPFNSETPROCESSDPIAWARE)();
356         LPFNSETPROCESSDPIAWARE SetProcessDPIAware =
357                 (LPFNSETPROCESSDPIAWARE)GetProcAddress(user32, "SetProcessDPIAware");
358         if (SetProcessDPIAware)
359                 SetProcessDPIAware();
360         FreeLibrary(user32);
361
362         // Determine whether this system has a high frequency performance counter. */
363         m_hasPerformanceCounter = ::QueryPerformanceFrequency((LARGE_INTEGER*)&m_freq) == TRUE;
364         if (m_hasPerformanceCounter) {
365                 GHOST_PRINT("GHOST_SystemWin32::init: High Frequency Performance Timer available\n")
366                 ::QueryPerformanceCounter((LARGE_INTEGER*)&m_start);
367         }
368         else {
369                 GHOST_PRINT("GHOST_SystemWin32::init: High Frequency Performance Timer not available\n")
370         }
371
372         if (success) {
373                 WNDCLASS wc;
374                 wc.style= CS_HREDRAW | CS_VREDRAW;
375                 wc.lpfnWndProc= s_wndProc;
376                 wc.cbClsExtra= 0;
377                 wc.cbWndExtra= 0;
378                 wc.hInstance= ::GetModuleHandle(0);
379                 wc.hIcon = ::LoadIcon(wc.hInstance, "APPICON");
380                 
381                 if (!wc.hIcon) {
382                         ::LoadIcon(NULL, IDI_APPLICATION);
383                 }
384                 wc.hCursor = ::LoadCursor(0, IDC_ARROW);
385                 wc.hbrBackground= (HBRUSH)::GetStockObject(BLACK_BRUSH);
386                 wc.lpszMenuName = 0;
387                 wc.lpszClassName= GHOST_WindowWin32::getWindowClassName();
388     
389                 // Use RegisterClassEx for setting small icon
390                 if (::RegisterClass(&wc) == 0) {
391                         success = GHOST_kFailure;
392                 }
393         }
394         return success;
395 }
396
397
398 GHOST_TSuccess GHOST_SystemWin32::exit()
399 {
400         return GHOST_System::exit();
401 }
402
403
404 GHOST_TKey GHOST_SystemWin32::convertKey(WPARAM wParam, LPARAM lParam) const
405 {
406         GHOST_TKey key;
407         bool isExtended = (lParam&(1<<24))?true:false;
408
409         if ((wParam >= '0') && (wParam <= '9')) {
410                 // VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39)
411                 key = (GHOST_TKey)(wParam - '0' + GHOST_kKey0);
412         }
413         else if ((wParam >= 'A') && (wParam <= 'Z')) {
414                 // VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A)
415                 key = (GHOST_TKey)(wParam - 'A' + GHOST_kKeyA);
416         }
417         else if ((wParam >= VK_F1) && (wParam <= VK_F24)) {
418                 key = (GHOST_TKey)(wParam - VK_F1 + GHOST_kKeyF1);
419         }
420         else {
421                 switch (wParam) {
422                 case VK_RETURN:
423                         key = isExtended?GHOST_kKeyNumpadEnter:GHOST_kKeyEnter;
424                         break;
425
426                 case VK_BACK:     key = GHOST_kKeyBackSpace;            break;
427                 case VK_TAB:      key = GHOST_kKeyTab;                          break;
428                 case VK_ESCAPE:   key = GHOST_kKeyEsc;                          break;
429                 case VK_SPACE:    key = GHOST_kKeySpace;                        break;
430                 case VK_PRIOR:    key = GHOST_kKeyUpPage;                       break;
431                 case VK_NEXT:     key = GHOST_kKeyDownPage;                     break;
432                 case VK_END:      key = GHOST_kKeyEnd;                          break;
433                 case VK_HOME:     key = GHOST_kKeyHome;                         break;
434                 case VK_INSERT:   key = GHOST_kKeyInsert;                       break;
435                 case VK_DELETE:   key = GHOST_kKeyDelete;                       break;
436                 case VK_LEFT:     key = GHOST_kKeyLeftArrow;            break;
437                 case VK_RIGHT:    key = GHOST_kKeyRightArrow;           break;
438                 case VK_UP:       key = GHOST_kKeyUpArrow;                      break;
439                 case VK_DOWN:     key = GHOST_kKeyDownArrow;            break;
440                 case VK_NUMPAD0:  key = GHOST_kKeyNumpad0;                      break;
441                 case VK_NUMPAD1:  key = GHOST_kKeyNumpad1;                      break;
442                 case VK_NUMPAD2:  key = GHOST_kKeyNumpad2;                      break;
443                 case VK_NUMPAD3:  key = GHOST_kKeyNumpad3;                      break;
444                 case VK_NUMPAD4:  key = GHOST_kKeyNumpad4;                      break;
445                 case VK_NUMPAD5:  key = GHOST_kKeyNumpad5;                      break;
446                 case VK_NUMPAD6:  key = GHOST_kKeyNumpad6;                      break;
447                 case VK_NUMPAD7:  key = GHOST_kKeyNumpad7;                      break;
448                 case VK_NUMPAD8:  key = GHOST_kKeyNumpad8;                      break;
449                 case VK_NUMPAD9:  key = GHOST_kKeyNumpad9;                      break;
450                 case VK_SNAPSHOT: key = GHOST_kKeyPrintScreen;          break;
451                 case VK_PAUSE:    key = GHOST_kKeyPause;                        break;
452                 case VK_MULTIPLY: key = GHOST_kKeyNumpadAsterisk;        break;
453                 case VK_SUBTRACT: key = GHOST_kKeyNumpadMinus;          break;
454                 case VK_DECIMAL:  key = GHOST_kKeyNumpadPeriod;         break;
455                 case VK_DIVIDE:   key = GHOST_kKeyNumpadSlash;          break;
456                 case VK_ADD:      key = GHOST_kKeyNumpadPlus;           break;
457
458                 case VK_SEMICOLON:              key = GHOST_kKeySemicolon;              break;
459                 case VK_EQUALS:                 key = GHOST_kKeyEqual;                  break;
460                 case VK_COMMA:                  key = GHOST_kKeyComma;                  break;
461                 case VK_MINUS:                  key = GHOST_kKeyMinus;                  break;
462                 case VK_PERIOD:                 key = GHOST_kKeyPeriod;                 break;
463                 case VK_SLASH:                  key = GHOST_kKeySlash;                  break;
464                 case VK_BACK_QUOTE:             key = GHOST_kKeyAccentGrave;    break;
465                 case VK_OPEN_BRACKET:   key = GHOST_kKeyLeftBracket;    break;
466                 case VK_BACK_SLASH:             key = GHOST_kKeyBackslash;              break;
467                 case VK_CLOSE_BRACKET:  key = GHOST_kKeyRightBracket;   break;
468                 case VK_QUOTE:                  key = GHOST_kKeyQuote;                  break;
469                 case VK_GR_LESS:                key = GHOST_kKeyGrLess;                 break;
470
471                 // Process these keys separately because we need to distinguish right from left modifier keys
472                 case VK_SHIFT:
473                 case VK_CONTROL:
474                 case VK_MENU:
475
476                 // Ignore these keys
477                 case VK_NUMLOCK:
478                 case VK_SCROLL:
479                 case VK_CAPITAL:
480                 default:
481                         key = GHOST_kKeyUnknown;
482                         break;
483                 }
484         }
485         return key;
486 }
487
488
489 void GHOST_SystemWin32::processModifierKeys(GHOST_IWindow *window)
490 {
491         GHOST_ModifierKeys oldModifiers, newModifiers;
492         // Retrieve old state of the modifier keys
493         ((GHOST_SystemWin32*)getSystem())->retrieveModifierKeys(oldModifiers);
494         // Retrieve current state of the modifier keys
495         ((GHOST_SystemWin32*)getSystem())->getModifierKeys(newModifiers);
496
497         // Compare the old and the new
498         if (!newModifiers.equals(oldModifiers)) {
499                 // Create events for the masks that changed
500                 for (int i = 0; i < GHOST_kModifierKeyNumMasks; i++) {
501                         if (newModifiers.get((GHOST_TModifierKeyMask)i) != oldModifiers.get((GHOST_TModifierKeyMask)i)) {
502                                 // Convert the mask to a key code
503                                 GHOST_TKey key = GHOST_ModifierKeys::getModifierKeyCode((GHOST_TModifierKeyMask)i);
504                                 bool keyDown = newModifiers.get((GHOST_TModifierKeyMask)i);
505                                 GHOST_EventKey* event;
506                                 if (key != GHOST_kKeyUnknown) {
507                                         // Create an event
508                                         event = new GHOST_EventKey(getSystem()->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown: GHOST_kEventKeyUp, window, key);
509                                         pushEvent(event);
510                                 }
511                         }
512                 }
513         }
514
515         // Store new modifier keys state
516         ((GHOST_SystemWin32*)getSystem())->storeModifierKeys(newModifiers);
517 }
518
519
520 GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask)
521 {
522         return new GHOST_EventButton (getSystem()->getMilliSeconds(), type, window, mask);
523 }
524
525
526 GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow)
527 {
528         GHOST_TInt32 x_screen, y_screen;
529         GHOST_SystemWin32 * system = ((GHOST_SystemWin32 * ) getSystem());
530         GHOST_WindowWin32 * window = ( GHOST_WindowWin32 * ) Iwindow;
531         
532         system->getCursorPosition(x_screen, y_screen);
533
534         if(window->getCursorGrabMode() != GHOST_kGrabDisable && window->getCursorGrabMode() != GHOST_kGrabNormal)
535         {
536                 GHOST_TInt32 x_new= x_screen;
537                 GHOST_TInt32 y_new= y_screen;
538                 GHOST_TInt32 x_accum, y_accum;
539                 GHOST_Rect bounds;
540
541                 /* fallback to window bounds */
542                 if(window->getCursorGrabBounds(bounds)==GHOST_kFailure){
543                         window->getClientBounds(bounds);
544                 }
545
546                 /* could also clamp to screen bounds
547                  * wrap with a window outside the view will fail atm  */
548
549                 bounds.wrapPoint(x_new, y_new, 2); /* offset of one incase blender is at screen bounds */
550
551                 window->getCursorGrabAccum(x_accum, y_accum);
552                 if(x_new != x_screen|| y_new != y_screen) {
553                         /* when wrapping we don't need to add an event because the
554                          * setCursorPosition call will cause a new event after */
555                         system->setCursorPosition(x_new, y_new); /* wrap */
556                         window->setCursorGrabAccum(x_accum + (x_screen - x_new), y_accum + (y_screen - y_new));
557                 }else{
558                         return new GHOST_EventCursor(system->getMilliSeconds(),
559                                                                                  GHOST_kEventCursorMove,
560                                                                                  window,
561                                                                                  x_screen + x_accum,
562                                                                                  y_screen + y_accum
563                         );
564                 }
565
566         }
567         else {
568                 return new GHOST_EventCursor(system->getMilliSeconds(),
569                                                                          GHOST_kEventCursorMove,
570                                                                          window,
571                                                                          x_screen,
572                                                                          y_screen
573                 );
574         }
575         return NULL;
576 }
577
578
579 GHOST_EventWheel* GHOST_SystemWin32::processWheelEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam)
580 {
581         // short fwKeys = LOWORD(wParam);                       // key flags
582         int zDelta = (short) HIWORD(wParam);    // wheel rotation
583         
584         // zDelta /= WHEEL_DELTA;
585         // temporary fix below: microsoft now has added more precision, making the above division not work
586         if (zDelta <= 0 ) zDelta= -1; else zDelta= 1;   
587         
588         // short xPos = (short) LOWORD(lParam); // horizontal position of pointer
589         // short yPos = (short) HIWORD(lParam); // vertical position of pointer
590         return new GHOST_EventWheel (getSystem()->getMilliSeconds(), window, zDelta);
591 }
592
593
594 GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, bool keyDown, WPARAM wParam, LPARAM lParam)
595 {
596         GHOST_TKey key = ((GHOST_SystemWin32*)getSystem())->convertKey(wParam, lParam);
597         GHOST_EventKey* event;
598         if (key != GHOST_kKeyUnknown) {
599                 MSG keyMsg;
600                 char ascii = '\0';
601
602                         /* Eat any character related messages */
603                 if (::PeekMessage(&keyMsg, NULL, WM_CHAR, WM_SYSDEADCHAR, PM_REMOVE)) {
604                         ascii = (char) keyMsg.wParam;
605                 }
606
607                 event = new GHOST_EventKey(getSystem()->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown: GHOST_kEventKeyUp, window, key, ascii);
608         }
609         else {
610                 event = 0;
611         }
612         return event;
613 }
614
615
616 GHOST_Event* GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window)
617 {
618         return new GHOST_Event(getSystem()->getMilliSeconds(), type, window);
619 }
620
621 GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType, 
622                                                                                                         GHOST_TDragnDropTypes draggedObjectType,
623                                                                                                         GHOST_IWindow* window,
624                                                                                                         int mouseX, int mouseY,
625                                                                                                         void* data)
626 {
627         GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem());
628         return system->pushEvent(new GHOST_EventDragnDrop(system->getMilliSeconds(),
629                                                                                                           eventType,
630                                                                                                           draggedObjectType,
631                                                                                                           window,mouseX,mouseY,data)
632                         );
633 }
634
635 void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax)
636 {
637         minmax->ptMinTrackSize.x=320;
638         minmax->ptMinTrackSize.y=240;
639 }
640
641
642 LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
643 {
644         GHOST_Event* event = 0;
645         LRESULT lResult = 0;
646         GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem());
647         GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized")
648
649         if (hwnd) {
650                 GHOST_WindowWin32* window = (GHOST_WindowWin32*)::GetWindowLong(hwnd, GWL_USERDATA);
651                 if (window) {
652                         switch (msg) {
653                                 ////////////////////////////////////////////////////////////////////////
654                                 // Keyboard events, processed
655                                 ////////////////////////////////////////////////////////////////////////
656                                 case WM_KEYDOWN:
657                                         /* The WM_KEYDOWN message is posted to the window with the keyboard focus when a 
658                                          * nonsystem key is pressed. A nonsystem key is a key that is pressed when the alt
659                                          * key is not pressed. 
660                                          */
661                                 case WM_SYSKEYDOWN:
662                                         /* The WM_SYSKEYDOWN message is posted to the window with the keyboard focus when 
663                                          * the user presses the F10 key (which activates the menu bar) or holds down the 
664                                          * alt key and then presses another key. It also occurs when no window currently 
665                                          * has the keyboard focus; in this case, the WM_SYSKEYDOWN message is sent to the 
666                                          * active window. The window that receives the message can distinguish between these 
667                                          * two contexts by checking the context code in the lKeyData parameter. 
668                                          */
669                                         switch (wParam) {
670                                                 case VK_SHIFT:
671                                                 case VK_CONTROL:
672                                                 case VK_MENU:
673                                                         if (!system->m_separateLeftRightInitialized) {
674                                                                 // Check whether this system supports separate left and right keys
675                                                                 switch (wParam) {
676                                                                         case VK_SHIFT:
677                                                                                 system->m_separateLeftRight = 
678                                                                                         (HIBYTE(::GetKeyState(VK_LSHIFT)) != 0) ||
679                                                                                         (HIBYTE(::GetKeyState(VK_RSHIFT)) != 0) ?
680                                                                                         true : false;
681                                                                                 break;
682                                                                         case VK_CONTROL:
683                                                                                 system->m_separateLeftRight = 
684                                                                                         (HIBYTE(::GetKeyState(VK_LCONTROL)) != 0) ||
685                                                                                         (HIBYTE(::GetKeyState(VK_RCONTROL)) != 0) ?
686                                                                                         true : false;
687                                                                                 break;
688                                                                         case VK_MENU:
689                                                                                 system->m_separateLeftRight = 
690                                                                                         (HIBYTE(::GetKeyState(VK_LMENU)) != 0) ||
691                                                                                         (HIBYTE(::GetKeyState(VK_RMENU)) != 0) ?
692                                                                                         true : false;
693                                                                                 break;
694                                                                 }
695                                                                 system->m_separateLeftRightInitialized = true;
696                                                         }
697                                                         system->processModifierKeys(window);
698                                                         // Bypass call to DefWindowProc
699                                                         return 0;
700                                                 default:
701                                                         event = processKeyEvent(window, true, wParam, lParam);
702                                                         if (!event) {
703                                                                 GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
704                                                                 GHOST_PRINT(msg)
705                                                                 GHOST_PRINT(" key ignored\n")
706                                                         }
707                                                         break;
708                                                 }
709                                         break;
710
711                                 case WM_KEYUP:
712                                 case WM_SYSKEYUP:
713                                         switch (wParam) {
714                                                 case VK_SHIFT:
715                                                 case VK_CONTROL:
716                                                 case VK_MENU:
717                                                         system->processModifierKeys(window);
718                                                         // Bypass call to DefWindowProc
719                                                         return 0;
720                                                 default:
721                                                         event = processKeyEvent(window, false, wParam, lParam);
722                                                         if (!event) {
723                                                                 GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
724                                                                 GHOST_PRINT(msg)
725                                                                 GHOST_PRINT(" key ignored\n")
726                                                         }
727                                                         break;
728                                         }
729                                         break;
730
731                                 ////////////////////////////////////////////////////////////////////////
732                                 // Keyboard events, ignored
733                                 ////////////////////////////////////////////////////////////////////////
734                                 case WM_CHAR:
735                                         /* The WM_CHAR message is posted to the window with the keyboard focus when 
736                                          * a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR 
737                                          * contains the character code of the key that was pressed. 
738                                          */
739                                 case WM_DEADCHAR:
740                                         /* The WM_DEADCHAR message is posted to the window with the keyboard focus when a
741                                          * WM_KEYUP message is translated by the TranslateMessage function. WM_DEADCHAR 
742                                          * specifies a character code generated by a dead key. A dead key is a key that 
743                                          * generates a character, such as the umlaut (double-dot), that is combined with 
744                                          * another character to form a composite character. For example, the umlaut-O 
745                                          * character (Ù) is generated by typing the dead key for the umlaut character, and 
746                                          * then typing the O key.
747                                          */
748                                 case WM_SYSDEADCHAR:
749                                         /* The WM_SYSDEADCHAR message is sent to the window with the keyboard focus when 
750                                          * a WM_SYSKEYDOWN message is translated by the TranslateMessage function. 
751                                          * WM_SYSDEADCHAR specifies the character code of a system dead key - that is, 
752                                          * a dead key that is pressed while holding down the alt key. 
753                                          */
754                                         break;
755                                 ////////////////////////////////////////////////////////////////////////
756                                 // Tablet events, processed
757                                 ////////////////////////////////////////////////////////////////////////
758                                 case WT_PACKET:
759                                         ((GHOST_WindowWin32*)window)->processWin32TabletEvent(wParam, lParam);
760                                         break;
761                                 case WT_CSRCHANGE:
762                                 case WT_PROXIMITY:
763                                         ((GHOST_WindowWin32*)window)->processWin32TabletInitEvent();
764                                         break;
765                                 ////////////////////////////////////////////////////////////////////////
766                                 // Mouse events, processed
767                                 ////////////////////////////////////////////////////////////////////////
768                                 case WM_LBUTTONDOWN:
769                                         window->registerMouseClickEvent(true);
770                                         event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskLeft);
771                                         break;
772                                 case WM_MBUTTONDOWN:
773                                         window->registerMouseClickEvent(true);
774                                         event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskMiddle);
775                                         break;
776                                 case WM_RBUTTONDOWN:
777                                         window->registerMouseClickEvent(true);
778                                         event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskRight);
779                                         break;
780                                 case WM_XBUTTONDOWN:
781                                         window->registerMouseClickEvent(true);
782                                         if ((short) HIWORD(wParam) == XBUTTON1){
783                                                 event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton4);
784                                         }else if((short) HIWORD(wParam) == XBUTTON2){
785                                                 event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton5);
786                                         }
787                                         break;
788                                 case WM_LBUTTONUP:
789                                         window->registerMouseClickEvent(false);
790                                         event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft);
791                                         break;
792                                 case WM_MBUTTONUP:
793                                         window->registerMouseClickEvent(false);
794                                         event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskMiddle);
795                                         break;
796                                 case WM_RBUTTONUP:
797                                         window->registerMouseClickEvent(false);
798                                         event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskRight);
799                                         break;
800                                 case WM_XBUTTONUP:
801                                         window->registerMouseClickEvent(false);
802                                         if ((short) HIWORD(wParam) == XBUTTON1){
803                                                 event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton4);
804                                         }else if((short) HIWORD(wParam) == XBUTTON2){
805                                                 event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton5);
806                                         }
807                                         break;
808                                 case WM_MOUSEMOVE:
809                                         event = processCursorEvent(GHOST_kEventCursorMove, window);
810                                         break;
811                                 case WM_MOUSEWHEEL:
812                                         /* The WM_MOUSEWHEEL message is sent to the focus window 
813                                          * when the mouse wheel is rotated. The DefWindowProc 
814                                          * function propagates the message to the window's parent.
815                                          * There should be no internal forwarding of the message, 
816                                          * since DefWindowProc propagates it up the parent chain 
817                                          * until it finds a window that processes it.
818                                          */
819                                         event = processWheelEvent(window, wParam, lParam);
820                                         break;
821                                 case WM_SETCURSOR:
822                                         /* The WM_SETCURSOR message is sent to a window if the mouse causes the cursor
823                                          * to move within a window and mouse input is not captured.
824                                          * This means we have to set the cursor shape every time the mouse moves!
825                                          * The DefWindowProc function uses this message to set the cursor to an 
826                                          * arrow if it is not in the client area.
827                                          */
828                                         if (LOWORD(lParam) == HTCLIENT) {
829                                                 // Load the current cursor
830                                                 window->loadCursor(window->getCursorVisibility(), window->getCursorShape());
831                                                 // Bypass call to DefWindowProc
832                                                 return 0;
833                                         } 
834                                         else {
835                                                 // Outside of client area show standard cursor
836                                                 window->loadCursor(true, GHOST_kStandardCursorDefault);
837                                         }
838                                         break;
839
840                                 ////////////////////////////////////////////////////////////////////////
841                                 // Mouse events, ignored
842                                 ////////////////////////////////////////////////////////////////////////
843                                 case WM_NCMOUSEMOVE:
844                                         /* The WM_NCMOUSEMOVE message is posted to a window when the cursor is moved 
845                                          * within the nonclient area of the window. This message is posted to the window 
846                                          * that contains the cursor. If a window has captured the mouse, this message is not posted.
847                                          */
848                                 case WM_NCHITTEST:
849                                         /* The WM_NCHITTEST message is sent to a window when the cursor moves, or 
850                                          * when a mouse button is pressed or released. If the mouse is not captured, 
851                                          * the message is sent to the window beneath the cursor. Otherwise, the message 
852                                          * is sent to the window that has captured the mouse. 
853                                          */
854                                         break;
855
856                                 ////////////////////////////////////////////////////////////////////////
857                                 // Window events, processed
858                                 ////////////////////////////////////////////////////////////////////////
859                                 case WM_CLOSE:
860                                         /* The WM_CLOSE message is sent as a signal that a window or an application should terminate. */
861                                         event = processWindowEvent(GHOST_kEventWindowClose, window);
862                                         break;
863                                 case WM_ACTIVATE:
864                                         /* The WM_ACTIVATE message is sent to both the window being activated and the window being 
865                                          * deactivated. If the windows use the same input queue, the message is sent synchronously, 
866                                          * first to the window procedure of the top-level window being deactivated, then to the window
867                                          * procedure of the top-level window being activated. If the windows use different input queues,
868                                          * the message is sent asynchronously, so the window is activated immediately. 
869                                          */
870                                         event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window);
871                                         /* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL
872                                         will not be dispatched to OUR active window if we minimize one of OUR windows. */
873                                         lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
874                                         break;
875                                 case WM_PAINT:
876                                         /* An application sends the WM_PAINT message when the system or another application 
877                                          * makes a request to paint a portion of an application's window. The message is sent
878                                          * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage 
879                                          * function when the application obtains a WM_PAINT message by using the GetMessage or 
880                                          * PeekMessage function. 
881                                          */
882                                         event = processWindowEvent(GHOST_kEventWindowUpdate, window);
883                                         ::ValidateRect(hwnd, NULL);
884                                         break;
885                                 case WM_GETMINMAXINFO:
886                                         /* The WM_GETMINMAXINFO message is sent to a window when the size or 
887                                          * position of the window is about to change. An application can use 
888                                          * this message to override the window's default maximized size and 
889                                          * position, or its default minimum or maximum tracking size. 
890                                          */
891                                         processMinMaxInfo((MINMAXINFO *) lParam);
892                                         /* Let DefWindowProc handle it. */
893                                         break;
894                                 case WM_SIZE:
895                                         /* The WM_SIZE message is sent to a window after its size has changed.
896                                          * The WM_SIZE and WM_MOVE messages are not sent if an application handles the 
897                                          * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
898                                          * to perform any move or size change processing during the WM_WINDOWPOSCHANGED 
899                                          * message without calling DefWindowProc.
900                                          */
901                                         event = processWindowEvent(GHOST_kEventWindowSize, window);
902                                         break;
903                                 case WM_CAPTURECHANGED:
904                                         window->lostMouseCapture();
905                                         break;
906                                 case WM_MOVING:
907                                         /* The WM_MOVING message is sent to a window that the user is moving. By processing 
908                                          * this message, an application can monitor the size and position of the drag rectangle
909                                          * and, if needed, change its size or position.
910                                          */
911                                 case WM_MOVE:
912                                         /* The WM_SIZE and WM_MOVE messages are not sent if an application handles the 
913                                          * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
914                                          * to perform any move or size change processing during the WM_WINDOWPOSCHANGED 
915                                          * message without calling DefWindowProc. 
916                                          */
917                                         event = processWindowEvent(GHOST_kEventWindowMove, window);
918                                         break;
919                                 ////////////////////////////////////////////////////////////////////////
920                                 // Window events, ignored
921                                 ////////////////////////////////////////////////////////////////////////
922                                 case WM_WINDOWPOSCHANGED:
923                                         /* The WM_WINDOWPOSCHANGED message is sent to a window whose size, position, or place
924                                          * in the Z order has changed as a result of a call to the SetWindowPos function or 
925                                          * another window-management function.
926                                          * The WM_SIZE and WM_MOVE messages are not sent if an application handles the 
927                                          * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
928                                          * to perform any move or size change processing during the WM_WINDOWPOSCHANGED 
929                                          * message without calling DefWindowProc.
930                                          */
931                                 case WM_ERASEBKGND:
932                                         /* An application sends the WM_ERASEBKGND message when the window background must be 
933                                          * erased (for example, when a window is resized). The message is sent to prepare an 
934                                          * invalidated portion of a window for painting. 
935                                          */
936                                 case WM_NCPAINT:
937                                         /* An application sends the WM_NCPAINT message to a window when its frame must be painted. */
938                                 case WM_NCACTIVATE:
939                                         /* The WM_NCACTIVATE message is sent to a window when its nonclient area needs to be changed 
940                                          * to indicate an active or inactive state. 
941                                          */
942                                 case WM_DESTROY:
943                                         /* The WM_DESTROY message is sent when a window is being destroyed. It is sent to the window 
944                                          * procedure of the window being destroyed after the window is removed from the screen. 
945                                          * This message is sent first to the window being destroyed and then to the child windows 
946                                          * (if any) as they are destroyed. During the processing of the message, it can be assumed 
947                                          * that all child windows still exist. 
948                                          */
949                                 case WM_NCDESTROY:
950                                         /* The WM_NCDESTROY message informs a window that its nonclient area is being destroyed. The 
951                                          * DestroyWindow function sends the WM_NCDESTROY message to the window following the WM_DESTROY
952                                          * message. WM_DESTROY is used to free the allocated memory object associated with the window. 
953                                          */
954                                 case WM_KILLFOCUS:
955                                         /* The WM_KILLFOCUS message is sent to a window immediately before it loses the keyboard focus. */
956                                 case WM_SHOWWINDOW:
957                                         /* The WM_SHOWWINDOW message is sent to a window when the window is about to be hidden or shown. */
958                                 case WM_WINDOWPOSCHANGING:
959                                         /* The WM_WINDOWPOSCHANGING message is sent to a window whose size, position, or place in 
960                                          * the Z order is about to change as a result of a call to the SetWindowPos function or 
961                                          * another window-management function. 
962                                          */
963                                 case WM_SETFOCUS:
964                                         /* The WM_SETFOCUS message is sent to a window after it has gained the keyboard focus. */
965                                 case WM_ENTERSIZEMOVE:
966                                         /* The WM_ENTERSIZEMOVE message is sent one time to a window after it enters the moving 
967                                          * or sizing modal loop. The window enters the moving or sizing modal loop when the user 
968                                          * clicks the window's title bar or sizing border, or when the window passes the 
969                                          * WM_SYSCOMMAND message to the DefWindowProc function and the wParam parameter of the 
970                                          * message specifies the SC_MOVE or SC_SIZE value. The operation is complete when 
971                                          * DefWindowProc returns. 
972                                          */
973                                         break;
974                                         
975                                 ////////////////////////////////////////////////////////////////////////
976                                 // Other events
977                                 ////////////////////////////////////////////////////////////////////////
978                                 case WM_GETTEXT:
979                                         /* An application sends a WM_GETTEXT message to copy the text that 
980                                          * corresponds to a window into a buffer provided by the caller. 
981                                          */
982                                 case WM_ACTIVATEAPP:
983                                         /* The WM_ACTIVATEAPP message is sent when a window belonging to a 
984                                          * different application than the active window is about to be activated.
985                                          * The message is sent to the application whose window is being activated
986                                          * and to the application whose window is being deactivated. 
987                                          */
988                                 case WM_TIMER:
989                                         /* The WIN32 docs say:
990                                          * The WM_TIMER message is posted to the installing thread's message queue
991                                          * when a timer expires. You can process the message by providing a WM_TIMER
992                                          * case in the window procedure. Otherwise, the default window procedure will
993                                          * call the TimerProc callback function specified in the call to the SetTimer
994                                          * function used to install the timer. 
995                                          *
996                                          * In GHOST, we let DefWindowProc call the timer callback.
997                                          */
998                                         break;
999                                 case WM_BLND_NDOF_AXIS:
1000                                         {
1001                                                 GHOST_TEventNDOFData ndofdata;
1002                                                 system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata);
1003                                                 system->m_eventManager->
1004                                                         pushEvent(new GHOST_EventNDOF(
1005                                                                 system->getMilliSeconds(), 
1006                                                                 GHOST_kEventNDOFMotion, 
1007                                                                 window, ndofdata));
1008                                         }
1009                                         break;
1010                                 case WM_BLND_NDOF_BTN:
1011                                         {
1012                                                 GHOST_TEventNDOFData ndofdata;
1013                                                 system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata);
1014                                                 system->m_eventManager->
1015                                                         pushEvent(new GHOST_EventNDOF(
1016                                                                 system->getMilliSeconds(), 
1017                                                                 GHOST_kEventNDOFButton, 
1018                                                                 window, ndofdata));
1019                                         }
1020                                         break;
1021                         }
1022                 }
1023                 else {
1024                         // Event found for a window before the pointer to the class has been set.
1025                         GHOST_PRINT("GHOST_SystemWin32::wndProc: GHOST window event before creation\n")
1026                         /* These are events we typically miss at this point:
1027                            WM_GETMINMAXINFO     0x24
1028                            WM_NCCREATE                  0x81
1029                            WM_NCCALCSIZE                0x83
1030                            WM_CREATE                    0x01
1031                            We let DefWindowProc do the work.
1032                         */
1033                 }
1034         }
1035         else {
1036                 // Events without valid hwnd
1037                 GHOST_PRINT("GHOST_SystemWin32::wndProc: event without window\n")
1038         }
1039
1040         if (event) {
1041                 system->pushEvent(event);
1042         }
1043         else {
1044                 lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
1045         }
1046         return lResult;
1047 }
1048
1049 GHOST_TUns8* GHOST_SystemWin32::getClipboard(bool selection) const 
1050 {
1051         char *buffer;
1052         char *temp_buff;
1053         
1054         if ( IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL) ) {
1055                 HANDLE hData = GetClipboardData( CF_TEXT );
1056                 if (hData == NULL) {
1057                         CloseClipboard();
1058                         return NULL;
1059                 }
1060                 buffer = (char*)GlobalLock( hData );
1061                 
1062                 temp_buff = (char*) malloc(strlen(buffer)+1);
1063                 strcpy(temp_buff, buffer);
1064                 
1065                 GlobalUnlock( hData );
1066                 CloseClipboard();
1067                 
1068                 temp_buff[strlen(buffer)] = '\0';
1069                 if (buffer) {
1070                         return (GHOST_TUns8*)temp_buff;
1071                 } else {
1072                         return NULL;
1073                 }
1074         } else {
1075                 return NULL;
1076         }
1077 }
1078
1079 void GHOST_SystemWin32::putClipboard(GHOST_TInt8 *buffer, bool selection) const
1080 {
1081         if(selection) {return;} // for copying the selection, used on X11
1082
1083         if (OpenClipboard(NULL)) {
1084                 HLOCAL clipbuffer;
1085                 char *data;
1086                 
1087                 if (buffer) {
1088                         EmptyClipboard();
1089                         
1090                         clipbuffer = LocalAlloc(LMEM_FIXED,((strlen(buffer)+1)));
1091                         data = (char*)GlobalLock(clipbuffer);
1092
1093                         strcpy(data, (char*)buffer);
1094                         data[strlen(buffer)] = '\0';
1095                         LocalUnlock(clipbuffer);
1096                         SetClipboardData(CF_TEXT,clipbuffer);
1097                 }
1098                 CloseClipboard();
1099         } else {
1100                 return;
1101         }
1102 }
1103
1104 const GHOST_TUns8* GHOST_SystemWin32::getSystemDir() const
1105 {
1106         static char knownpath[MAX_PATH];
1107         HRESULT hResult = SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, knownpath);
1108
1109         if (hResult == S_OK)
1110         {
1111                 return (GHOST_TUns8*)knownpath;
1112         }
1113
1114         return NULL;
1115 }
1116
1117 const GHOST_TUns8* GHOST_SystemWin32::getUserDir() const
1118 {
1119         static char knownpath[MAX_PATH];
1120         HRESULT hResult = SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, knownpath);
1121
1122         if (hResult == S_OK)
1123         {
1124                 return (GHOST_TUns8*)knownpath;
1125         }
1126
1127         return NULL;
1128 }
1129
1130 const GHOST_TUns8* GHOST_SystemWin32::getBinaryDir() const
1131 {
1132         static char fullname[MAX_PATH];
1133         if(GetModuleFileName(0, fullname, MAX_PATH)) {
1134                 return (GHOST_TUns8*)fullname;
1135         }
1136
1137         return NULL;
1138 }