revert (ifdef) r54745. which enbabled alpha in the GL buffer.
[blender.git] / intern / ghost / intern / GHOST_WindowWin32.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Maarten Gribnau.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file ghost/intern/GHOST_WindowWin32.cpp
29  *  \ingroup GHOST
30  */
31
32 #include <string.h>
33 #include "GHOST_WindowWin32.h"
34 #include "GHOST_SystemWin32.h"
35 #include "GHOST_DropTargetWin32.h"
36 #include "utfconv.h"
37 #include "utf_winfunc.h"
38
39 // Need glew for some defines
40 #include <GL/glew.h>
41 #include <GL/wglew.h>
42 #include <math.h>
43
44 // MSVC6 still doesn't define M_PI
45 #ifndef M_PI
46 #  define M_PI 3.1415926536
47 #endif
48
49 // Some more multisample defines
50 #define WGL_SAMPLE_BUFFERS_ARB  0x2041
51 #define WGL_SAMPLES_ARB         0x2042
52
53 const wchar_t *GHOST_WindowWin32::s_windowClassName = L"GHOST_WindowClass";
54 const int GHOST_WindowWin32::s_maxTitleLength = 128;
55 HGLRC GHOST_WindowWin32::s_firsthGLRc = NULL;
56 HDC GHOST_WindowWin32::s_firstHDC = NULL;
57
58 static int WeightPixelFormat(PIXELFORMATDESCRIPTOR& pfd);
59 static int EnumPixelFormats(HDC hdc);
60
61 /*
62  * Color and depth bit values are not to be trusted.
63  * For instance, on TNT2:
64  * When the screen color depth is set to 16 bit, we get 5 color bits
65  * and 16 depth bits.
66  * When the screen color depth is set to 32 bit, we get 8 color bits
67  * and 24 depth bits.
68  * Just to be safe, we request high waulity settings.
69  */
70 static PIXELFORMATDESCRIPTOR sPreferredFormat = {
71         sizeof(PIXELFORMATDESCRIPTOR),  /* size */
72         1,                              /* version */
73         PFD_SUPPORT_OPENGL |
74         PFD_DRAW_TO_WINDOW |
75         PFD_SWAP_COPY |                 /* support swap copy */
76         PFD_DOUBLEBUFFER,               /* support double-buffering */
77         PFD_TYPE_RGBA,                  /* color type */
78         32,                             /* prefered color depth */
79         0, 0, 0, 0, 0, 0,               /* color bits (ignored) */
80         0,                              /* no alpha buffer */
81         0,                              /* alpha bits (ignored) */
82         0,                              /* no accumulation buffer */
83         0, 0, 0, 0,                     /* accum bits (ignored) */
84         32,                             /* depth buffer */
85         0,                              /* no stencil buffer */
86         0,                              /* no auxiliary buffers */
87         PFD_MAIN_PLANE,                 /* main layer */
88         0,                              /* reserved */
89         0, 0, 0                         /* no layer, visible, damage masks */
90 };
91
92 /* Intel videocards don't work fine with multiple contexts and
93  * have to share the same context for all windows.
94  * But if we just share context for all windows it could work incorrect
95  * with multiple videocards configuration. Suppose, that Intel videocards
96  * can't be in multiple-devices configuration. */
97 static int is_crappy_intel_card(void)
98 {
99         static short is_crappy = -1;
100
101         if (is_crappy == -1) {
102                 const char *vendor = (const char *)glGetString(GL_VENDOR);
103                 is_crappy = (strstr(vendor, "Intel") != NULL);
104         }
105
106         return is_crappy;
107 }
108
109 GHOST_WindowWin32::GHOST_WindowWin32(
110     GHOST_SystemWin32 *system,
111     const STR_String& title,
112     GHOST_TInt32 left,
113     GHOST_TInt32 top,
114     GHOST_TUns32 width,
115     GHOST_TUns32 height,
116     GHOST_TWindowState state,
117     GHOST_TDrawingContextType type,
118     const bool stereoVisual,
119     const GHOST_TUns16 numOfAASamples,
120     GHOST_TEmbedderWindowID parentwindowhwnd,
121     GHOST_TSuccess msEnabled,
122     int msPixelFormat)
123         :
124         GHOST_Window(width, height, state, GHOST_kDrawingContextTypeNone,
125                      stereoVisual, false, numOfAASamples),
126         m_system(system),
127         m_hDC(0),
128         m_hGlRc(0),
129         m_hasMouseCaptured(false),
130         m_hasGrabMouse(false),
131         m_nPressedButtons(0),
132         m_customCursor(0),
133         m_wintab(NULL),
134         m_tabletData(NULL),
135         m_tablet(0),
136         m_maxPressure(0),
137         m_multisample(numOfAASamples),
138         m_multisampleEnabled(msEnabled),
139         m_msPixelFormat(msPixelFormat),
140         //For recreation
141         m_title(title),
142         m_left(left),
143         m_top(top),
144         m_width(width),
145         m_height(height),
146         m_normal_state(GHOST_kWindowStateNormal),
147         m_stereo(stereoVisual),
148         m_nextWindow(NULL),
149         m_parentWindowHwnd(parentwindowhwnd)
150 {
151         OSVERSIONINFOEX versionInfo;
152         bool hasMinVersionForTaskbar = false;
153         
154         ZeroMemory(&versionInfo, sizeof(OSVERSIONINFOEX));
155         
156         versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
157         
158         if (!GetVersionEx((OSVERSIONINFO *)&versionInfo)) {
159                 versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
160                 if (GetVersionEx((OSVERSIONINFO *)&versionInfo)) {
161                         if ((versionInfo.dwMajorVersion == 6 && versionInfo.dwMinorVersion >= 1) || versionInfo.dwMajorVersion >= 7) {
162                                 hasMinVersionForTaskbar = true;
163                         }
164                 }
165         }
166         else {
167                 if ((versionInfo.dwMajorVersion == 6 && versionInfo.dwMinorVersion >= 1) || versionInfo.dwMajorVersion >= 7) {
168                         hasMinVersionForTaskbar = true;
169                 }
170         }
171
172         if (state != GHOST_kWindowStateFullScreen) {
173                 RECT rect;
174                 MONITORINFO monitor;
175                 GHOST_TUns32 tw, th; 
176
177                 width += GetSystemMetrics(SM_CXSIZEFRAME) * 2;
178                 height += GetSystemMetrics(SM_CYSIZEFRAME) * 2 + GetSystemMetrics(SM_CYCAPTION);
179
180                 rect.left = left;
181                 rect.right = left + width;
182                 rect.top = top;
183                 rect.bottom = top + height;
184
185                 monitor.cbSize = sizeof(monitor);
186                 monitor.dwFlags = 0;
187
188                 // take taskbar into account
189                 GetMonitorInfo(MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST), &monitor);
190
191                 th = monitor.rcWork.bottom - monitor.rcWork.top;
192                 tw = monitor.rcWork.right - monitor.rcWork.left;
193
194                 if (tw < width)
195                 {
196                         width = tw;
197                         left = monitor.rcWork.left;
198                 }
199                 else if (monitor.rcWork.right < left + (int)width)
200                         left = monitor.rcWork.right - width;
201                 else if (left < monitor.rcWork.left)
202                         left = monitor.rcWork.left;
203
204                 if (th < height)
205                 {
206                         height = th;
207                         top = monitor.rcWork.top;
208                 }
209                 else if (monitor.rcWork.bottom < top + (int)height)
210                         top = monitor.rcWork.bottom - height;
211                 else if (top < monitor.rcWork.top)
212                         top = monitor.rcWork.top;
213
214                 int wintype = WS_OVERLAPPEDWINDOW;
215                 if (m_parentWindowHwnd != 0)
216                 {
217                         wintype = WS_CHILD;
218                         GetWindowRect((HWND)m_parentWindowHwnd, &rect);
219                         left = 0;
220                         top = 0;
221                         width = rect.right - rect.left;
222                         height = rect.bottom - rect.top;
223                 }
224                 
225                 wchar_t *title_16 = alloc_utf16_from_8((char *)(const char *)title, 0);
226                 m_hWnd = ::CreateWindowW(
227                     s_windowClassName,          // pointer to registered class name
228                     title_16,                   // pointer to window name
229                     wintype,                    // window style
230                     left,                       // horizontal position of window
231                     top,                        // vertical position of window
232                     width,                      // window width
233                     height,                     // window height
234                     (HWND) m_parentWindowHwnd,  // handle to parent or owner window
235                     0,                          // handle to menu or child-window identifier
236                     ::GetModuleHandle(0),       // handle to application instance
237                     0);                         // pointer to window-creation data
238                 free(title_16);
239         }
240         else {
241                 wchar_t *title_16 = alloc_utf16_from_8((char *)(const char *)title, 0);
242                 m_hWnd = ::CreateWindowW(
243                     s_windowClassName,          // pointer to registered class name
244                     title_16,                   // pointer to window name
245                     WS_POPUP | WS_MAXIMIZE,     // window style
246                     left,                       // horizontal position of window
247                     top,                        // vertical position of window
248                     width,                      // window width
249                     height,                     // window height
250                     HWND_DESKTOP,               // handle to parent or owner window
251                     0,                          // handle to menu or child-window identifier
252                     ::GetModuleHandle(0),       // handle to application instance
253                     0);                         // pointer to window-creation data
254                 free(title_16);
255         }
256         if (m_hWnd) {
257                 // Register this window as a droptarget. Requires m_hWnd to be valid.
258                 // Note that OleInitialize(0) has to be called prior to this. Done in GHOST_SystemWin32.
259                 m_dropTarget = new GHOST_DropTargetWin32(this, m_system);
260                 if (m_dropTarget) {
261                         ::RegisterDragDrop(m_hWnd, m_dropTarget);
262                 }
263
264                 // Store a pointer to this class in the window structure
265                 ::SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG_PTR) this);
266
267                 m_wsh.setHWND(m_hWnd);
268                 m_wsh.setMinSize(320, 240);
269
270                 // Store the device context
271                 m_hDC = ::GetDC(m_hWnd);
272
273                 if (!s_firstHDC) {
274                         s_firstHDC = m_hDC;
275                 }
276
277                 // Show the window
278                 int nCmdShow;
279                 switch (state) {
280                         case GHOST_kWindowStateMaximized:
281                                 nCmdShow = SW_SHOWMAXIMIZED;
282                                 break;
283                         case GHOST_kWindowStateMinimized:
284                                 nCmdShow = SW_SHOWMINIMIZED;
285                                 break;
286                         case GHOST_kWindowStateNormal:
287                         default:
288                                 nCmdShow = SW_SHOWNORMAL;
289                                 break;
290                 }
291                 GHOST_TSuccess success;
292                 success = setDrawingContextType(type);
293
294                 if (success)
295                 {
296                         ::ShowWindow(m_hWnd, nCmdShow);
297                         // Force an initial paint of the window
298                         ::UpdateWindow(m_hWnd);
299                 }
300                 else {
301                         //invalidate the window
302                         m_hWnd = 0;
303                 }
304         }
305
306         if (parentwindowhwnd != 0) {
307                 RAWINPUTDEVICE device = {0};
308                 device.usUsagePage  = 0x01; /* usUsagePage & usUsage for keyboard*/
309                 device.usUsage      = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */
310                 device.dwFlags |= RIDEV_INPUTSINK; // makes WM_INPUT is visible for ghost when has parent window
311                 device.hwndTarget = m_hWnd;
312                 RegisterRawInputDevices(&device, 1, sizeof(device));
313         }
314
315         m_wintab = ::LoadLibrary("Wintab32.dll");
316         if (m_wintab) {
317                 GHOST_WIN32_WTInfo fpWTInfo = (GHOST_WIN32_WTInfo) ::GetProcAddress(m_wintab, "WTInfoA");
318                 GHOST_WIN32_WTOpen fpWTOpen = (GHOST_WIN32_WTOpen) ::GetProcAddress(m_wintab, "WTOpenA");
319
320                 // let's see if we can initialize tablet here
321                 /* check if WinTab available. */
322                 if (fpWTInfo && fpWTInfo(0, 0, NULL)) {
323                         // Now init the tablet
324                         LOGCONTEXT lc;
325                         AXIS TabletX, TabletY, Pressure, Orientation[3]; /* The maximum tablet size, pressure and orientation (tilt) */
326
327                         // Open a Wintab context
328
329                         // Get default context information
330                         fpWTInfo(WTI_DEFCONTEXT, 0, &lc);
331
332                         // Open the context
333                         lc.lcPktData = PACKETDATA;
334                         lc.lcPktMode = PACKETMODE;
335                         lc.lcOptions |= CXO_MESSAGES | CXO_SYSTEM;
336
337                         /* Set the entire tablet as active */
338                         fpWTInfo(WTI_DEVICES, DVC_X, &TabletX);
339                         fpWTInfo(WTI_DEVICES, DVC_Y, &TabletY);
340
341                         /* get the max pressure, to divide into a float */
342                         BOOL pressureSupport = fpWTInfo(WTI_DEVICES, DVC_NPRESSURE, &Pressure);
343                         if (pressureSupport)
344                                 m_maxPressure = Pressure.axMax;
345                         else
346                                 m_maxPressure = 0;
347
348                         /* get the max tilt axes, to divide into floats */
349                         BOOL tiltSupport = fpWTInfo(WTI_DEVICES, DVC_ORIENTATION, &Orientation);
350                         if (tiltSupport) {
351                                 /* does the tablet support azimuth ([0]) and altitude ([1]) */
352                                 if (Orientation[0].axResolution && Orientation[1].axResolution) {
353                                         /* all this assumes the minimum is 0 */
354                                         m_maxAzimuth = Orientation[0].axMax;
355                                         m_maxAltitude = Orientation[1].axMax;
356                                 }
357                                 else {  /* no so dont do tilt stuff */
358                                         m_maxAzimuth = m_maxAltitude = 0;
359                                 }
360                         }
361
362                         if (fpWTOpen) {
363                                 m_tablet = fpWTOpen(m_hWnd, &lc, TRUE);
364                                 if (m_tablet) {
365                                         m_tabletData = new GHOST_TabletData();
366                                         m_tabletData->Active = GHOST_kTabletModeNone;
367                                 }
368                         }
369                 }
370         }
371
372         if (hasMinVersionForTaskbar)
373                 CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList, (LPVOID *)&m_Bar);
374         else
375                 m_Bar = NULL;
376 }
377
378
379 GHOST_WindowWin32::~GHOST_WindowWin32()
380 {
381         if (m_Bar)
382         {
383                 m_Bar->SetProgressState(m_hWnd, TBPF_NOPROGRESS);
384                 m_Bar->Release();
385         };
386
387         if (m_wintab) {
388                 GHOST_WIN32_WTClose fpWTClose = (GHOST_WIN32_WTClose) ::GetProcAddress(m_wintab, "WTClose");
389                 if (fpWTClose) {
390                         if (m_tablet)
391                                 fpWTClose(m_tablet);
392                         if (m_tabletData)
393                                 delete m_tabletData;
394                         m_tabletData = NULL;
395                 }
396         }
397         if (m_customCursor) {
398                 DestroyCursor(m_customCursor);
399                 m_customCursor = NULL;
400         }
401
402         ::wglMakeCurrent(NULL, NULL);
403         m_multisampleEnabled = GHOST_kFailure;
404         m_multisample = 0;
405         setDrawingContextType(GHOST_kDrawingContextTypeNone);
406         if (m_hDC && m_hDC != s_firstHDC) {
407                 ::ReleaseDC(m_hWnd, m_hDC);
408                 m_hDC = 0;
409         }
410         if (m_hWnd) {
411                 if (m_dropTarget) {
412                         // Disable DragDrop
413                         RevokeDragDrop(m_hWnd);
414                         // Release our reference of the DropTarget and it will delete itself eventually.
415                         m_dropTarget->Release();
416                 }
417
418                 ::DestroyWindow(m_hWnd);
419                 m_hWnd = 0;
420         }
421 }
422
423 GHOST_Window *GHOST_WindowWin32::getNextWindow()
424 {
425         return m_nextWindow;
426 }
427
428 bool GHOST_WindowWin32::getValid() const
429 {
430         return m_hWnd != 0;
431 }
432
433 HWND GHOST_WindowWin32::getHWND() const
434 {
435         return m_hWnd;
436 }
437
438 void GHOST_WindowWin32::setTitle(const STR_String& title)
439 {
440         wchar_t *title_16 = alloc_utf16_from_8((char *)(const char *)title, 0);
441         ::SetWindowTextW(m_hWnd, (wchar_t *)title_16);
442         free(title_16);
443 }
444
445
446 void GHOST_WindowWin32::getTitle(STR_String& title) const
447 {
448         char buf[s_maxTitleLength]; /*CHANGE + never used yet*/
449         ::GetWindowText(m_hWnd, buf, s_maxTitleLength);
450         STR_String temp(buf);
451         title = buf;
452 }
453
454
455 void GHOST_WindowWin32::getWindowBounds(GHOST_Rect& bounds) const
456 {
457         RECT rect;
458         ::GetWindowRect(m_hWnd, &rect);
459         bounds.m_b = rect.bottom;
460         bounds.m_l = rect.left;
461         bounds.m_r = rect.right;
462         bounds.m_t = rect.top;
463 }
464
465
466 void GHOST_WindowWin32::getClientBounds(GHOST_Rect& bounds) const
467 {
468         RECT rect;
469         POINT coord;
470         ::GetClientRect(m_hWnd, &rect);
471
472         coord.x = rect.left;
473         coord.y = rect.top;
474         ::ClientToScreen(m_hWnd, &coord);
475
476         bounds.m_l = coord.x;
477         bounds.m_t = coord.y;
478
479         coord.x = rect.right;
480         coord.y = rect.bottom;
481         ::ClientToScreen(m_hWnd, &coord);
482
483         bounds.m_r = coord.x;
484         bounds.m_b = coord.y;
485 }
486
487
488 GHOST_TSuccess GHOST_WindowWin32::setClientWidth(GHOST_TUns32 width)
489 {
490         GHOST_TSuccess success;
491         GHOST_Rect cBnds, wBnds;
492         getClientBounds(cBnds);
493         if (cBnds.getWidth() != (GHOST_TInt32)width) {
494                 getWindowBounds(wBnds);
495                 int cx = wBnds.getWidth() + width - cBnds.getWidth();
496                 int cy = wBnds.getHeight();
497                 success =  ::SetWindowPos(m_hWnd, HWND_TOP, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER) ?
498                           GHOST_kSuccess : GHOST_kFailure;
499         }
500         else {
501                 success = GHOST_kSuccess;
502         }
503         return success;
504 }
505
506
507 GHOST_TSuccess GHOST_WindowWin32::setClientHeight(GHOST_TUns32 height)
508 {
509         GHOST_TSuccess success;
510         GHOST_Rect cBnds, wBnds;
511         getClientBounds(cBnds);
512         if (cBnds.getHeight() != (GHOST_TInt32)height) {
513                 getWindowBounds(wBnds);
514                 int cx = wBnds.getWidth();
515                 int cy = wBnds.getHeight() + height - cBnds.getHeight();
516                 success = ::SetWindowPos(m_hWnd, HWND_TOP, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER) ?
517                           GHOST_kSuccess : GHOST_kFailure;
518         }
519         else {
520                 success = GHOST_kSuccess;
521         }
522         return success;
523 }
524
525
526 GHOST_TSuccess GHOST_WindowWin32::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height)
527 {
528         GHOST_TSuccess success;
529         GHOST_Rect cBnds, wBnds;
530         getClientBounds(cBnds);
531         if ((cBnds.getWidth() != (GHOST_TInt32)width) || (cBnds.getHeight() != (GHOST_TInt32)height)) {
532                 getWindowBounds(wBnds);
533                 int cx = wBnds.getWidth() + width - cBnds.getWidth();
534                 int cy = wBnds.getHeight() + height - cBnds.getHeight();
535                 success = ::SetWindowPos(m_hWnd, HWND_TOP, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER) ?
536                           GHOST_kSuccess : GHOST_kFailure;
537         }
538         else {
539                 success = GHOST_kSuccess;
540         }
541         return success;
542 }
543
544
545 GHOST_TWindowState GHOST_WindowWin32::getState() const
546 {
547         GHOST_TWindowState state;
548
549         // XXX 27.04.2011
550         // we need to find a way to combine parented windows + resizing if we simply set the
551         // state as GHOST_kWindowStateEmbedded we will need to check for them somewhere else.
552         // It's also strange that in Windows is the only platform we need to make this separation.
553         if (m_parentWindowHwnd != 0) {
554                 state = GHOST_kWindowStateEmbedded;
555                 return state;
556         }
557         if (::IsIconic(m_hWnd)) {
558                 state = GHOST_kWindowStateMinimized;
559         }
560         else if (::IsZoomed(m_hWnd)) {
561                 LONG_PTR result = ::GetWindowLongPtr(m_hWnd, GWL_STYLE);
562                 if ((result & (WS_POPUP | WS_MAXIMIZE)) != (WS_POPUP | WS_MAXIMIZE))
563                         state = GHOST_kWindowStateMaximized;
564                 else
565                         state = GHOST_kWindowStateFullScreen;
566         }
567         else {
568                 state = GHOST_kWindowStateNormal;
569         }
570         return state;
571 }
572
573
574 void GHOST_WindowWin32::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
575 {
576         POINT point = { inX, inY };
577         ::ScreenToClient(m_hWnd, &point);
578         outX = point.x;
579         outY = point.y;
580 }
581
582
583 void GHOST_WindowWin32::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
584 {
585         POINT point = { inX, inY };
586         ::ClientToScreen(m_hWnd, &point);
587         outX = point.x;
588         outY = point.y;
589 }
590
591
592 GHOST_TSuccess GHOST_WindowWin32::setState(GHOST_TWindowState state)
593 {
594         GHOST_TWindowState curstate = getState();
595         WINDOWPLACEMENT wp;
596         wp.length = sizeof(WINDOWPLACEMENT);
597         ::GetWindowPlacement(m_hWnd, &wp);
598
599         if (state == GHOST_kWindowStateNormal)
600                 state = m_normal_state;
601         switch (state) {
602                 case GHOST_kWindowStateMinimized:
603                         wp.showCmd = SW_SHOWMINIMIZED;
604                         break;
605                 case GHOST_kWindowStateMaximized:
606                         wp.showCmd = SW_SHOWMAXIMIZED;
607                         SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
608                         break;
609                 case GHOST_kWindowStateFullScreen:
610                         if (curstate != state && curstate != GHOST_kWindowStateMinimized)
611                                 m_normal_state = curstate;
612                         wp.showCmd = SW_SHOWMAXIMIZED;
613                         wp.ptMaxPosition.x = 0;
614                         wp.ptMaxPosition.y = 0;
615                         SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_POPUP | WS_MAXIMIZE);
616                         break;
617                 case GHOST_kWindowStateEmbedded:
618                         SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_CHILD);
619                         break;
620                 case GHOST_kWindowStateNormal:
621                 default:
622                         wp.showCmd = SW_SHOWNORMAL;
623                         SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
624                         break;
625         }
626         SetWindowPos(m_hWnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); /*Clears window cache for SetWindowLongPtr */
627         return ::SetWindowPlacement(m_hWnd, &wp) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
628 }
629
630
631 GHOST_TSuccess GHOST_WindowWin32::setOrder(GHOST_TWindowOrder order)
632 {
633         HWND hWndInsertAfter = order == GHOST_kWindowOrderTop ? HWND_TOP : HWND_BOTTOM;
634         return ::SetWindowPos(m_hWnd, hWndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
635 }
636
637
638 GHOST_TSuccess GHOST_WindowWin32::swapBuffers()
639 {
640         HDC hDC = m_hDC;
641
642         if (is_crappy_intel_card())
643                 hDC = ::wglGetCurrentDC();
644
645         return ::SwapBuffers(hDC) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
646 }
647
648
649 GHOST_TSuccess GHOST_WindowWin32::activateDrawingContext()
650 {
651         GHOST_TSuccess success;
652         if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
653                 if (m_hDC && m_hGlRc) {
654                         success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
655                 }
656                 else {
657                         success = GHOST_kFailure;
658                 }
659         }
660         else {
661                 success = GHOST_kSuccess;
662         }
663         return success;
664 }
665
666
667 GHOST_TSuccess GHOST_WindowWin32::invalidate()
668 {
669         GHOST_TSuccess success;
670         if (m_hWnd) {
671                 success = ::InvalidateRect(m_hWnd, 0, FALSE) != 0 ? GHOST_kSuccess : GHOST_kFailure;
672         }
673         else {
674                 success = GHOST_kFailure;
675         }
676         return success;
677 }
678
679 GHOST_TSuccess GHOST_WindowWin32::initMultisample(PIXELFORMATDESCRIPTOR pfd)
680 {
681         int pixelFormat;
682         bool success = FALSE;
683         UINT numFormats;
684         HDC hDC = GetDC(getHWND());
685         float fAttributes[] = {0, 0};
686         UINT nMaxFormats = 1;
687
688         // The attributes to look for
689         int iAttributes[] = {
690                 WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
691                 WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
692                 WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
693                 WGL_COLOR_BITS_ARB, pfd.cColorBits,
694                 WGL_DEPTH_BITS_ARB, pfd.cDepthBits,
695 #ifdef GHOST_OPENGL_ALPHA
696                 WGL_ALPHA_BITS_ARB, pfd.cAlphaBits,
697 #endif
698                 WGL_STENCIL_BITS_ARB, pfd.cStencilBits,
699                 WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
700                 WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
701                 WGL_SAMPLES_ARB, m_multisample,
702                 0, 0
703         };
704
705         // Get the function
706         PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
707
708         if (!wglChoosePixelFormatARB)
709         {
710                 m_multisampleEnabled = GHOST_kFailure;
711                 return GHOST_kFailure;
712         }
713
714         // iAttributes[17] is the initial multisample. If not valid try to use the closest valid value under it.
715         while (iAttributes[17] > 0) {
716                 // See if the format is valid
717                 success = wglChoosePixelFormatARB(hDC, iAttributes, fAttributes, nMaxFormats, &pixelFormat, &numFormats);
718                 GHOST_PRINTF("WGL_SAMPLES_ARB = %i --> success = %i, %i formats\n", iAttributes[17], success, numFormats);
719
720                 if (success && numFormats >= 1 && m_multisampleEnabled == GHOST_kFailure) {
721                         GHOST_PRINTF("valid pixel format with %i multisamples\n", iAttributes[17]);
722                         m_multisampleEnabled = GHOST_kSuccess;
723                         m_msPixelFormat = pixelFormat;
724                 }
725                 iAttributes[17] -= 1;
726                 success = GHOST_kFailure;
727         }
728         if (m_multisampleEnabled == GHOST_kSuccess) {
729                 return GHOST_kSuccess;
730         }
731         GHOST_PRINT("no available pixel format\n");
732         return GHOST_kFailure;
733 }
734
735 GHOST_TSuccess GHOST_WindowWin32::installDrawingContext(GHOST_TDrawingContextType type)
736 {
737         GHOST_TSuccess success;
738         switch (type) {
739                 case GHOST_kDrawingContextTypeOpenGL:
740                 {
741                         // If this window has multisample enabled, use the supplied format
742                         if (m_multisampleEnabled)
743                         {
744                                 if (SetPixelFormat(m_hDC, m_msPixelFormat, &sPreferredFormat) == FALSE)
745                                 {
746                                         success = GHOST_kFailure;
747                                         break;
748                                 }
749
750                                 // Create the context
751                                 m_hGlRc = ::wglCreateContext(m_hDC);
752                                 if (m_hGlRc) {
753                                         if (::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE) {
754                                                 if (s_firsthGLRc) {
755                                                         if (is_crappy_intel_card()) {
756                                                                 if (::wglMakeCurrent(NULL, NULL) == TRUE) {
757                                                                         ::wglDeleteContext(m_hGlRc);
758                                                                         m_hGlRc = s_firsthGLRc;
759                                                                 }
760                                                                 else {
761                                                                         ::wglDeleteContext(m_hGlRc);
762                                                                         m_hGlRc = NULL;
763                                                                 }
764                                                         }
765                                                         else {
766                                                                 ::wglCopyContext(s_firsthGLRc, m_hGlRc, GL_ALL_ATTRIB_BITS);
767                                                                 ::wglShareLists(s_firsthGLRc, m_hGlRc);
768                                                         }
769                                                 }
770                                                 else {
771                                                         s_firsthGLRc = m_hGlRc;
772                                                 }
773
774                                                 if (m_hGlRc) {
775                                                         success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
776                                                 }
777                                                 else {
778                                                         success = GHOST_kFailure;
779                                                 }
780                                         }
781                                         else {
782                                                 success = GHOST_kFailure;
783                                         }
784                                 }
785                                 else {
786                                         success = GHOST_kFailure;
787                                 }
788
789                                 if (success == GHOST_kFailure) {
790                                         printf("Failed to get a context....\n");
791                                 }
792                         }
793                         else {
794                                 if (m_stereoVisual)
795                                         sPreferredFormat.dwFlags |= PFD_STEREO;
796
797                                 // Attempt to match device context pixel format to the preferred format
798                                 int iPixelFormat = EnumPixelFormats(m_hDC);
799                                 if (iPixelFormat == 0) {
800                                         success = GHOST_kFailure;
801                                         break;
802                                 }
803                                 if (::SetPixelFormat(m_hDC, iPixelFormat, &sPreferredFormat) == FALSE) {
804                                         success = GHOST_kFailure;
805                                         break;
806                                 }
807                                 // For debugging only: retrieve the pixel format chosen
808                                 PIXELFORMATDESCRIPTOR preferredFormat;
809                                 ::DescribePixelFormat(m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &preferredFormat);
810
811                                 // Create the context
812                                 m_hGlRc = ::wglCreateContext(m_hDC);
813                                 if (m_hGlRc) {
814                                         if (::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE) {
815                                                 if (s_firsthGLRc) {
816                                                         if (is_crappy_intel_card()) {
817                                                                 if (::wglMakeCurrent(NULL, NULL) == TRUE) {
818                                                                         ::wglDeleteContext(m_hGlRc);
819                                                                         m_hGlRc = s_firsthGLRc;
820                                                                 }
821                                                                 else {
822                                                                         ::wglDeleteContext(m_hGlRc);
823                                                                         m_hGlRc = NULL;
824                                                                 }
825                                                         }
826                                                         else {
827                                                                 ::wglShareLists(s_firsthGLRc, m_hGlRc);
828                                                         }
829                                                 }
830                                                 else {
831                                                         s_firsthGLRc = m_hGlRc;
832                                                 }
833
834                                                 if (m_hGlRc) {
835                                                         success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
836                                                 }
837                                                 else {
838                                                         success = GHOST_kFailure;
839                                                 }
840                                         }
841                                         else {
842                                                 success = GHOST_kFailure;
843                                         }
844                                 }
845                                 else {
846                                         success = GHOST_kFailure;
847                                 }
848                                         
849                                 if (success == GHOST_kFailure) {
850                                         printf("Failed to get a context....\n");
851                                 }
852
853                                 // Attempt to enable multisample
854                                 if (m_multisample && WGL_ARB_multisample && !m_multisampleEnabled && !is_crappy_intel_card())
855                                 {
856                                         success = initMultisample(preferredFormat);
857
858                                         if (success)
859                                         {
860
861                                                 // Make sure we don't screw up the context
862                                                 if (m_hGlRc == s_firsthGLRc)
863                                                         s_firsthGLRc = NULL;
864                                                 m_drawingContextType = GHOST_kDrawingContextTypeOpenGL;
865                                                 removeDrawingContext();
866
867                                                 // Create a new window
868                                                 GHOST_TWindowState new_state = getState();
869
870                                                 m_nextWindow = new GHOST_WindowWin32((GHOST_SystemWin32 *)GHOST_ISystem::getSystem(),
871                                                                                      m_title,
872                                                                                      m_left,
873                                                                                      m_top,
874                                                                                      m_width,
875                                                                                      m_height,
876                                                                                      new_state,
877                                                                                      type,
878                                                                                      m_stereo,
879                                                                                      m_multisample,
880                                                                                      m_parentWindowHwnd,
881                                                                                      m_multisampleEnabled,
882                                                                                      m_msPixelFormat);
883
884                                                 // Return failure so we can trash this window.
885                                                 success = GHOST_kFailure;
886                                                 break;
887                                         }
888                                         else {
889                                                 m_multisampleEnabled = GHOST_kSuccess;
890                                                 printf("Multisample failed to initialized\n");
891                                                 success = GHOST_kSuccess;
892                                         }
893                                 }
894                         }
895
896                 }
897                 break;
898
899                 case GHOST_kDrawingContextTypeNone:
900                         success = GHOST_kSuccess;
901                         break;
902
903                 default:
904                         success = GHOST_kFailure;
905         }
906         return success;
907 }
908
909 GHOST_TSuccess GHOST_WindowWin32::removeDrawingContext()
910 {
911         GHOST_TSuccess success;
912         switch (m_drawingContextType) {
913                 case GHOST_kDrawingContextTypeOpenGL:
914                         // we shouldn't remove the drawing context if it's the first OpenGL context
915                         // If we do, we get corrupted drawing. See #19997
916                         if (m_hGlRc && m_hGlRc != s_firsthGLRc) {
917                                 success = ::wglDeleteContext(m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
918                                 m_hGlRc = 0;
919                         }
920                         else {
921                                 success = GHOST_kFailure;
922                         }
923                         break;
924                 case GHOST_kDrawingContextTypeNone:
925                         success = GHOST_kSuccess;
926                         break;
927                 default:
928                         success = GHOST_kFailure;
929         }
930         return success;
931 }
932
933 void GHOST_WindowWin32::lostMouseCapture()
934 {
935         if (m_hasMouseCaptured)
936         {   m_hasGrabMouse = false;
937                 m_nPressedButtons = 0;
938                 m_hasMouseCaptured = false; };
939 }
940
941 void GHOST_WindowWin32::registerMouseClickEvent(int press)
942 {
943
944         switch (press)
945         {
946                 case 0: m_nPressedButtons++;    break;
947                 case 1: if (m_nPressedButtons) m_nPressedButtons--; break;
948                 case 2: m_hasGrabMouse = true;    break;
949                 case 3: m_hasGrabMouse = false;   break;
950         }
951
952         if (!m_nPressedButtons && !m_hasGrabMouse && m_hasMouseCaptured)
953         {
954                 ::ReleaseCapture();
955                 m_hasMouseCaptured = false;
956         }
957         else if ((m_nPressedButtons || m_hasGrabMouse) && !m_hasMouseCaptured)
958         {
959                 ::SetCapture(m_hWnd);
960                 m_hasMouseCaptured = true;
961
962         }
963 }
964
965
966 void GHOST_WindowWin32::loadCursor(bool visible, GHOST_TStandardCursor cursor) const
967 {
968         if (!visible) {
969                 while (::ShowCursor(FALSE) >= 0) ;
970         }
971         else {
972                 while (::ShowCursor(TRUE) < 0) ;
973         }
974
975         if (cursor == GHOST_kStandardCursorCustom && m_customCursor) {
976                 ::SetCursor(m_customCursor);
977         }
978         else {
979                 // Convert GHOST cursor to Windows OEM cursor
980                 bool success = true;
981                 LPCSTR id;
982                 switch (cursor) {
983                         case GHOST_kStandardCursorDefault:              id = IDC_ARROW;     break;
984                         case GHOST_kStandardCursorRightArrow:           id = IDC_ARROW;     break;
985                         case GHOST_kStandardCursorLeftArrow:            id = IDC_ARROW;     break;
986                         case GHOST_kStandardCursorInfo:                 id = IDC_SIZEALL;   break;  // Four-pointed arrow pointing north, south, east, and west
987                         case GHOST_kStandardCursorDestroy:              id = IDC_NO;        break;  // Slashed circle
988                         case GHOST_kStandardCursorHelp:                 id = IDC_HELP;      break;  // Arrow and question mark
989                         case GHOST_kStandardCursorCycle:                id = IDC_NO;        break;  // Slashed circle
990                         case GHOST_kStandardCursorSpray:                id = IDC_SIZEALL;   break;  // Four-pointed arrow pointing north, south, east, and west
991                         case GHOST_kStandardCursorWait:                 id = IDC_WAIT;      break;  // Hourglass
992                         case GHOST_kStandardCursorText:                 id = IDC_IBEAM;     break;  // I-beam
993                         case GHOST_kStandardCursorCrosshair:            id = IDC_CROSS;     break;  // Crosshair
994                         case GHOST_kStandardCursorUpDown:               id = IDC_SIZENS;    break;  // Double-pointed arrow pointing north and south
995                         case GHOST_kStandardCursorLeftRight:            id = IDC_SIZEWE;    break;  // Double-pointed arrow pointing west and east
996                         case GHOST_kStandardCursorTopSide:              id = IDC_UPARROW;   break;  // Vertical arrow
997                         case GHOST_kStandardCursorBottomSide:           id = IDC_SIZENS;    break;
998                         case GHOST_kStandardCursorLeftSide:             id = IDC_SIZEWE;    break;
999                         case GHOST_kStandardCursorTopLeftCorner:        id = IDC_SIZENWSE;  break;
1000                         case GHOST_kStandardCursorTopRightCorner:       id = IDC_SIZENESW;  break;
1001                         case GHOST_kStandardCursorBottomRightCorner:    id = IDC_SIZENWSE;  break;
1002                         case GHOST_kStandardCursorBottomLeftCorner:     id = IDC_SIZENESW;  break;
1003                         case GHOST_kStandardCursorPencil:               id = IDC_ARROW;     break;
1004                         case GHOST_kStandardCursorCopy:                 id = IDC_ARROW;     break;
1005                         default:
1006                                 success = false;
1007                 }
1008
1009                 if (success) {
1010                         ::SetCursor(::LoadCursor(0, id));
1011                 }
1012         }
1013 }
1014
1015 GHOST_TSuccess GHOST_WindowWin32::setWindowCursorVisibility(bool visible)
1016 {
1017         if (::GetForegroundWindow() == m_hWnd) {
1018                 loadCursor(visible, getCursorShape());
1019         }
1020
1021         return GHOST_kSuccess;
1022 }
1023
1024 GHOST_TSuccess GHOST_WindowWin32::setWindowCursorGrab(GHOST_TGrabCursorMode mode)
1025 {
1026         if (mode != GHOST_kGrabDisable) {
1027                 if (mode != GHOST_kGrabNormal) {
1028                         m_system->getCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
1029                         setCursorGrabAccum(0, 0);
1030
1031                         if (mode == GHOST_kGrabHide)
1032                                 setWindowCursorVisibility(false);
1033                 }
1034                 registerMouseClickEvent(2);
1035         }
1036         else {
1037                 if (m_cursorGrab == GHOST_kGrabHide) {
1038                         m_system->setCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
1039                         setWindowCursorVisibility(true);
1040                 }
1041                 if (m_cursorGrab != GHOST_kGrabNormal) {
1042                         /* use to generate a mouse move event, otherwise the last event
1043                          * blender gets can be outside the screen causing menus not to show
1044                          * properly unless the user moves the mouse */
1045                         GHOST_TInt32 pos[2];
1046                         m_system->getCursorPosition(pos[0], pos[1]);
1047                         m_system->setCursorPosition(pos[0], pos[1]);
1048                 }
1049
1050                 /* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
1051                 setCursorGrabAccum(0, 0);
1052                 m_cursorGrabBounds.m_l = m_cursorGrabBounds.m_r = -1; /* disable */
1053                 registerMouseClickEvent(3);
1054         }
1055         
1056         return GHOST_kSuccess;
1057 }
1058
1059 GHOST_TSuccess GHOST_WindowWin32::setWindowCursorShape(GHOST_TStandardCursor cursorShape)
1060 {
1061         if (m_customCursor) {
1062                 DestroyCursor(m_customCursor);
1063                 m_customCursor = NULL;
1064         }
1065
1066         if (::GetForegroundWindow() == m_hWnd) {
1067                 loadCursor(getCursorVisibility(), cursorShape);
1068         }
1069
1070         return GHOST_kSuccess;
1071 }
1072
1073 void GHOST_WindowWin32::processWin32TabletInitEvent()
1074 {
1075         if (m_wintab) {
1076                 GHOST_WIN32_WTInfo fpWTInfo = (GHOST_WIN32_WTInfo) ::GetProcAddress(m_wintab, "WTInfoA");
1077
1078                 // let's see if we can initialize tablet here
1079                 /* check if WinTab available. */
1080                 if (fpWTInfo) {
1081                         AXIS Pressure, Orientation[3]; /* The maximum tablet size */
1082
1083                         BOOL pressureSupport = fpWTInfo(WTI_DEVICES, DVC_NPRESSURE, &Pressure);
1084                         if (pressureSupport)
1085                                 m_maxPressure = Pressure.axMax;
1086                         else
1087                                 m_maxPressure = 0;
1088
1089                         BOOL tiltSupport = fpWTInfo(WTI_DEVICES, DVC_ORIENTATION, &Orientation);
1090                         if (tiltSupport) {
1091                                 /* does the tablet support azimuth ([0]) and altitude ([1]) */
1092                                 if (Orientation[0].axResolution && Orientation[1].axResolution) {
1093                                         m_maxAzimuth = Orientation[0].axMax;
1094                                         m_maxAltitude = Orientation[1].axMax;
1095                                 }
1096                                 else {  /* no so dont do tilt stuff */
1097                                         m_maxAzimuth = m_maxAltitude = 0;
1098                                 }
1099                         }
1100
1101                         m_tabletData->Active = GHOST_kTabletModeNone;
1102                 }
1103         }
1104 }
1105
1106 void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam)
1107 {
1108         PACKET pkt;
1109         if (m_wintab) {
1110                 GHOST_WIN32_WTPacket fpWTPacket = (GHOST_WIN32_WTPacket) ::GetProcAddress(m_wintab, "WTPacket");
1111                 if (fpWTPacket) {
1112                         if (fpWTPacket((HCTX)lParam, wParam, &pkt)) {
1113                                 if (m_tabletData) {
1114                                         switch (pkt.pkCursor) {
1115                                                 case 0: /* first device */
1116                                                 case 3: /* second device */
1117                                                         m_tabletData->Active = GHOST_kTabletModeNone; /* puck - not yet supported */
1118                                                         break;
1119                                                 case 1:
1120                                                 case 4:
1121                                                         m_tabletData->Active = GHOST_kTabletModeStylus; /* stylus */
1122                                                         break;
1123                                                 case 2:
1124                                                 case 5:
1125                                                         m_tabletData->Active = GHOST_kTabletModeEraser; /* eraser */
1126                                                         break;
1127                                         }
1128                                         if (m_maxPressure > 0) {
1129                                                 m_tabletData->Pressure = (float)pkt.pkNormalPressure / (float)m_maxPressure;
1130                                         }
1131                                         else {
1132                                                 m_tabletData->Pressure = 1.0f;
1133                                         }
1134
1135                                         if ((m_maxAzimuth > 0) && (m_maxAltitude > 0)) {
1136                                                 ORIENTATION ort = pkt.pkOrientation;
1137                                                 float vecLen;
1138                                                 float altRad, azmRad;   /* in radians */
1139
1140                                                 /*
1141                                                  * from the wintab spec:
1142                                                  * orAzimuth    Specifies the clockwise rotation of the
1143                                                  * cursor about the z axis through a full circular range.
1144                                                  *
1145                                                  * orAltitude   Specifies the angle with the x-y plane
1146                                                  * through a signed, semicircular range.  Positive values
1147                                                  * specify an angle upward toward the positive z axis;
1148                                                  * negative values specify an angle downward toward the negative z axis.
1149                                                  *
1150                                                  * wintab.h defines .orAltitude as a UINT but documents .orAltitude
1151                                                  * as positive for upward angles and negative for downward angles.
1152                                                  * WACOM uses negative altitude values to show that the pen is inverted;
1153                                                  * therefore we cast .orAltitude as an (int) and then use the absolute value.
1154                                                  */
1155
1156                                                 /* convert raw fixed point data to radians */
1157                                                 altRad = (float)((fabs((float)ort.orAltitude) / (float)m_maxAltitude) * M_PI / 2.0);
1158                                                 azmRad = (float)(((float)ort.orAzimuth / (float)m_maxAzimuth) * M_PI * 2.0);
1159
1160                                                 /* find length of the stylus' projected vector on the XY plane */
1161                                                 vecLen = cos(altRad);
1162
1163                                                 /* from there calculate X and Y components based on azimuth */
1164                                                 m_tabletData->Xtilt = sin(azmRad) * vecLen;
1165                                                 m_tabletData->Ytilt = (float)(sin(M_PI / 2.0 - azmRad) * vecLen);
1166
1167                                         }
1168                                         else {
1169                                                 m_tabletData->Xtilt = 0.0f;
1170                                                 m_tabletData->Ytilt = 0.0f;
1171                                         }
1172                                 }
1173                         }
1174                 }
1175         }
1176 }
1177
1178 void GHOST_WindowWin32::bringTabletContextToFront()
1179 {
1180         if (m_wintab) {
1181                 GHOST_WIN32_WTOverlap fpWTOverlap = (GHOST_WIN32_WTOverlap) ::GetProcAddress(m_wintab, "WTOverlap");
1182                 if (fpWTOverlap) {
1183                         fpWTOverlap(m_tablet, TRUE);
1184                 }
1185         }
1186 }
1187
1188 /** Reverse the bits in a GHOST_TUns8 */
1189 static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch)
1190 {
1191         ch = ((ch >> 1) & 0x55) | ((ch << 1) & 0xAA);
1192         ch = ((ch >> 2) & 0x33) | ((ch << 2) & 0xCC);
1193         ch = ((ch >> 4) & 0x0F) | ((ch << 4) & 0xF0);
1194         return ch;
1195 }
1196
1197 #if 0  /* UNUSED */
1198 /** Reverse the bits in a GHOST_TUns16 */
1199 static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt)
1200 {
1201         shrt = ((shrt >> 1) & 0x5555) | ((shrt << 1) & 0xAAAA);
1202         shrt = ((shrt >> 2) & 0x3333) | ((shrt << 2) & 0xCCCC);
1203         shrt = ((shrt >> 4) & 0x0F0F) | ((shrt << 4) & 0xF0F0);
1204         shrt = ((shrt >> 8) & 0x00FF) | ((shrt << 8) & 0xFF00);
1205         return shrt;
1206 }
1207 #endif
1208 GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2],
1209                                                              GHOST_TUns8 mask[16][2],
1210                                                              int hotX, int hotY)
1211 {
1212         return setWindowCustomCursorShape((GHOST_TUns8 *)bitmap, (GHOST_TUns8 *)mask,
1213                                           16, 16, hotX, hotY, 0, 1);
1214 }
1215
1216 GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(GHOST_TUns8 *bitmap,
1217                                                              GHOST_TUns8 *mask, int sizeX, int sizeY, int hotX, int hotY,
1218                                                              int fg_color, int bg_color)
1219 {
1220         GHOST_TUns32 andData[32];
1221         GHOST_TUns32 xorData[32];
1222         GHOST_TUns32 fullBitRow, fullMaskRow;
1223         int x, y, cols;
1224
1225         cols = sizeX / 8; /* Num of whole bytes per row (width of bm/mask) */
1226         if (sizeX % 8) cols++;
1227
1228         if (m_customCursor) {
1229                 DestroyCursor(m_customCursor);
1230                 m_customCursor = NULL;
1231         }
1232
1233         memset(&andData, 0xFF, sizeof(andData));
1234         memset(&xorData, 0, sizeof(xorData));
1235
1236         for (y = 0; y < sizeY; y++) {
1237                 fullBitRow = 0;
1238                 fullMaskRow = 0;
1239                 for (x = cols - 1; x >= 0; x--) {
1240                         fullBitRow <<= 8;
1241                         fullMaskRow <<= 8;
1242                         fullBitRow  |= uns8ReverseBits(bitmap[cols * y + x]);
1243                         fullMaskRow |= uns8ReverseBits(mask[cols * y + x]);
1244                 }
1245                 xorData[y] = fullBitRow & fullMaskRow;
1246                 andData[y] = ~fullMaskRow;
1247         }
1248
1249         m_customCursor = ::CreateCursor(::GetModuleHandle(0), hotX, hotY, 32, 32, andData, xorData);
1250         if (!m_customCursor) {
1251                 return GHOST_kFailure;
1252         }
1253
1254         if (::GetForegroundWindow() == m_hWnd) {
1255                 loadCursor(getCursorVisibility(), GHOST_kStandardCursorCustom);
1256         }
1257
1258         return GHOST_kSuccess;
1259 }
1260
1261
1262 GHOST_TSuccess GHOST_WindowWin32::setProgressBar(float progress)
1263 {       
1264         /*SetProgressValue sets state to TBPF_NORMAL automaticly*/
1265         if (m_Bar && S_OK == m_Bar->SetProgressValue(m_hWnd, 10000 * progress, 10000))
1266                 return GHOST_kSuccess;
1267
1268         return GHOST_kFailure;
1269 }
1270
1271 GHOST_TSuccess GHOST_WindowWin32::endProgressBar()
1272 {
1273         if (m_Bar && S_OK == m_Bar->SetProgressState(m_hWnd, TBPF_NOPROGRESS))
1274                 return GHOST_kSuccess;
1275
1276         return GHOST_kFailure;
1277 }
1278
1279 /* Ron Fosner's code for weighting pixel formats and forcing software.
1280  * See http://www.opengl.org/resources/faq/technical/weight.cpp */
1281
1282 static int WeightPixelFormat(PIXELFORMATDESCRIPTOR& pfd)
1283 {
1284         int weight = 0;
1285
1286         /* assume desktop color depth is 32 bits per pixel */
1287
1288         /* cull unusable pixel formats */
1289         /* if no formats can be found, can we determine why it was rejected? */
1290         if (!(pfd.dwFlags & PFD_SUPPORT_OPENGL) ||
1291             !(pfd.dwFlags & PFD_DRAW_TO_WINDOW) ||
1292             !(pfd.dwFlags & PFD_DOUBLEBUFFER) || /* Blender _needs_ this */
1293             (pfd.cDepthBits <= 8) ||
1294             !(pfd.iPixelType == PFD_TYPE_RGBA))
1295         {
1296                 return 0;
1297         }
1298
1299         weight = 1;  /* it's usable */
1300
1301         /* the bigger the depth buffer the better */
1302         /* give no weight to a 16-bit depth buffer, because those are crap */
1303         weight += pfd.cDepthBits - 16;
1304
1305         weight += pfd.cColorBits - 8;
1306
1307 #ifdef GHOST_OPENGL_ALPHA
1308         if (pfd.cAlphaBits > 0)
1309                 weight ++;
1310 #endif
1311
1312         /* want swap copy capability -- it matters a lot */
1313         if (pfd.dwFlags & PFD_SWAP_COPY) weight += 16;
1314
1315         /* but if it's a generic (not accelerated) view, it's really bad */
1316         if (pfd.dwFlags & PFD_GENERIC_FORMAT) weight /= 10;
1317
1318         return weight;
1319 }
1320
1321 /* A modification of Ron Fosner's replacement for ChoosePixelFormat */
1322 /* returns 0 on error, else returns the pixel format number to be used */
1323 static int EnumPixelFormats(HDC hdc)
1324 {
1325         int iPixelFormat;
1326         int i, n, w, weight = 0;
1327         PIXELFORMATDESCRIPTOR pfd;
1328
1329         /* we need a device context to do anything */
1330         if (!hdc) return 0;
1331
1332         iPixelFormat = 1; /* careful! PFD numbers are 1 based, not zero based */
1333
1334         /* obtain detailed information about
1335          * the device context's first pixel format */
1336         n = 1 + ::DescribePixelFormat(hdc, iPixelFormat,
1337                                       sizeof(PIXELFORMATDESCRIPTOR), &pfd);
1338
1339         /* choose a pixel format using the useless Windows function in case
1340          * we come up empty handed */
1341         iPixelFormat = ::ChoosePixelFormat(hdc, &sPreferredFormat);
1342
1343         if (!iPixelFormat) return 0;  /* couldn't find one to use */
1344
1345         for (i = 1; i <= n; i++) { /* not the idiom, but it's right */
1346                 ::DescribePixelFormat(hdc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
1347                 w = WeightPixelFormat(pfd);
1348                 // be strict on stereo
1349                 if (!((sPreferredFormat.dwFlags ^ pfd.dwFlags) & PFD_STEREO)) {
1350                         if (w > weight) {
1351                                 weight = w;
1352                                 iPixelFormat = i;
1353                         }
1354                 }
1355         }
1356         if (weight == 0) {
1357                 // we could find the correct stereo setting, just find any suitable format
1358                 for (i = 1; i <= n; i++) { /* not the idiom, but it's right */
1359                         ::DescribePixelFormat(hdc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
1360                         w = WeightPixelFormat(pfd);
1361                         if (w > weight) {
1362                                 weight = w;
1363                                 iPixelFormat = i;
1364                         }
1365                 }
1366         }
1367         return iPixelFormat;
1368 }
1369
1370