Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): none yet. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00040 #include <string.h> 00041 #include "GHOST_WindowWin32.h" 00042 #include "GHOST_SystemWin32.h" 00043 #include "GHOST_DropTargetWin32.h" 00044 00045 // Need glew for some defines 00046 #include <GL/glew.h> 00047 #include <GL/wglew.h> 00048 #include <math.h> 00049 00050 // MSVC6 still doesn't define M_PI 00051 #ifndef M_PI 00052 #define M_PI 3.1415926536 00053 #endif 00054 00055 // Some more multisample defines 00056 #define WGL_SAMPLE_BUFERS_ARB 0x2041 00057 #define WGL_SAMPLES_ARB 0x2042 00058 00059 // win64 doesn't define GWL_USERDATA 00060 #ifdef WIN32 00061 #ifndef GWL_USERDATA 00062 #define GWL_USERDATA GWLP_USERDATA 00063 #define GWL_WNDPROC GWLP_WNDPROC 00064 #endif 00065 #endif 00066 00067 LPCSTR GHOST_WindowWin32::s_windowClassName = "GHOST_WindowClass"; 00068 const int GHOST_WindowWin32::s_maxTitleLength = 128; 00069 HGLRC GHOST_WindowWin32::s_firsthGLRc = NULL; 00070 HDC GHOST_WindowWin32::s_firstHDC = NULL; 00071 00072 static int WeightPixelFormat(PIXELFORMATDESCRIPTOR& pfd); 00073 static int EnumPixelFormats(HDC hdc); 00074 00075 /* 00076 * Color and depth bit values are not to be trusted. 00077 * For instance, on TNT2: 00078 * When the screen color depth is set to 16 bit, we get 5 color bits 00079 * and 16 depth bits. 00080 * When the screen color depth is set to 32 bit, we get 8 color bits 00081 * and 24 depth bits. 00082 * Just to be safe, we request high waulity settings. 00083 */ 00084 static PIXELFORMATDESCRIPTOR sPreferredFormat = { 00085 sizeof(PIXELFORMATDESCRIPTOR), /* size */ 00086 1, /* version */ 00087 PFD_SUPPORT_OPENGL | 00088 PFD_DRAW_TO_WINDOW | 00089 PFD_SWAP_COPY | /* support swap copy */ 00090 PFD_DOUBLEBUFFER, /* support double-buffering */ 00091 PFD_TYPE_RGBA, /* color type */ 00092 32, /* prefered color depth */ 00093 0, 0, 0, 0, 0, 0, /* color bits (ignored) */ 00094 0, /* no alpha buffer */ 00095 0, /* alpha bits (ignored) */ 00096 0, /* no accumulation buffer */ 00097 0, 0, 0, 0, /* accum bits (ignored) */ 00098 32, /* depth buffer */ 00099 0, /* no stencil buffer */ 00100 0, /* no auxiliary buffers */ 00101 PFD_MAIN_PLANE, /* main layer */ 00102 0, /* reserved */ 00103 0, 0, 0 /* no layer, visible, damage masks */ 00104 }; 00105 00106 /* Intel videocards don't work fine with multiple contexts and 00107 have to share the same context for all windows. 00108 But if we just share context for all windows it could work incorrect 00109 with multiple videocards configuration. Suppose, that Intel videocards 00110 can't be in multiple-devices configuration. */ 00111 static int is_crappy_intel_card(void) 00112 { 00113 int crappy = 0; 00114 const char *vendor = (const char*)glGetString(GL_VENDOR); 00115 00116 if (strstr(vendor, "Intel")) 00117 crappy = 1; 00118 00119 return crappy; 00120 } 00121 00122 GHOST_WindowWin32::GHOST_WindowWin32( 00123 GHOST_SystemWin32 * system, 00124 const STR_String& title, 00125 GHOST_TInt32 left, 00126 GHOST_TInt32 top, 00127 GHOST_TUns32 width, 00128 GHOST_TUns32 height, 00129 GHOST_TWindowState state, 00130 GHOST_TDrawingContextType type, 00131 const bool stereoVisual, 00132 const GHOST_TUns16 numOfAASamples, 00133 GHOST_TEmbedderWindowID parentwindowhwnd, 00134 GHOST_TSuccess msEnabled, 00135 int msPixelFormat) 00136 : 00137 GHOST_Window(width, height, state, GHOST_kDrawingContextTypeNone, 00138 stereoVisual,numOfAASamples), 00139 m_system(system), 00140 m_hDC(0), 00141 m_hGlRc(0), 00142 m_hasMouseCaptured(false), 00143 m_hasGrabMouse(false), 00144 m_nPressedButtons(0), 00145 m_customCursor(0), 00146 m_wintab(NULL), 00147 m_tabletData(NULL), 00148 m_tablet(0), 00149 m_maxPressure(0), 00150 m_multisample(numOfAASamples), 00151 m_parentWindowHwnd(parentwindowhwnd), 00152 m_multisampleEnabled(msEnabled), 00153 m_msPixelFormat(msPixelFormat), 00154 //For recreation 00155 m_title(title), 00156 m_left(left), 00157 m_top(top), 00158 m_width(width), 00159 m_height(height), 00160 m_normal_state(GHOST_kWindowStateNormal), 00161 m_stereo(stereoVisual), 00162 m_nextWindow(NULL) 00163 { 00164 OSVERSIONINFOEX versionInfo; 00165 bool hasMinVersionForTaskbar = false; 00166 00167 ZeroMemory(&versionInfo, sizeof(OSVERSIONINFOEX)); 00168 00169 versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); 00170 00171 if(!GetVersionEx((OSVERSIONINFO *)&versionInfo)) { 00172 versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 00173 if(GetVersionEx((OSVERSIONINFO*)&versionInfo)) { 00174 if((versionInfo.dwMajorVersion==6 && versionInfo.dwMinorVersion>=1) || versionInfo.dwMajorVersion >= 7) { 00175 hasMinVersionForTaskbar = true; 00176 } 00177 } 00178 } else { 00179 if((versionInfo.dwMajorVersion==6 && versionInfo.dwMinorVersion>=1) || versionInfo.dwMajorVersion >= 7) { 00180 hasMinVersionForTaskbar = true; 00181 } 00182 } 00183 00184 if (state != GHOST_kWindowStateFullScreen) { 00185 RECT rect; 00186 MONITORINFO monitor; 00187 GHOST_TUns32 tw, th; 00188 00189 width += GetSystemMetrics(SM_CXSIZEFRAME)*2; 00190 height += GetSystemMetrics(SM_CYSIZEFRAME)*2 + GetSystemMetrics(SM_CYCAPTION); 00191 00192 rect.left = left; 00193 rect.right = left + width; 00194 rect.top = top; 00195 rect.bottom = top + height; 00196 00197 monitor.cbSize=sizeof(monitor); 00198 monitor.dwFlags=0; 00199 00200 // take taskbar into account 00201 GetMonitorInfo(MonitorFromRect(&rect,MONITOR_DEFAULTTONEAREST),&monitor); 00202 00203 th = monitor.rcWork.bottom - monitor.rcWork.top; 00204 tw = monitor.rcWork.right - monitor.rcWork.left; 00205 00206 if(tw < width) 00207 { 00208 width = tw; 00209 left = monitor.rcWork.left; 00210 } 00211 else if(monitor.rcWork.right < left + (int)width) 00212 left = monitor.rcWork.right - width; 00213 else if(left < monitor.rcWork.left) 00214 left = monitor.rcWork.left; 00215 00216 if(th < height) 00217 { 00218 height = th; 00219 top = monitor.rcWork.top; 00220 } 00221 else if(monitor.rcWork.bottom < top + (int)height) 00222 top = monitor.rcWork.bottom - height; 00223 else if(top < monitor.rcWork.top) 00224 top = monitor.rcWork.top; 00225 00226 int wintype = WS_OVERLAPPEDWINDOW; 00227 if (m_parentWindowHwnd != 0) 00228 { 00229 wintype = WS_CHILD; 00230 GetWindowRect((HWND)m_parentWindowHwnd, &rect); 00231 left = 0; 00232 top = 0; 00233 width = rect.right - rect.left; 00234 height = rect.bottom - rect.top; 00235 } 00236 00237 m_hWnd = ::CreateWindow( 00238 s_windowClassName, // pointer to registered class name 00239 title, // pointer to window name 00240 wintype, // window style 00241 left, // horizontal position of window 00242 top, // vertical position of window 00243 width, // window width 00244 height, // window height 00245 (HWND) m_parentWindowHwnd, // handle to parent or owner window 00246 0, // handle to menu or child-window identifier 00247 ::GetModuleHandle(0), // handle to application instance 00248 0); // pointer to window-creation data 00249 } 00250 else { 00251 m_hWnd = ::CreateWindow( 00252 s_windowClassName, // pointer to registered class name 00253 title, // pointer to window name 00254 WS_POPUP | WS_MAXIMIZE, // window style 00255 left, // horizontal position of window 00256 top, // vertical position of window 00257 width, // window width 00258 height, // window height 00259 HWND_DESKTOP, // handle to parent or owner window 00260 0, // handle to menu or child-window identifier 00261 ::GetModuleHandle(0), // handle to application instance 00262 0); // pointer to window-creation data 00263 } 00264 if (m_hWnd) { 00265 // Register this window as a droptarget. Requires m_hWnd to be valid. 00266 // Note that OleInitialize(0) has to be called prior to this. Done in GHOST_SystemWin32. 00267 m_dropTarget = new GHOST_DropTargetWin32(this, m_system); 00268 // Store a pointer to this class in the window structure 00269 ::SetWindowLongPtr(m_hWnd, GWL_USERDATA, (LONG_PTR)this); 00270 00271 // Store the device context 00272 m_hDC = ::GetDC(m_hWnd); 00273 00274 if(!s_firstHDC) { 00275 s_firstHDC = m_hDC; 00276 } 00277 00278 // Show the window 00279 int nCmdShow; 00280 switch (state) { 00281 case GHOST_kWindowStateMaximized: 00282 nCmdShow = SW_SHOWMAXIMIZED; 00283 break; 00284 case GHOST_kWindowStateMinimized: 00285 nCmdShow = SW_SHOWMINIMIZED; 00286 break; 00287 case GHOST_kWindowStateNormal: 00288 default: 00289 nCmdShow = SW_SHOWNORMAL; 00290 break; 00291 } 00292 GHOST_TSuccess success; 00293 success = setDrawingContextType(type); 00294 00295 if (success) 00296 { 00297 ::ShowWindow(m_hWnd, nCmdShow); 00298 // Force an initial paint of the window 00299 ::UpdateWindow(m_hWnd); 00300 } 00301 else 00302 { 00303 //invalidate the window 00304 m_hWnd = 0; 00305 } 00306 } 00307 00308 if (parentwindowhwnd != 0) { 00309 RAWINPUTDEVICE device = {0}; 00310 device.usUsagePage = 0x01; /* usUsagePage & usUsage for keyboard*/ 00311 device.usUsage = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */ 00312 device.dwFlags |= RIDEV_INPUTSINK; // makes WM_INPUT is visible for ghost when has parent window 00313 device.hwndTarget = m_hWnd; 00314 RegisterRawInputDevices(&device, 1, sizeof(device)); 00315 } 00316 00317 m_wintab = ::LoadLibrary("Wintab32.dll"); 00318 if (m_wintab) { 00319 GHOST_WIN32_WTInfo fpWTInfo = ( GHOST_WIN32_WTInfo ) ::GetProcAddress( m_wintab, "WTInfoA" ); 00320 GHOST_WIN32_WTOpen fpWTOpen = ( GHOST_WIN32_WTOpen ) ::GetProcAddress( m_wintab, "WTOpenA" ); 00321 00322 // let's see if we can initialize tablet here 00323 /* check if WinTab available. */ 00324 if (fpWTInfo && fpWTInfo(0, 0, NULL)) { 00325 // Now init the tablet 00326 LOGCONTEXT lc; 00327 AXIS TabletX, TabletY, Pressure, Orientation[3]; /* The maximum tablet size, pressure and orientation (tilt) */ 00328 00329 // Open a Wintab context 00330 00331 // Get default context information 00332 fpWTInfo( WTI_DEFCONTEXT, 0, &lc ); 00333 00334 // Open the context 00335 lc.lcPktData = PACKETDATA; 00336 lc.lcPktMode = PACKETMODE; 00337 lc.lcOptions |= CXO_MESSAGES | CXO_SYSTEM; 00338 00339 /* Set the entire tablet as active */ 00340 fpWTInfo(WTI_DEVICES,DVC_X,&TabletX); 00341 fpWTInfo(WTI_DEVICES,DVC_Y,&TabletY); 00342 00343 /* get the max pressure, to divide into a float */ 00344 BOOL pressureSupport = fpWTInfo (WTI_DEVICES, DVC_NPRESSURE, &Pressure); 00345 if (pressureSupport) 00346 m_maxPressure = Pressure.axMax; 00347 else 00348 m_maxPressure = 0; 00349 00350 /* get the max tilt axes, to divide into floats */ 00351 BOOL tiltSupport = fpWTInfo (WTI_DEVICES, DVC_ORIENTATION, &Orientation); 00352 if (tiltSupport) { 00353 /* does the tablet support azimuth ([0]) and altitude ([1]) */ 00354 if (Orientation[0].axResolution && Orientation[1].axResolution) { 00355 /* all this assumes the minimum is 0 */ 00356 m_maxAzimuth = Orientation[0].axMax; 00357 m_maxAltitude = Orientation[1].axMax; 00358 } 00359 else { /* no so dont do tilt stuff */ 00360 m_maxAzimuth = m_maxAltitude = 0; 00361 } 00362 } 00363 00364 if (fpWTOpen) { 00365 m_tablet = fpWTOpen( m_hWnd, &lc, TRUE ); 00366 if (m_tablet) { 00367 m_tabletData = new GHOST_TabletData(); 00368 m_tabletData->Active = GHOST_kTabletModeNone; 00369 } 00370 } 00371 } 00372 } 00373 00374 if(hasMinVersionForTaskbar) 00375 CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList ,(LPVOID*)&m_Bar); 00376 else 00377 m_Bar=NULL; 00378 } 00379 00380 00381 GHOST_WindowWin32::~GHOST_WindowWin32() 00382 { 00383 if(m_Bar) 00384 { 00385 m_Bar->SetProgressState(m_hWnd, TBPF_NOPROGRESS); 00386 m_Bar->Release(); 00387 }; 00388 00389 if (m_wintab) { 00390 GHOST_WIN32_WTClose fpWTClose = ( GHOST_WIN32_WTClose ) ::GetProcAddress( m_wintab, "WTClose" ); 00391 if (fpWTClose) { 00392 if (m_tablet) 00393 fpWTClose(m_tablet); 00394 if (m_tabletData) 00395 delete m_tabletData; 00396 m_tabletData = NULL; 00397 } 00398 } 00399 if (m_customCursor) { 00400 DestroyCursor(m_customCursor); 00401 m_customCursor = NULL; 00402 } 00403 00404 ::wglMakeCurrent(NULL, NULL); 00405 m_multisampleEnabled = GHOST_kFailure; 00406 m_multisample = 0; 00407 setDrawingContextType(GHOST_kDrawingContextTypeNone); 00408 if (m_hDC && m_hDC != s_firstHDC) { 00409 ::ReleaseDC(m_hWnd, m_hDC); 00410 m_hDC = 0; 00411 } 00412 if (m_hWnd) { 00413 m_dropTarget->Release(); // frees itself. 00414 ::DestroyWindow(m_hWnd); 00415 m_hWnd = 0; 00416 } 00417 } 00418 00419 GHOST_Window *GHOST_WindowWin32::getNextWindow() 00420 { 00421 return m_nextWindow; 00422 } 00423 00424 bool GHOST_WindowWin32::getValid() const 00425 { 00426 return m_hWnd != 0; 00427 } 00428 00429 HWND GHOST_WindowWin32::getHWND() const 00430 { 00431 return m_hWnd; 00432 } 00433 00434 void GHOST_WindowWin32::setTitle(const STR_String& title) 00435 { 00436 ::SetWindowText(m_hWnd, title); 00437 } 00438 00439 00440 void GHOST_WindowWin32::getTitle(STR_String& title) const 00441 { 00442 char buf[s_maxTitleLength]; 00443 ::GetWindowText(m_hWnd, buf, s_maxTitleLength); 00444 STR_String temp (buf); 00445 title = buf; 00446 } 00447 00448 00449 void GHOST_WindowWin32::getWindowBounds(GHOST_Rect& bounds) const 00450 { 00451 RECT rect; 00452 ::GetWindowRect(m_hWnd, &rect); 00453 bounds.m_b = rect.bottom; 00454 bounds.m_l = rect.left; 00455 bounds.m_r = rect.right; 00456 bounds.m_t = rect.top; 00457 } 00458 00459 00460 void GHOST_WindowWin32::getClientBounds(GHOST_Rect& bounds) const 00461 { 00462 RECT rect; 00463 GHOST_TWindowState state= this->getState(); 00464 LONG_PTR result = ::GetWindowLongPtr(m_hWnd, GWL_STYLE); 00465 int sm_cysizeframe = GetSystemMetrics(SM_CYSIZEFRAME); 00466 ::GetWindowRect(m_hWnd, &rect); 00467 00468 if((result & (WS_POPUP | WS_MAXIMIZE)) != (WS_POPUP | WS_MAXIMIZE)) { 00469 if(state==GHOST_kWindowStateMaximized) { 00470 // in maximized state we don't have borders on the window 00471 bounds.m_b = rect.bottom-GetSystemMetrics(SM_CYCAPTION)- sm_cysizeframe*2; 00472 bounds.m_l = rect.left + sm_cysizeframe; 00473 bounds.m_r = rect.right - sm_cysizeframe; 00474 bounds.m_t = rect.top; 00475 } else if (state == GHOST_kWindowStateEmbedded) { 00476 bounds.m_b = rect.bottom; 00477 bounds.m_l = rect.left; 00478 bounds.m_r = rect.right; 00479 bounds.m_t = rect.top; 00480 } else { 00481 bounds.m_b = rect.bottom-GetSystemMetrics(SM_CYCAPTION)-sm_cysizeframe*2; 00482 bounds.m_l = rect.left; 00483 bounds.m_r = rect.right-sm_cysizeframe*2; 00484 bounds.m_t = rect.top; 00485 } 00486 } else { 00487 bounds.m_b = rect.bottom; 00488 bounds.m_l = rect.left; 00489 bounds.m_r = rect.right; 00490 bounds.m_t = rect.top; 00491 } 00492 } 00493 00494 00495 GHOST_TSuccess GHOST_WindowWin32::setClientWidth(GHOST_TUns32 width) 00496 { 00497 GHOST_TSuccess success; 00498 GHOST_Rect cBnds, wBnds; 00499 getClientBounds(cBnds); 00500 if (cBnds.getWidth() != (GHOST_TInt32)width) { 00501 getWindowBounds(wBnds); 00502 int cx = wBnds.getWidth() + width - cBnds.getWidth(); 00503 int cy = wBnds.getHeight(); 00504 success = ::SetWindowPos(m_hWnd, HWND_TOP, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER) ? 00505 GHOST_kSuccess : GHOST_kFailure; 00506 } 00507 else { 00508 success = GHOST_kSuccess; 00509 } 00510 return success; 00511 } 00512 00513 00514 GHOST_TSuccess GHOST_WindowWin32::setClientHeight(GHOST_TUns32 height) 00515 { 00516 GHOST_TSuccess success; 00517 GHOST_Rect cBnds, wBnds; 00518 getClientBounds(cBnds); 00519 if (cBnds.getHeight() != (GHOST_TInt32)height) { 00520 getWindowBounds(wBnds); 00521 int cx = wBnds.getWidth(); 00522 int cy = wBnds.getHeight() + height - cBnds.getHeight(); 00523 success = ::SetWindowPos(m_hWnd, HWND_TOP, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER) ? 00524 GHOST_kSuccess : GHOST_kFailure; 00525 } 00526 else { 00527 success = GHOST_kSuccess; 00528 } 00529 return success; 00530 } 00531 00532 00533 GHOST_TSuccess GHOST_WindowWin32::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) 00534 { 00535 GHOST_TSuccess success; 00536 GHOST_Rect cBnds, wBnds; 00537 getClientBounds(cBnds); 00538 if ((cBnds.getWidth() != (GHOST_TInt32)width) || (cBnds.getHeight() != (GHOST_TInt32)height)) { 00539 getWindowBounds(wBnds); 00540 int cx = wBnds.getWidth() + width - cBnds.getWidth(); 00541 int cy = wBnds.getHeight() + height - cBnds.getHeight(); 00542 success = ::SetWindowPos(m_hWnd, HWND_TOP, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER) ? 00543 GHOST_kSuccess : GHOST_kFailure; 00544 } 00545 else { 00546 success = GHOST_kSuccess; 00547 } 00548 return success; 00549 } 00550 00551 00552 GHOST_TWindowState GHOST_WindowWin32::getState() const 00553 { 00554 GHOST_TWindowState state; 00555 00556 // XXX 27.04.2011 00557 // we need to find a way to combine parented windows + resizing if we simply set the 00558 // state as GHOST_kWindowStateEmbedded we will need to check for them somewhere else. 00559 // It's also strange that in Windows is the only platform we need to make this separation. 00560 if (m_parentWindowHwnd != 0) { 00561 state = GHOST_kWindowStateEmbedded; 00562 return state; 00563 } 00564 if (::IsIconic(m_hWnd)) { 00565 state = GHOST_kWindowStateMinimized; 00566 } 00567 else if (::IsZoomed(m_hWnd)) { 00568 LONG_PTR result = ::GetWindowLongPtr(m_hWnd, GWL_STYLE); 00569 if((result & (WS_POPUP | WS_MAXIMIZE)) != (WS_POPUP | WS_MAXIMIZE)) 00570 state = GHOST_kWindowStateMaximized; 00571 else 00572 state = GHOST_kWindowStateFullScreen; 00573 } 00574 else { 00575 state = GHOST_kWindowStateNormal; 00576 } 00577 return state; 00578 } 00579 00580 00581 void GHOST_WindowWin32::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const 00582 { 00583 POINT point = { inX, inY }; 00584 ::ScreenToClient(m_hWnd, &point); 00585 outX = point.x; 00586 outY = point.y; 00587 } 00588 00589 00590 void GHOST_WindowWin32::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const 00591 { 00592 POINT point = { inX, inY }; 00593 ::ClientToScreen(m_hWnd, &point); 00594 outX = point.x; 00595 outY = point.y; 00596 } 00597 00598 00599 GHOST_TSuccess GHOST_WindowWin32::setState(GHOST_TWindowState state) 00600 { 00601 GHOST_TWindowState curstate = getState(); 00602 WINDOWPLACEMENT wp; 00603 wp.length = sizeof(WINDOWPLACEMENT); 00604 ::GetWindowPlacement(m_hWnd, &wp); 00605 00606 if (state == GHOST_kWindowStateNormal) 00607 state = m_normal_state; 00608 switch (state) { 00609 case GHOST_kWindowStateMinimized: 00610 wp.showCmd = SW_SHOWMINIMIZED; 00611 break; 00612 case GHOST_kWindowStateMaximized: 00613 wp.showCmd = SW_SHOWMAXIMIZED; 00614 SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW); 00615 break; 00616 case GHOST_kWindowStateFullScreen: 00617 if (curstate != state && curstate != GHOST_kWindowStateMinimized) 00618 m_normal_state = curstate; 00619 wp.showCmd = SW_SHOWMAXIMIZED; 00620 wp.ptMaxPosition.x = 0; 00621 wp.ptMaxPosition.y = 0; 00622 SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_POPUP | WS_MAXIMIZE); 00623 break; 00624 case GHOST_kWindowStateEmbedded: 00625 SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_CHILD); 00626 break; 00627 case GHOST_kWindowStateNormal: 00628 default: 00629 wp.showCmd = SW_SHOWNORMAL; 00630 SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW); 00631 break; 00632 } 00633 SetWindowPos(m_hWnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); /*Clears window cache for SetWindowLongPtr */ 00634 return ::SetWindowPlacement(m_hWnd, &wp) == TRUE ? GHOST_kSuccess : GHOST_kFailure; 00635 } 00636 00637 00638 GHOST_TSuccess GHOST_WindowWin32::setOrder(GHOST_TWindowOrder order) 00639 { 00640 HWND hWndInsertAfter = order == GHOST_kWindowOrderTop ? HWND_TOP : HWND_BOTTOM; 00641 return ::SetWindowPos(m_hWnd, hWndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE) == TRUE ? GHOST_kSuccess : GHOST_kFailure; 00642 } 00643 00644 00645 GHOST_TSuccess GHOST_WindowWin32::swapBuffers() 00646 { 00647 HDC hDC = m_hDC; 00648 00649 if (is_crappy_intel_card()) 00650 hDC = ::wglGetCurrentDC(); 00651 00652 return ::SwapBuffers(hDC) == TRUE ? GHOST_kSuccess : GHOST_kFailure; 00653 } 00654 00655 00656 GHOST_TSuccess GHOST_WindowWin32::activateDrawingContext() 00657 { 00658 GHOST_TSuccess success; 00659 if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { 00660 if (m_hDC && m_hGlRc) { 00661 success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure; 00662 } 00663 else { 00664 success = GHOST_kFailure; 00665 } 00666 } 00667 else { 00668 success = GHOST_kSuccess; 00669 } 00670 return success; 00671 } 00672 00673 00674 GHOST_TSuccess GHOST_WindowWin32::invalidate() 00675 { 00676 GHOST_TSuccess success; 00677 if (m_hWnd) { 00678 success = ::InvalidateRect(m_hWnd, 0, FALSE) != 0 ? GHOST_kSuccess : GHOST_kFailure; 00679 } 00680 else { 00681 success = GHOST_kFailure; 00682 } 00683 return success; 00684 } 00685 00686 GHOST_TSuccess GHOST_WindowWin32::initMultisample(PIXELFORMATDESCRIPTOR pfd) 00687 { 00688 int pixelFormat; 00689 bool success = FALSE; 00690 UINT numFormats; 00691 HDC hDC = GetDC(getHWND()); 00692 float fAttributes[] = {0, 0}; 00693 UINT nMaxFormats = 1; 00694 00695 // The attributes to look for 00696 int iAttributes[] = { 00697 WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, 00698 WGL_SUPPORT_OPENGL_ARB, GL_TRUE, 00699 WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, 00700 WGL_COLOR_BITS_ARB, pfd.cColorBits, 00701 WGL_DEPTH_BITS_ARB, pfd.cDepthBits, 00702 WGL_STENCIL_BITS_ARB, pfd.cStencilBits, 00703 WGL_DOUBLE_BUFFER_ARB, GL_TRUE, 00704 WGL_SAMPLE_BUFFERS_ARB, GL_TRUE, 00705 WGL_SAMPLES_ARB, m_multisample, 00706 0, 0 00707 }; 00708 00709 // Get the function 00710 PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); 00711 00712 if (!wglChoosePixelFormatARB) 00713 { 00714 m_multisampleEnabled = GHOST_kFailure; 00715 return GHOST_kFailure; 00716 } 00717 00718 // iAttributes[17] is the initial multisample. If not valid try to use the closest valid value under it. 00719 while (iAttributes[17] > 0) { 00720 // See if the format is valid 00721 success = wglChoosePixelFormatARB(hDC, iAttributes, fAttributes, nMaxFormats, &pixelFormat, &numFormats); 00722 GHOST_PRINTF("WGL_SAMPLES_ARB = %i --> success = %i, %i formats\n", iAttributes[17], success, numFormats); 00723 00724 if (success && numFormats >= 1 && m_multisampleEnabled == GHOST_kFailure) { 00725 GHOST_PRINTF("valid pixel format with %i multisamples\n", iAttributes[17]); 00726 m_multisampleEnabled = GHOST_kSuccess; 00727 m_msPixelFormat = pixelFormat; 00728 } 00729 iAttributes[17] -= 1; 00730 success = GHOST_kFailure; 00731 } 00732 if (m_multisampleEnabled == GHOST_kSuccess) { 00733 return GHOST_kSuccess; 00734 } 00735 GHOST_PRINT("no available pixel format\n"); 00736 return GHOST_kFailure; 00737 } 00738 00739 GHOST_TSuccess GHOST_WindowWin32::installDrawingContext(GHOST_TDrawingContextType type) 00740 { 00741 GHOST_TSuccess success; 00742 switch (type) { 00743 case GHOST_kDrawingContextTypeOpenGL: 00744 { 00745 // If this window has multisample enabled, use the supplied format 00746 if (m_multisampleEnabled) 00747 { 00748 if (SetPixelFormat(m_hDC, m_msPixelFormat, &sPreferredFormat)==FALSE) 00749 { 00750 success = GHOST_kFailure; 00751 break; 00752 } 00753 00754 // Create the context 00755 m_hGlRc = ::wglCreateContext(m_hDC); 00756 if (m_hGlRc) { 00757 if (::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE) { 00758 if (s_firsthGLRc) { 00759 if (is_crappy_intel_card()) { 00760 if (::wglMakeCurrent(NULL, NULL) == TRUE) { 00761 ::wglDeleteContext(m_hGlRc); 00762 m_hGlRc = s_firsthGLRc; 00763 } 00764 else { 00765 ::wglDeleteContext(m_hGlRc); 00766 m_hGlRc = NULL; 00767 } 00768 } 00769 else { 00770 ::wglCopyContext(s_firsthGLRc, m_hGlRc, GL_ALL_ATTRIB_BITS); 00771 ::wglShareLists(s_firsthGLRc, m_hGlRc); 00772 } 00773 } 00774 else { 00775 s_firsthGLRc = m_hGlRc; 00776 } 00777 00778 if (m_hGlRc) { 00779 success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure; 00780 } 00781 else { 00782 success = GHOST_kFailure; 00783 } 00784 } 00785 else { 00786 success = GHOST_kFailure; 00787 } 00788 } 00789 else { 00790 success = GHOST_kFailure; 00791 } 00792 00793 if (success == GHOST_kFailure) { 00794 printf("Failed to get a context....\n"); 00795 } 00796 } 00797 else 00798 { 00799 if(m_stereoVisual) 00800 sPreferredFormat.dwFlags |= PFD_STEREO; 00801 00802 // Attempt to match device context pixel format to the preferred format 00803 int iPixelFormat = EnumPixelFormats(m_hDC); 00804 if (iPixelFormat == 0) { 00805 success = GHOST_kFailure; 00806 break; 00807 } 00808 if (::SetPixelFormat(m_hDC, iPixelFormat, &sPreferredFormat) == FALSE) { 00809 success = GHOST_kFailure; 00810 break; 00811 } 00812 // For debugging only: retrieve the pixel format chosen 00813 PIXELFORMATDESCRIPTOR preferredFormat; 00814 ::DescribePixelFormat(m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &preferredFormat); 00815 00816 // Create the context 00817 m_hGlRc = ::wglCreateContext(m_hDC); 00818 if (m_hGlRc) { 00819 if (::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE) { 00820 if (s_firsthGLRc) { 00821 if (is_crappy_intel_card()) { 00822 if (::wglMakeCurrent(NULL, NULL) == TRUE) { 00823 ::wglDeleteContext(m_hGlRc); 00824 m_hGlRc = s_firsthGLRc; 00825 } 00826 else { 00827 ::wglDeleteContext(m_hGlRc); 00828 m_hGlRc = NULL; 00829 } 00830 } 00831 else { 00832 ::wglShareLists(s_firsthGLRc, m_hGlRc); 00833 } 00834 } 00835 else { 00836 s_firsthGLRc = m_hGlRc; 00837 } 00838 00839 if (m_hGlRc) { 00840 success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure; 00841 } 00842 else { 00843 success = GHOST_kFailure; 00844 } 00845 } 00846 else { 00847 success = GHOST_kFailure; 00848 } 00849 } 00850 else { 00851 success = GHOST_kFailure; 00852 } 00853 00854 if (success == GHOST_kFailure) { 00855 printf("Failed to get a context....\n"); 00856 } 00857 00858 // Attempt to enable multisample 00859 if (m_multisample && WGL_ARB_multisample && !m_multisampleEnabled) 00860 { 00861 success = initMultisample(preferredFormat); 00862 00863 if (success) 00864 { 00865 00866 // Make sure we don't screw up the context 00867 if (m_hGlRc == s_firsthGLRc) 00868 s_firsthGLRc = NULL; 00869 m_drawingContextType = GHOST_kDrawingContextTypeOpenGL; 00870 removeDrawingContext(); 00871 00872 // Create a new window 00873 GHOST_TWindowState new_state = getState(); 00874 00875 m_nextWindow = new GHOST_WindowWin32((GHOST_SystemWin32*)GHOST_ISystem::getSystem(), 00876 m_title, 00877 m_left, 00878 m_top, 00879 m_width, 00880 m_height, 00881 new_state, 00882 type, 00883 m_stereo, 00884 m_multisample, 00885 m_parentWindowHwnd, 00886 m_multisampleEnabled, 00887 m_msPixelFormat); 00888 00889 // Return failure so we can trash this window. 00890 success = GHOST_kFailure; 00891 break; 00892 } else { 00893 m_multisampleEnabled = GHOST_kSuccess; 00894 printf("Multisample failed to initialized\n"); 00895 success = GHOST_kSuccess; 00896 } 00897 } 00898 } 00899 00900 } 00901 break; 00902 00903 case GHOST_kDrawingContextTypeNone: 00904 success = GHOST_kSuccess; 00905 break; 00906 00907 default: 00908 success = GHOST_kFailure; 00909 } 00910 return success; 00911 } 00912 00913 GHOST_TSuccess GHOST_WindowWin32::removeDrawingContext() 00914 { 00915 GHOST_TSuccess success; 00916 switch (m_drawingContextType) { 00917 case GHOST_kDrawingContextTypeOpenGL: 00918 // we shouldn't remove the drawing context if it's the first OpenGL context 00919 // If we do, we get corrupted drawing. See #19997 00920 if (m_hGlRc && m_hGlRc!=s_firsthGLRc) { 00921 success = ::wglDeleteContext(m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure; 00922 m_hGlRc = 0; 00923 } 00924 else { 00925 success = GHOST_kFailure; 00926 } 00927 break; 00928 case GHOST_kDrawingContextTypeNone: 00929 success = GHOST_kSuccess; 00930 break; 00931 default: 00932 success = GHOST_kFailure; 00933 } 00934 return success; 00935 } 00936 00937 void GHOST_WindowWin32::lostMouseCapture() 00938 { 00939 if(m_hasMouseCaptured) 00940 { m_hasGrabMouse = false; 00941 m_nPressedButtons = 0; 00942 m_hasMouseCaptured = false; 00943 }; 00944 } 00945 00946 void GHOST_WindowWin32::registerMouseClickEvent(int press) 00947 { 00948 00949 switch(press) 00950 { 00951 case 0: m_nPressedButtons++; break; 00952 case 1: if(m_nPressedButtons) m_nPressedButtons--; break; 00953 case 2: m_hasGrabMouse=true; break; 00954 case 3: m_hasGrabMouse=false; break; 00955 } 00956 00957 if(!m_nPressedButtons && !m_hasGrabMouse && m_hasMouseCaptured) 00958 { 00959 ::ReleaseCapture(); 00960 m_hasMouseCaptured = false; 00961 } 00962 else if((m_nPressedButtons || m_hasGrabMouse) && !m_hasMouseCaptured) 00963 { 00964 ::SetCapture(m_hWnd); 00965 m_hasMouseCaptured = true; 00966 00967 } 00968 } 00969 00970 00971 void GHOST_WindowWin32::loadCursor(bool visible, GHOST_TStandardCursor cursor) const 00972 { 00973 if (!visible) { 00974 while (::ShowCursor(FALSE) >= 0); 00975 } 00976 else { 00977 while (::ShowCursor(TRUE) < 0); 00978 } 00979 00980 if (cursor == GHOST_kStandardCursorCustom && m_customCursor) { 00981 ::SetCursor( m_customCursor ); 00982 } else { 00983 // Convert GHOST cursor to Windows OEM cursor 00984 bool success = true; 00985 LPCSTR id; 00986 switch (cursor) { 00987 case GHOST_kStandardCursorDefault: id = IDC_ARROW; break; 00988 case GHOST_kStandardCursorRightArrow: id = IDC_ARROW; break; 00989 case GHOST_kStandardCursorLeftArrow: id = IDC_ARROW; break; 00990 case GHOST_kStandardCursorInfo: id = IDC_SIZEALL; break; // Four-pointed arrow pointing north, south, east, and west 00991 case GHOST_kStandardCursorDestroy: id = IDC_NO; break; // Slashed circle 00992 case GHOST_kStandardCursorHelp: id = IDC_HELP; break; // Arrow and question mark 00993 case GHOST_kStandardCursorCycle: id = IDC_NO; break; // Slashed circle 00994 case GHOST_kStandardCursorSpray: id = IDC_SIZEALL; break; // Four-pointed arrow pointing north, south, east, and west 00995 case GHOST_kStandardCursorWait: id = IDC_WAIT; break; // Hourglass 00996 case GHOST_kStandardCursorText: id = IDC_IBEAM; break; // I-beam 00997 case GHOST_kStandardCursorCrosshair: id = IDC_CROSS; break; // Crosshair 00998 case GHOST_kStandardCursorUpDown: id = IDC_SIZENS; break; // Double-pointed arrow pointing north and south 00999 case GHOST_kStandardCursorLeftRight: id = IDC_SIZEWE; break; // Double-pointed arrow pointing west and east 01000 case GHOST_kStandardCursorTopSide: id = IDC_UPARROW; break; // Vertical arrow 01001 case GHOST_kStandardCursorBottomSide: id = IDC_SIZENS; break; 01002 case GHOST_kStandardCursorLeftSide: id = IDC_SIZEWE; break; 01003 case GHOST_kStandardCursorTopLeftCorner: id = IDC_SIZENWSE; break; 01004 case GHOST_kStandardCursorTopRightCorner: id = IDC_SIZENESW; break; 01005 case GHOST_kStandardCursorBottomRightCorner: id = IDC_SIZENWSE; break; 01006 case GHOST_kStandardCursorBottomLeftCorner: id = IDC_SIZENESW; break; 01007 case GHOST_kStandardCursorPencil: id = IDC_ARROW; break; 01008 case GHOST_kStandardCursorCopy: id = IDC_ARROW; break; 01009 default: 01010 success = false; 01011 } 01012 01013 if (success) { 01014 ::SetCursor(::LoadCursor(0, id)); 01015 } 01016 } 01017 } 01018 01019 GHOST_TSuccess GHOST_WindowWin32::setWindowCursorVisibility(bool visible) 01020 { 01021 if (::GetForegroundWindow() == m_hWnd) { 01022 loadCursor(visible, getCursorShape()); 01023 } 01024 01025 return GHOST_kSuccess; 01026 } 01027 01028 GHOST_TSuccess GHOST_WindowWin32::setWindowCursorGrab(GHOST_TGrabCursorMode mode) 01029 { 01030 if(mode != GHOST_kGrabDisable) { 01031 if(mode != GHOST_kGrabNormal) { 01032 m_system->getCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]); 01033 setCursorGrabAccum(0, 0); 01034 01035 if(mode == GHOST_kGrabHide) 01036 setWindowCursorVisibility(false); 01037 } 01038 registerMouseClickEvent(2); 01039 } 01040 else { 01041 if (m_cursorGrab==GHOST_kGrabHide) { 01042 m_system->setCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]); 01043 setWindowCursorVisibility(true); 01044 } 01045 if(m_cursorGrab != GHOST_kGrabNormal) { 01046 /* use to generate a mouse move event, otherwise the last event 01047 * blender gets can be outside the screen causing menus not to show 01048 * properly unless the user moves the mouse */ 01049 GHOST_TInt32 pos[2]; 01050 m_system->getCursorPosition(pos[0], pos[1]); 01051 m_system->setCursorPosition(pos[0], pos[1]); 01052 } 01053 01054 /* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */ 01055 setCursorGrabAccum(0, 0); 01056 m_cursorGrabBounds.m_l= m_cursorGrabBounds.m_r= -1; /* disable */ 01057 registerMouseClickEvent(3); 01058 } 01059 01060 return GHOST_kSuccess; 01061 } 01062 01063 GHOST_TSuccess GHOST_WindowWin32::setWindowCursorShape(GHOST_TStandardCursor cursorShape) 01064 { 01065 if (m_customCursor) { 01066 DestroyCursor(m_customCursor); 01067 m_customCursor = NULL; 01068 } 01069 01070 if (::GetForegroundWindow() == m_hWnd) { 01071 loadCursor(getCursorVisibility(), cursorShape); 01072 } 01073 01074 return GHOST_kSuccess; 01075 } 01076 01077 void GHOST_WindowWin32::processWin32TabletInitEvent() 01078 { 01079 if (m_wintab) { 01080 GHOST_WIN32_WTInfo fpWTInfo = ( GHOST_WIN32_WTInfo ) ::GetProcAddress( m_wintab, "WTInfoA" ); 01081 01082 // let's see if we can initialize tablet here 01083 /* check if WinTab available. */ 01084 if (fpWTInfo) { 01085 AXIS Pressure, Orientation[3]; /* The maximum tablet size */ 01086 01087 BOOL pressureSupport = fpWTInfo (WTI_DEVICES, DVC_NPRESSURE, &Pressure); 01088 if (pressureSupport) 01089 m_maxPressure = Pressure.axMax; 01090 else 01091 m_maxPressure = 0; 01092 01093 BOOL tiltSupport = fpWTInfo (WTI_DEVICES, DVC_ORIENTATION, &Orientation); 01094 if (tiltSupport) { 01095 /* does the tablet support azimuth ([0]) and altitude ([1]) */ 01096 if (Orientation[0].axResolution && Orientation[1].axResolution) { 01097 m_maxAzimuth = Orientation[0].axMax; 01098 m_maxAltitude = Orientation[1].axMax; 01099 } 01100 else { /* no so dont do tilt stuff */ 01101 m_maxAzimuth = m_maxAltitude = 0; 01102 } 01103 } 01104 01105 m_tabletData->Active = GHOST_kTabletModeNone; 01106 } 01107 } 01108 } 01109 01110 void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam) 01111 { 01112 PACKET pkt; 01113 if (m_wintab) { 01114 GHOST_WIN32_WTPacket fpWTPacket = ( GHOST_WIN32_WTPacket ) ::GetProcAddress( m_wintab, "WTPacket" ); 01115 if (fpWTPacket) { 01116 if (fpWTPacket((HCTX)lParam, wParam, &pkt)) { 01117 if (m_tabletData) { 01118 switch (pkt.pkCursor) { 01119 case 0: /* first device */ 01120 case 3: /* second device */ 01121 m_tabletData->Active = GHOST_kTabletModeNone; /* puck - not yet supported */ 01122 break; 01123 case 1: 01124 case 4: 01125 m_tabletData->Active = GHOST_kTabletModeStylus; /* stylus */ 01126 break; 01127 case 2: 01128 case 5: 01129 m_tabletData->Active = GHOST_kTabletModeEraser; /* eraser */ 01130 break; 01131 } 01132 if (m_maxPressure > 0) { 01133 m_tabletData->Pressure = (float)pkt.pkNormalPressure / (float)m_maxPressure; 01134 } else { 01135 m_tabletData->Pressure = 1.0f; 01136 } 01137 01138 if ((m_maxAzimuth > 0) && (m_maxAltitude > 0)) { 01139 ORIENTATION ort = pkt.pkOrientation; 01140 float vecLen; 01141 float altRad, azmRad; /* in radians */ 01142 01143 /* 01144 from the wintab spec: 01145 orAzimuth Specifies the clockwise rotation of the 01146 cursor about the z axis through a full circular range. 01147 01148 orAltitude Specifies the angle with the x-y plane 01149 through a signed, semicircular range. Positive values 01150 specify an angle upward toward the positive z axis; 01151 negative values specify an angle downward toward the negative z axis. 01152 01153 wintab.h defines .orAltitude as a UINT but documents .orAltitude 01154 as positive for upward angles and negative for downward angles. 01155 WACOM uses negative altitude values to show that the pen is inverted; 01156 therefore we cast .orAltitude as an (int) and then use the absolute value. 01157 */ 01158 01159 /* convert raw fixed point data to radians */ 01160 altRad = (float)((fabs((float)ort.orAltitude)/(float)m_maxAltitude) * M_PI/2.0); 01161 azmRad = (float)(((float)ort.orAzimuth/(float)m_maxAzimuth) * M_PI*2.0); 01162 01163 /* find length of the stylus' projected vector on the XY plane */ 01164 vecLen = cos(altRad); 01165 01166 /* from there calculate X and Y components based on azimuth */ 01167 m_tabletData->Xtilt = sin(azmRad) * vecLen; 01168 m_tabletData->Ytilt = (float)(sin(M_PI/2.0 - azmRad) * vecLen); 01169 01170 } else { 01171 m_tabletData->Xtilt = 0.0f; 01172 m_tabletData->Ytilt = 0.0f; 01173 } 01174 } 01175 } 01176 } 01177 } 01178 } 01179 01181 static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch) 01182 { 01183 ch= ((ch>>1)&0x55) | ((ch<<1)&0xAA); 01184 ch= ((ch>>2)&0x33) | ((ch<<2)&0xCC); 01185 ch= ((ch>>4)&0x0F) | ((ch<<4)&0xF0); 01186 return ch; 01187 } 01188 01190 static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt) 01191 { 01192 shrt= ((shrt>>1)&0x5555) | ((shrt<<1)&0xAAAA); 01193 shrt= ((shrt>>2)&0x3333) | ((shrt<<2)&0xCCCC); 01194 shrt= ((shrt>>4)&0x0F0F) | ((shrt<<4)&0xF0F0); 01195 shrt= ((shrt>>8)&0x00FF) | ((shrt<<8)&0xFF00); 01196 return shrt; 01197 } 01198 GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], 01199 GHOST_TUns8 mask[16][2], 01200 int hotX, int hotY) 01201 { 01202 return setWindowCustomCursorShape((GHOST_TUns8*)bitmap, (GHOST_TUns8*)mask, 01203 16, 16, hotX, hotY, 0, 1); 01204 } 01205 01206 GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(GHOST_TUns8 *bitmap, 01207 GHOST_TUns8 *mask, int sizeX, int sizeY, int hotX, int hotY, 01208 int fg_color, int bg_color) 01209 { 01210 GHOST_TUns32 andData[32]; 01211 GHOST_TUns32 xorData[32]; 01212 GHOST_TUns32 fullBitRow, fullMaskRow; 01213 int x, y, cols; 01214 01215 cols=sizeX/8; /* Num of whole bytes per row (width of bm/mask) */ 01216 if (sizeX%8) cols++; 01217 01218 if (m_customCursor) { 01219 DestroyCursor(m_customCursor); 01220 m_customCursor = NULL; 01221 } 01222 01223 memset(&andData, 0xFF, sizeof(andData)); 01224 memset(&xorData, 0, sizeof(xorData)); 01225 01226 for (y=0; y<sizeY; y++) { 01227 fullBitRow=0; 01228 fullMaskRow=0; 01229 for (x=cols-1; x>=0; x--){ 01230 fullBitRow<<=8; 01231 fullMaskRow<<=8; 01232 fullBitRow |= uns8ReverseBits(bitmap[cols*y + x]); 01233 fullMaskRow |= uns8ReverseBits( mask[cols*y + x]); 01234 } 01235 xorData[y]= fullBitRow & fullMaskRow; 01236 andData[y]= ~fullMaskRow; 01237 } 01238 01239 m_customCursor = ::CreateCursor(::GetModuleHandle(0), hotX, hotY, 32, 32, andData, xorData); 01240 if (!m_customCursor) { 01241 return GHOST_kFailure; 01242 } 01243 01244 if (::GetForegroundWindow() == m_hWnd) { 01245 loadCursor(getCursorVisibility(), GHOST_kStandardCursorCustom); 01246 } 01247 01248 return GHOST_kSuccess; 01249 } 01250 01251 01252 GHOST_TSuccess GHOST_WindowWin32::setProgressBar(float progress) 01253 { 01254 /*SetProgressValue sets state to TBPF_NORMAL automaticly*/ 01255 if(m_Bar && S_OK == m_Bar->SetProgressValue(m_hWnd,10000*progress,10000)) 01256 return GHOST_kSuccess; 01257 01258 return GHOST_kFailure; 01259 } 01260 01261 GHOST_TSuccess GHOST_WindowWin32::endProgressBar() 01262 { 01263 if(m_Bar && S_OK == m_Bar->SetProgressState(m_hWnd,TBPF_NOPROGRESS)) 01264 return GHOST_kSuccess; 01265 01266 return GHOST_kFailure; 01267 } 01268 01269 /* Ron Fosner's code for weighting pixel formats and forcing software. 01270 See http://www.opengl.org/resources/faq/technical/weight.cpp */ 01271 01272 static int WeightPixelFormat(PIXELFORMATDESCRIPTOR& pfd) 01273 { 01274 int weight = 0; 01275 01276 /* assume desktop color depth is 32 bits per pixel */ 01277 01278 /* cull unusable pixel formats */ 01279 /* if no formats can be found, can we determine why it was rejected? */ 01280 if( !(pfd.dwFlags & PFD_SUPPORT_OPENGL) || 01281 !(pfd.dwFlags & PFD_DRAW_TO_WINDOW) || 01282 !(pfd.dwFlags & PFD_DOUBLEBUFFER) || /* Blender _needs_ this */ 01283 ( pfd.cDepthBits <= 8 ) || 01284 !(pfd.iPixelType == PFD_TYPE_RGBA)) 01285 return 0; 01286 01287 weight = 1; /* it's usable */ 01288 01289 /* the bigger the depth buffer the better */ 01290 /* give no weight to a 16-bit depth buffer, because those are crap */ 01291 weight += pfd.cDepthBits - 16; 01292 01293 weight += pfd.cColorBits - 8; 01294 01295 /* want swap copy capability -- it matters a lot */ 01296 if(pfd.dwFlags & PFD_SWAP_COPY) weight += 16; 01297 01298 /* but if it's a generic (not accelerated) view, it's really bad */ 01299 if(pfd.dwFlags & PFD_GENERIC_FORMAT) weight /= 10; 01300 01301 return weight; 01302 } 01303 01304 /* A modification of Ron Fosner's replacement for ChoosePixelFormat */ 01305 /* returns 0 on error, else returns the pixel format number to be used */ 01306 static int EnumPixelFormats(HDC hdc) 01307 { 01308 int iPixelFormat; 01309 int i, n, w, weight = 0; 01310 PIXELFORMATDESCRIPTOR pfd; 01311 01312 /* we need a device context to do anything */ 01313 if(!hdc) return 0; 01314 01315 iPixelFormat = 1; /* careful! PFD numbers are 1 based, not zero based */ 01316 01317 /* obtain detailed information about 01318 the device context's first pixel format */ 01319 n = 1+::DescribePixelFormat(hdc, iPixelFormat, 01320 sizeof(PIXELFORMATDESCRIPTOR), &pfd); 01321 01322 /* choose a pixel format using the useless Windows function in case 01323 we come up empty handed */ 01324 iPixelFormat = ::ChoosePixelFormat( hdc, &sPreferredFormat ); 01325 01326 if(!iPixelFormat) return 0; /* couldn't find one to use */ 01327 01328 for(i=1; i<=n; i++) { /* not the idiom, but it's right */ 01329 ::DescribePixelFormat( hdc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd ); 01330 w = WeightPixelFormat(pfd); 01331 // be strict on stereo 01332 if (!((sPreferredFormat.dwFlags ^ pfd.dwFlags) & PFD_STEREO)) { 01333 if(w > weight) { 01334 weight = w; 01335 iPixelFormat = i; 01336 } 01337 } 01338 } 01339 if (weight == 0) { 01340 // we could find the correct stereo setting, just find any suitable format 01341 for(i=1; i<=n; i++) { /* not the idiom, but it's right */ 01342 ::DescribePixelFormat( hdc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd ); 01343 w = WeightPixelFormat(pfd); 01344 if(w > weight) { 01345 weight = w; 01346 iPixelFormat = i; 01347 } 01348 } 01349 } 01350 return iPixelFormat; 01351 } 01352 01353