00001
00032 #include "linden_common.h"
00033
00034 #if LL_WINDOWS && !LL_MESA_HEADLESS
00035
00036 #include "llwindowwin32.h"
00037
00038 #include <commdlg.h>
00039 #include <WinUser.h>
00040 #include <mapi.h>
00041 #include <process.h>
00042 #include <shellapi.h>
00043 #include <Imm.h>
00044
00045
00046 #define DIRECTINPUT_VERSION 0x0800
00047 #include <dinput.h>
00048
00049
00050 #include "llkeyboardwin32.h"
00051 #include "llerror.h"
00052 #include "llgl.h"
00053 #include "llstring.h"
00054 #include "lldir.h"
00055
00056 #include "llglheaders.h"
00057
00058 #include "indra_constants.h"
00059
00060
00061 #ifndef WM_MOUSEWHEEL
00062 const S32 WM_MOUSEWHEEL = 0x020A;
00063 #endif
00064 #ifndef WHEEL_DELTA
00065 const S32 WHEEL_DELTA = 120;
00066 #endif
00067 const S32 MAX_MESSAGE_PER_UPDATE = 20;
00068 const S32 BITS_PER_PIXEL = 32;
00069 const S32 MAX_NUM_RESOLUTIONS = 32;
00070 const F32 ICON_FLASH_TIME = 0.5f;
00071
00072 extern BOOL gDebugWindowProc;
00073
00074 LPWSTR gIconResource = IDI_APPLICATION;
00075
00076 LLW32MsgCallback gAsyncMsgCallback = NULL;
00077
00078
00079
00080
00081
00082 void show_window_creation_error(const char* title)
00083 {
00084 llwarns << title << llendl;
00085 shell_open( "help/window_creation_error.html");
00086 }
00087
00088
00089 BOOL LLWindowWin32::sIsClassRegistered = FALSE;
00090
00091 BOOL LLWindowWin32::sLanguageTextInputAllowed = TRUE;
00092 BOOL LLWindowWin32::sWinIMEOpened = FALSE;
00093 HKL LLWindowWin32::sWinInputLocale = 0;
00094 DWORD LLWindowWin32::sWinIMEConversionMode = IME_CMODE_NATIVE;
00095 DWORD LLWindowWin32::sWinIMESentenceMode = IME_SMODE_AUTOMATIC;
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 class LLWinImm
00107 {
00108 public:
00109 static bool isAvailable() { return sTheInstance.mHImmDll != NULL; }
00110
00111 public:
00112
00113 static BOOL isIME(HKL hkl);
00114 static HIMC getContext(HWND hwnd);
00115 static BOOL releaseContext(HWND hwnd, HIMC himc);
00116 static BOOL getOpenStatus(HIMC himc);
00117 static BOOL setOpenStatus(HIMC himc, BOOL status);
00118 static BOOL getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence);
00119 static BOOL setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence);
00120 static BOOL getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form);
00121 static BOOL setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form);
00122
00123 private:
00124 LLWinImm();
00125 ~LLWinImm();
00126
00127 private:
00128
00129 BOOL (WINAPI *mImmIsIME)(HKL);
00130 HIMC (WINAPI *mImmGetContext)(HWND);
00131 BOOL (WINAPI *mImmReleaseContext)(HWND, HIMC);
00132 BOOL (WINAPI *mImmGetOpenStatus)(HIMC);
00133 BOOL (WINAPI *mImmSetOpenStatus)(HIMC, BOOL);
00134 BOOL (WINAPI *mImmGetConversionStatus)(HIMC, LPDWORD, LPDWORD);
00135 BOOL (WINAPI *mImmSetConversionStatus)(HIMC, DWORD, DWORD);
00136 BOOL (WINAPI *mImmGetCompostitionWindow)(HIMC, LPCOMPOSITIONFORM);
00137 BOOL (WINAPI *mImmSetCompostitionWindow)(HIMC, LPCOMPOSITIONFORM);
00138
00139 private:
00140 HMODULE mHImmDll;
00141 static LLWinImm sTheInstance;
00142 };
00143
00144 LLWinImm LLWinImm::sTheInstance;
00145
00146 LLWinImm::LLWinImm() : mHImmDll(NULL)
00147 {
00148
00149 if ( !GetSystemMetrics( SM_DBCSENABLED ) )
00150 return;
00151
00152
00153 mHImmDll = LoadLibraryA("Imm32");
00154 if (mHImmDll != NULL)
00155 {
00156 mImmIsIME = (BOOL (WINAPI *)(HKL)) GetProcAddress(mHImmDll, "ImmIsIME");
00157 mImmGetContext = (HIMC (WINAPI *)(HWND)) GetProcAddress(mHImmDll, "ImmGetContext");
00158 mImmReleaseContext = (BOOL (WINAPI *)(HWND, HIMC)) GetProcAddress(mHImmDll, "ImmReleaseContext");
00159 mImmGetOpenStatus = (BOOL (WINAPI *)(HIMC)) GetProcAddress(mHImmDll, "ImmGetOpenStatus");
00160 mImmSetOpenStatus = (BOOL (WINAPI *)(HIMC, BOOL)) GetProcAddress(mHImmDll, "ImmSetOpenStatus");
00161 mImmGetConversionStatus = (BOOL (WINAPI *)(HIMC, LPDWORD, LPDWORD)) GetProcAddress(mHImmDll, "ImmGetConversionStatus");
00162 mImmSetConversionStatus = (BOOL (WINAPI *)(HIMC, DWORD, DWORD)) GetProcAddress(mHImmDll, "ImmSetConversionStatus");
00163 mImmGetCompostitionWindow = (BOOL (WINAPI *)(HIMC, LPCOMPOSITIONFORM)) GetProcAddress(mHImmDll, "ImmGetCompositionWindow");
00164 mImmSetCompostitionWindow = (BOOL (WINAPI *)(HIMC, LPCOMPOSITIONFORM)) GetProcAddress(mHImmDll, "ImmSetCompositionWindow");
00165
00166 if (mImmIsIME == NULL ||
00167 mImmGetContext == NULL ||
00168 mImmReleaseContext == NULL ||
00169 mImmGetOpenStatus == NULL ||
00170 mImmSetOpenStatus == NULL ||
00171 mImmGetConversionStatus == NULL ||
00172 mImmSetConversionStatus == NULL ||
00173 mImmGetCompostitionWindow == NULL ||
00174 mImmSetCompostitionWindow == NULL)
00175 {
00176
00177
00178
00179
00180
00181
00182
00183 FreeLibrary(mHImmDll);
00184 mHImmDll = NULL;
00185
00186
00187 mImmIsIME = NULL;
00188 mImmGetContext = NULL;
00189 mImmReleaseContext = NULL;
00190 mImmGetOpenStatus = NULL;
00191 mImmSetOpenStatus = NULL;
00192 mImmGetConversionStatus = NULL;
00193 mImmSetConversionStatus = NULL;
00194 mImmGetCompostitionWindow = NULL;
00195 mImmSetCompostitionWindow = NULL;
00196 }
00197 }
00198 }
00199
00200
00201
00202 BOOL LLWinImm::isIME(HKL hkl)
00203 {
00204 if ( sTheInstance.mImmIsIME )
00205 return sTheInstance.mImmIsIME(hkl);
00206 return FALSE;
00207 }
00208
00209
00210 HIMC LLWinImm::getContext(HWND hwnd)
00211 {
00212 if ( sTheInstance.mImmGetContext )
00213 return sTheInstance.mImmGetContext(hwnd);
00214 return 0;
00215 }
00216
00217
00218 BOOL LLWinImm::releaseContext(HWND hwnd, HIMC himc)
00219 {
00220 if ( sTheInstance.mImmIsIME )
00221 return sTheInstance.mImmReleaseContext(hwnd, himc);
00222 return FALSE;
00223 }
00224
00225
00226 BOOL LLWinImm::getOpenStatus(HIMC himc)
00227 {
00228 if ( sTheInstance.mImmGetOpenStatus )
00229 return sTheInstance.mImmGetOpenStatus(himc);
00230 return FALSE;
00231 }
00232
00233
00234 BOOL LLWinImm::setOpenStatus(HIMC himc, BOOL status)
00235 {
00236 if ( sTheInstance.mImmSetOpenStatus )
00237 return sTheInstance.mImmSetOpenStatus(himc, status);
00238 return FALSE;
00239 }
00240
00241
00242 BOOL LLWinImm::getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence)
00243 {
00244 if ( sTheInstance.mImmGetConversionStatus )
00245 return sTheInstance.mImmGetConversionStatus(himc, conversion, sentence);
00246 return FALSE;
00247 }
00248
00249
00250 BOOL LLWinImm::setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence)
00251 {
00252 if ( sTheInstance.mImmSetConversionStatus )
00253 return sTheInstance.mImmSetConversionStatus(himc, conversion, sentence);
00254 return FALSE;
00255 }
00256
00257
00258 BOOL LLWinImm::getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form)
00259 {
00260 if ( sTheInstance.mImmGetCompostitionWindow )
00261 return sTheInstance.mImmGetCompostitionWindow(himc, form);
00262 return FALSE;
00263 }
00264
00265
00266 BOOL LLWinImm::setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form)
00267 {
00268 if ( sTheInstance.mImmSetCompostitionWindow )
00269 return sTheInstance.mImmSetCompostitionWindow(himc, form);
00270 return FALSE;
00271 }
00272
00273
00274
00275 LLWinImm::~LLWinImm()
00276 {
00277 if (mHImmDll != NULL)
00278 {
00279 FreeLibrary(mHImmDll);
00280 mHImmDll = NULL;
00281 }
00282 }
00283
00284
00285 LPDIRECTINPUT8 g_pDI = NULL;
00286 LPDIRECTINPUTDEVICE8 g_pJoystick = NULL;
00287 BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance,
00288 VOID* pContext );
00289 BOOL CALLBACK EnumObjectsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
00290 VOID* pContext );
00291
00292
00293 LLWindowWin32::LLWindowWin32(char *title, char *name, S32 x, S32 y, S32 width,
00294 S32 height, U32 flags,
00295 BOOL fullscreen, BOOL clearBg,
00296 BOOL disable_vsync, BOOL use_gl,
00297 BOOL ignore_pixel_depth, S32 stereo_mode)
00298 : LLWindow(fullscreen, flags)
00299 {
00300 S32 i = 0;
00301 mIconResource = gIconResource;
00302 mOverrideAspectRatio = 0.f;
00303 mNativeAspectRatio = 0.f;
00304 mMousePositionModified = FALSE;
00305 mInputProcessingPaused = FALSE;
00306 mStereoMode = stereo_mode;
00307
00308
00309 gKeyboard = new LLKeyboardWin32();
00310
00311
00312
00313 allowLanguageTextInput(FALSE);
00314
00315 GLuint pixel_format;
00316 WNDCLASS wc;
00317 DWORD dw_ex_style;
00318 DWORD dw_style;
00319 RECT window_rect;
00320
00321
00322 if (!title)
00323 {
00324 mWindowTitle = new WCHAR[50];
00325 wsprintf(mWindowTitle, L"OpenGL Window");
00326 }
00327 else
00328 {
00329 mWindowTitle = new WCHAR[256];
00330 mbstowcs(mWindowTitle, title, 255);
00331 mWindowTitle[255] = 0;
00332 }
00333
00334
00335 if (!name)
00336 {
00337 mWindowClassName = new WCHAR[50];
00338 wsprintf(mWindowClassName, L"OpenGL Window");
00339 }
00340 else
00341 {
00342 mWindowClassName = new WCHAR[256];
00343 mbstowcs(mWindowClassName, name, 255);
00344 mWindowClassName[255] = 0;
00345 }
00346
00347
00348
00349 SetRect( &mOldMouseClip, 0, 0, 0, 0 );
00350
00351
00352 mhInstance = GetModuleHandle(NULL);
00353 mWndProc = NULL;
00354
00355 mSwapMethod = SWAP_METHOD_UNDEFINED;
00356
00357
00358 mLastSizeWParam = 0;
00359
00360
00361 window_rect.left = (long) 0;
00362 window_rect.right = (long) width;
00363 window_rect.top = (long) 0;
00364 window_rect.bottom = (long) height;
00365
00366
00367 S32 window_border_y = GetSystemMetrics(SM_CYBORDER);
00368 S32 virtual_screen_x = GetSystemMetrics(SM_XVIRTUALSCREEN);
00369 S32 virtual_screen_y = GetSystemMetrics(SM_YVIRTUALSCREEN);
00370 S32 virtual_screen_width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
00371 S32 virtual_screen_height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
00372
00373 if (x < virtual_screen_x) x = virtual_screen_x;
00374 if (y < virtual_screen_y - window_border_y) y = virtual_screen_y - window_border_y;
00375
00376 if (x + width > virtual_screen_x + virtual_screen_width) x = virtual_screen_x + virtual_screen_width - width;
00377 if (y + height > virtual_screen_y + virtual_screen_height) y = virtual_screen_y + virtual_screen_height - height;
00378
00379 if (!sIsClassRegistered)
00380 {
00381
00382
00383
00384 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
00385
00386
00387 wc.lpfnWndProc = (WNDPROC) mainWindowProc;
00388
00389
00390 wc.cbClsExtra = 0;
00391 wc.cbWndExtra = 0;
00392
00393 wc.hInstance = mhInstance;
00394 wc.hIcon = LoadIcon(mhInstance, mIconResource);
00395
00396
00397 wc.hCursor = NULL;
00398
00399
00400 if (clearBg)
00401 {
00402 wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
00403 }
00404 else
00405 {
00406 wc.hbrBackground = (HBRUSH) NULL;
00407 }
00408
00409
00410 wc.lpszMenuName = NULL;
00411
00412 wc.lpszClassName = mWindowClassName;
00413
00414 if (!RegisterClass(&wc))
00415 {
00416 OSMessageBox("RegisterClass failed", "Error", OSMB_OK);
00417 return;
00418 }
00419 sIsClassRegistered = TRUE;
00420 }
00421
00422
00423
00424
00425
00426 DEVMODE dev_mode;
00427 DWORD current_refresh;
00428 if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode))
00429 {
00430 current_refresh = dev_mode.dmDisplayFrequency;
00431 mNativeAspectRatio = ((F32)dev_mode.dmPelsWidth) / ((F32)dev_mode.dmPelsHeight);
00432 }
00433 else
00434 {
00435 current_refresh = 60;
00436 }
00437
00438
00439
00440
00441
00442
00443 if (mFullscreen)
00444 {
00445 BOOL success = FALSE;
00446 DWORD closest_refresh = 0;
00447
00448 for (S32 mode_num = 0;; mode_num++)
00449 {
00450 if (!EnumDisplaySettings(NULL, mode_num, &dev_mode))
00451 {
00452 break;
00453 }
00454
00455 if (dev_mode.dmPelsWidth == width &&
00456 dev_mode.dmPelsHeight == height &&
00457 dev_mode.dmBitsPerPel == BITS_PER_PIXEL)
00458 {
00459 success = TRUE;
00460 if ((dev_mode.dmDisplayFrequency - current_refresh)
00461 < (closest_refresh - current_refresh))
00462 {
00463 closest_refresh = dev_mode.dmDisplayFrequency;
00464 }
00465 }
00466 }
00467
00468 if (closest_refresh == 0)
00469 {
00470 llwarns << "Couldn't find display mode " << width << " by " << height << " at " << BITS_PER_PIXEL << " bits per pixel" << llendl;
00471 success = FALSE;
00472 }
00473
00474
00475 if (success)
00476 {
00477 success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh);
00478 }
00479
00480
00481
00482 EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode);
00483
00484
00485 if (success)
00486 {
00487 mFullscreen = TRUE;
00488 mFullscreenWidth = dev_mode.dmPelsWidth;
00489 mFullscreenHeight = dev_mode.dmPelsHeight;
00490 mFullscreenBits = dev_mode.dmBitsPerPel;
00491 mFullscreenRefresh = dev_mode.dmDisplayFrequency;
00492
00493 llinfos << "Running at " << dev_mode.dmPelsWidth
00494 << "x" << dev_mode.dmPelsHeight
00495 << "x" << dev_mode.dmBitsPerPel
00496 << " @ " << dev_mode.dmDisplayFrequency
00497 << llendl;
00498 }
00499 else
00500 {
00501 mFullscreen = FALSE;
00502 mFullscreenWidth = -1;
00503 mFullscreenHeight = -1;
00504 mFullscreenBits = -1;
00505 mFullscreenRefresh = -1;
00506
00507 char error[256];
00508 snprintf(error, sizeof(error), "Unable to run fullscreen at %d x %d.\nRunning in window.", width, height);
00509 OSMessageBox(error, "Error", OSMB_OK);
00510 }
00511 }
00512
00513
00514
00515
00516 if (mFullscreen)
00517 {
00518 dw_ex_style = WS_EX_APPWINDOW;
00519 dw_style = WS_POPUP;
00520
00521
00522 AdjustWindowRectEx(&window_rect, dw_style, FALSE, dw_ex_style);
00523 }
00524 else
00525 {
00526
00527 dw_ex_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
00528 dw_style = WS_OVERLAPPEDWINDOW;
00529 }
00530
00531
00532
00533
00534
00535
00536 mWindowHandle = CreateWindowEx(dw_ex_style,
00537 mWindowClassName,
00538 mWindowTitle,
00539 WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style,
00540 x,
00541 y,
00542 window_rect.right - window_rect.left,
00543 window_rect.bottom - window_rect.top,
00544 NULL,
00545 NULL,
00546 mhInstance,
00547 NULL);
00548
00549 if (!mWindowHandle)
00550 {
00551 OSMessageBox("Window creation error", "Error", OSMB_OK);
00552 return;
00553 }
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566 S32 pfdflags = PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
00567 if (use_gl)
00568 {
00569 pfdflags |= PFD_SUPPORT_OPENGL;
00570
00571
00572
00573
00574 if (mStereoMode == STEREO_MODE_ACTIVE) { pfdflags |= PFD_STEREO; }
00575
00576 }
00577
00578
00579
00580
00581 PIXELFORMATDESCRIPTOR pfd =
00582 {
00583 sizeof(PIXELFORMATDESCRIPTOR),
00584 1,
00585 pfdflags,
00586 PFD_TYPE_RGBA,
00587 BITS_PER_PIXEL,
00588 0, 0, 0, 0, 0, 0,
00589 8,
00590 0,
00591 0,
00592 0, 0, 0, 0,
00593 24,
00594 8,
00595 0,
00596 PFD_MAIN_PLANE,
00597 0,
00598 0, 0, 0
00599 };
00600
00601 if (!(mhDC = GetDC(mWindowHandle)))
00602 {
00603 close();
00604 OSMessageBox("Can't make GL device context", "Error", OSMB_OK);
00605 return;
00606 }
00607
00608 if (!(pixel_format = ChoosePixelFormat(mhDC, &pfd)))
00609 {
00610 close();
00611 OSMessageBox("Can't find suitable pixel format", "Error", OSMB_OK);
00612 return;
00613 }
00614
00615
00616 if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),
00617 &pfd))
00618 {
00619 close();
00620 OSMessageBox("Can't get pixel format description", "Error", OSMB_OK);
00621 return;
00622 }
00623
00624
00625 if (!ignore_pixel_depth && (pfd.cColorBits < 32))
00626 {
00627 close();
00628 OSMessageBox(
00629 "Second Life requires True Color (32-bit) to run in a window.\n"
00630 "Please go to Control Panels -> Display -> Settings and\n"
00631 "set the screen to 32-bit color.\n"
00632 "Alternately, if you choose to run fullscreen, Second Life\n"
00633 "will automatically adjust the screen each time it runs.",
00634 "Error",
00635 OSMB_OK);
00636 return;
00637 }
00638
00639 if (!ignore_pixel_depth && (pfd.cAlphaBits < 8))
00640 {
00641 close();
00642 OSMessageBox(
00643 "Second Life is unable to run because it can't get an 8 bit alpha\n"
00644 "channel. Usually this is due to video card driver issues.\n"
00645 "Please make sure you have the latest video card drivers installed.\n"
00646 "Also be sure your monitor is set to True Color (32-bit) in\n"
00647 "Control Panels -> Display -> Settings.\n"
00648 "If you continue to receive this message, contact customer service.",
00649 "Error",
00650 OSMB_OK);
00651 return;
00652 }
00653
00654 if (!SetPixelFormat(mhDC, pixel_format, &pfd))
00655 {
00656 close();
00657 OSMessageBox("Can't set pixel format", "Error", OSMB_OK);
00658 return;
00659 }
00660
00661 if (use_gl)
00662 {
00663 if (!(mhRC = wglCreateContext(mhDC)))
00664 {
00665 close();
00666 OSMessageBox("Can't create GL rendering context", "Error", OSMB_OK);
00667 return;
00668 }
00669
00670 if (!wglMakeCurrent(mhDC, mhRC))
00671 {
00672 close();
00673 OSMessageBox("Can't activate GL rendering context", "Error", OSMB_OK);
00674 return;
00675 }
00676
00677 gGLManager.initWGL();
00678
00679 if (gGLManager.mHasWGLARBPixelFormat && (wglChoosePixelFormatARB != NULL))
00680 {
00681
00682
00683 GLint attrib_list[256];
00684 S32 cur_attrib = 0;
00685
00686 attrib_list[cur_attrib++] = WGL_DEPTH_BITS_ARB;
00687 attrib_list[cur_attrib++] = 24;
00688
00689 attrib_list[cur_attrib++] = WGL_STENCIL_BITS_ARB;
00690 attrib_list[cur_attrib++] = 8;
00691
00692 attrib_list[cur_attrib++] = WGL_DRAW_TO_WINDOW_ARB;
00693 attrib_list[cur_attrib++] = GL_TRUE;
00694
00695 attrib_list[cur_attrib++] = WGL_ACCELERATION_ARB;
00696 attrib_list[cur_attrib++] = WGL_FULL_ACCELERATION_ARB;
00697
00698 attrib_list[cur_attrib++] = WGL_SUPPORT_OPENGL_ARB;
00699 attrib_list[cur_attrib++] = GL_TRUE;
00700
00701 attrib_list[cur_attrib++] = WGL_DOUBLE_BUFFER_ARB;
00702 attrib_list[cur_attrib++] = GL_TRUE;
00703
00704 attrib_list[cur_attrib++] = WGL_COLOR_BITS_ARB;
00705 attrib_list[cur_attrib++] = 24;
00706
00707 attrib_list[cur_attrib++] = WGL_RED_BITS_ARB;
00708 attrib_list[cur_attrib++] = 8;
00709
00710 attrib_list[cur_attrib++] = WGL_GREEN_BITS_ARB;
00711 attrib_list[cur_attrib++] = 8;
00712
00713 attrib_list[cur_attrib++] = WGL_BLUE_BITS_ARB;
00714 attrib_list[cur_attrib++] = 8;
00715
00716 attrib_list[cur_attrib++] = WGL_ALPHA_BITS_ARB;
00717 attrib_list[cur_attrib++] = 8;
00718
00719
00720 attrib_list[cur_attrib++] = 0;
00721
00722 GLint pixel_formats[256];
00723 U32 num_formats = 0;
00724
00725
00726 BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
00727 if (!result)
00728 {
00729 close();
00730 show_window_creation_error("Error after wglChoosePixelFormatARB 32-bit");
00731 return;
00732 }
00733
00734 if (!num_formats)
00735 {
00736 llinfos << "No 32 bit z-buffer, trying 24 bits instead" << llendl;
00737
00738 attrib_list[1] = 24;
00739 BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
00740 if (!result)
00741 {
00742 close();
00743 show_window_creation_error("Error after wglChoosePixelFormatARB 24-bit");
00744 return;
00745 }
00746
00747 if (!num_formats)
00748 {
00749 llwarns << "Couldn't get 24 bit z-buffer,trying 16 bits instead!" << llendl;
00750 attrib_list[1] = 16;
00751 BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
00752 if (!result || !num_formats)
00753 {
00754 close();
00755 show_window_creation_error("Error after wglChoosePixelFormatARB 16-bit");
00756 return;
00757 }
00758 }
00759
00760 llinfos << "Choosing pixel formats: " << num_formats << " pixel formats returned" << llendl;
00761
00762 pixel_format = pixel_formats[0];
00763 }
00764
00765 DestroyWindow(mWindowHandle);
00766
00767 mWindowHandle = CreateWindowEx(dw_ex_style,
00768 mWindowClassName,
00769 mWindowTitle,
00770 WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style,
00771 x,
00772 y,
00773 window_rect.right - window_rect.left,
00774 window_rect.bottom - window_rect.top,
00775 NULL,
00776 NULL,
00777 mhInstance,
00778 NULL);
00779
00780 if (!(mhDC = GetDC(mWindowHandle)))
00781 {
00782 close();
00783 OSMessageBox("Can't make GL device context", "Error", OSMB_OK);
00784 return;
00785 }
00786
00787 if (!SetPixelFormat(mhDC, pixel_format, &pfd))
00788 {
00789 close();
00790 OSMessageBox("Can't set pixel format", "Error", OSMB_OK);
00791 return;
00792 }
00793
00794 int swap_method = 0;
00795 GLint swap_query = WGL_SWAP_METHOD_ARB;
00796
00797 if (wglGetPixelFormatAttribivARB(mhDC, pixel_format, 0, 1, &swap_query, &swap_method))
00798 {
00799 switch (swap_method)
00800 {
00801 case WGL_SWAP_EXCHANGE_ARB:
00802 mSwapMethod = SWAP_METHOD_EXCHANGE;
00803 llinfos << "Swap Method: Exchange" << llendl;
00804 break;
00805 case WGL_SWAP_COPY_ARB:
00806 mSwapMethod = SWAP_METHOD_COPY;
00807 llinfos << "Swap Method: Copy" << llendl;
00808 break;
00809 case WGL_SWAP_UNDEFINED_ARB:
00810 mSwapMethod = SWAP_METHOD_UNDEFINED;
00811 llinfos << "Swap Method: Undefined" << llendl;
00812 break;
00813 default:
00814 mSwapMethod = SWAP_METHOD_UNDEFINED;
00815 llinfos << "Swap Method: Unknown" << llendl;
00816 break;
00817 }
00818 }
00819 }
00820 else
00821 {
00822 llwarns << "No wgl_ARB_pixel_format extension, using default ChoosePixelFormat!" << llendl;
00823 }
00824
00825
00826 if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),
00827 &pfd))
00828 {
00829 close();
00830 OSMessageBox("Can't get pixel format description", "Error", OSMB_OK);
00831 return;
00832 }
00833 llinfos << "GL buffer: Color Bits " << S32(pfd.cColorBits)
00834 << " Alpha Bits " << S32(pfd.cAlphaBits)
00835 << " Depth Bits " << S32(pfd.cDepthBits)
00836 << llendl;
00837
00838 if (pfd.cColorBits < 32)
00839 {
00840 close();
00841 OSMessageBox(
00842 "Second Life requires True Color (32-bit) to run in a window.\n"
00843 "Please go to Control Panels -> Display -> Settings and\n"
00844 "set the screen to 32-bit color.\n"
00845 "Alternately, if you choose to run fullscreen, Second Life\n"
00846 "will automatically adjust the screen each time it runs.",
00847 "Error",
00848 OSMB_OK);
00849 return;
00850 }
00851
00852 if (pfd.cAlphaBits < 8)
00853 {
00854 close();
00855 OSMessageBox(
00856 "Second Life is unable to run because it can't get an 8 bit alpha\n"
00857 "channel. Usually this is due to video card driver issues.\n"
00858 "Please make sure you have the latest video card drivers installed.\n"
00859 "Also be sure your monitor is set to True Color (32-bit) in\n"
00860 "Control Panels -> Display -> Settings.\n"
00861 "If you continue to receive this message, contact customer service.",
00862 "Error",
00863 OSMB_OK);
00864 return;
00865 }
00866
00867 if (!(mhRC = wglCreateContext(mhDC)))
00868 {
00869 close();
00870 OSMessageBox("Can't create GL rendering context", "Error", OSMB_OK);
00871 return;
00872 }
00873
00874 if (!wglMakeCurrent(mhDC, mhRC))
00875 {
00876 close();
00877 OSMessageBox("Can't activate GL rendering context", "Error", OSMB_OK);
00878 return;
00879 }
00880
00881 if (!gGLManager.initGL())
00882 {
00883 close();
00884 OSMessageBox(
00885 "Second Life is unable to run because your video card drivers\n"
00886 "are out of date or unsupported. Please make sure you have\n"
00887 "the latest video card drivers installed.\n\n"
00888 "If you continue to receive this message, contact customer service.",
00889 "Error",
00890 OSMB_OK);
00891 return;
00892 }
00893
00894
00895 if (disable_vsync && wglSwapIntervalEXT)
00896 {
00897 llinfos << "Disabling vertical sync" << llendl;
00898 wglSwapIntervalEXT(0);
00899 }
00900 else
00901 {
00902 llinfos << "Keeping vertical sync" << llendl;
00903 }
00904
00905
00906
00907 mCurrentGamma = 0.f;
00908 if (!GetDeviceGammaRamp(mhDC, mPrevGammaRamp))
00909 {
00910 llwarns << "Unable to get device gamma ramp" << llendl;
00911 }
00912
00913
00914
00915
00916
00917
00918
00919 F32 Csum = 0.0;
00920 S32 Ccount = 0;
00921 for (i = 0; i < 256; i++)
00922 {
00923 if (i != 0 && mPrevGammaRamp[i] != 0 && mPrevGammaRamp[i] != 65536)
00924 {
00925 F64 B = (i % 256) / 256.0;
00926 F64 A = mPrevGammaRamp[i] / 65536.0;
00927 F32 C = (F32) ( log(A) / log(B) );
00928 Csum += C;
00929 Ccount++;
00930 }
00931 }
00932 mCurrentGamma = Csum / Ccount;
00933
00934 llinfos << "Previous gamma: " << mCurrentGamma << llendl;
00935 }
00936
00937
00938
00939
00940 if((mStereoMode==STEREO_MODE_ACTIVE) && ((pfd.dwFlags & PFD_STEREO)==0))
00941 { mStereoMode = STEREO_MODE_NONE; }
00942
00943
00944
00945 SetWindowLong(mWindowHandle, GWL_USERDATA, (U32)this);
00946
00947
00948 initCursors();
00949 setCursor( UI_CURSOR_ARROW );
00950
00951
00952 HRESULT hr;
00953
00954 if( FAILED( hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION,
00955 IID_IDirectInput8, (VOID**)&g_pDI, NULL ) ) )
00956 {
00957 llwarns << "Direct8InputCreate failed!" << llendl;
00958 }
00959 else
00960 {
00961 while(1)
00962 {
00963
00964 if (FAILED( hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL,
00965 EnumJoysticksCallback,
00966 NULL, DIEDFL_ATTACHEDONLY ) ) )
00967 break;
00968 if (!g_pJoystick)
00969 break;
00970 if( FAILED( hr = g_pJoystick->SetDataFormat( &c_dfDIJoystick ) ) )
00971 break;
00972 if( FAILED( hr = g_pJoystick->EnumObjects( EnumObjectsCallback,
00973 (VOID*)mWindowHandle, DIDFT_ALL ) ) )
00974 break;
00975 g_pJoystick->Acquire();
00976 break;
00977 }
00978 }
00979
00980 SetTimer( mWindowHandle, 0, 1000 / 30, NULL );
00981 }
00982
00983
00984 LLWindowWin32::~LLWindowWin32()
00985 {
00986 delete [] mWindowTitle;
00987 mWindowTitle = NULL;
00988
00989 delete [] mSupportedResolutions;
00990 mSupportedResolutions = NULL;
00991
00992 delete mWindowClassName;
00993 mWindowClassName = NULL;
00994 }
00995
00996 void LLWindowWin32::show()
00997 {
00998 ShowWindow(mWindowHandle, SW_SHOW);
00999 SetForegroundWindow(mWindowHandle);
01000 SetFocus(mWindowHandle);
01001 }
01002
01003 void LLWindowWin32::hide()
01004 {
01005 setMouseClipping(FALSE);
01006 ShowWindow(mWindowHandle, SW_HIDE);
01007 }
01008
01009 void LLWindowWin32::minimize()
01010 {
01011 setMouseClipping(FALSE);
01012 showCursor();
01013 ShowWindow(mWindowHandle, SW_MINIMIZE);
01014 }
01015
01016
01017 void LLWindowWin32::restore()
01018 {
01019 ShowWindow(mWindowHandle, SW_RESTORE);
01020 SetForegroundWindow(mWindowHandle);
01021 SetFocus(mWindowHandle);
01022 }
01023
01024
01025
01026
01027 void LLWindowWin32::close()
01028 {
01029 llinfos << "Closing LLWindowWin32" << llendl;
01030
01031 if (!mWindowHandle)
01032 {
01033 return;
01034 }
01035
01036
01037 setMouseClipping(FALSE);
01038 showCursor();
01039
01040
01041 if (mFullscreen)
01042 {
01043 resetDisplayResolution();
01044 }
01045
01046
01047 llinfos << "Shutting down GL" << llendl;
01048 gGLManager.shutdownGL();
01049
01050 llinfos << "Releasing Context" << llendl;
01051 if (mhRC)
01052 {
01053 if (!wglMakeCurrent(NULL, NULL))
01054 {
01055 llwarns << "Release of DC and RC failed" << llendl;
01056 }
01057
01058 if (!wglDeleteContext(mhRC))
01059 {
01060 llwarns << "Release of rendering context failed" << llendl;
01061 }
01062
01063 mhRC = NULL;
01064 }
01065
01066
01067 restoreGamma();
01068
01069 if (mhDC && !ReleaseDC(mWindowHandle, mhDC))
01070 {
01071 llwarns << "Release of ghDC failed" << llendl;
01072 mhDC = NULL;
01073 }
01074
01075 llinfos << "Destroying Window" << llendl;
01076
01077
01078 SetWindowLong(mWindowHandle, GWL_USERDATA, NULL);
01079
01080
01081 ShowWindow(mWindowHandle, SW_HIDE);
01082
01083
01084 if (!DestroyWindow(mWindowHandle))
01085 {
01086 OSMessageBox("DestroyWindow(mWindowHandle) failed", "Shutdown Error", OSMB_OK);
01087 }
01088
01089 mWindowHandle = NULL;
01090 }
01091
01092 BOOL LLWindowWin32::isValid()
01093 {
01094 return (mWindowHandle != NULL);
01095 }
01096
01097 BOOL LLWindowWin32::getVisible()
01098 {
01099 return (mWindowHandle && IsWindowVisible(mWindowHandle));
01100 }
01101
01102 BOOL LLWindowWin32::getMinimized()
01103 {
01104 return (mWindowHandle && IsIconic(mWindowHandle));
01105 }
01106
01107 BOOL LLWindowWin32::getMaximized()
01108 {
01109 return (mWindowHandle && IsZoomed(mWindowHandle));
01110 }
01111
01112 BOOL LLWindowWin32::maximize()
01113 {
01114 BOOL success = FALSE;
01115 if (!mWindowHandle) return success;
01116
01117 WINDOWPLACEMENT placement;
01118 placement.length = sizeof(WINDOWPLACEMENT);
01119
01120 success = GetWindowPlacement(mWindowHandle, &placement);
01121 if (!success) return success;
01122
01123 placement.showCmd = SW_MAXIMIZE;
01124
01125 success = SetWindowPlacement(mWindowHandle, &placement);
01126 return success;
01127 }
01128
01129 BOOL LLWindowWin32::getFullscreen()
01130 {
01131 return mFullscreen;
01132 }
01133
01134 BOOL LLWindowWin32::getPosition(LLCoordScreen *position)
01135 {
01136 RECT window_rect;
01137
01138 if (!mWindowHandle ||
01139 !GetWindowRect(mWindowHandle, &window_rect) ||
01140 NULL == position)
01141 {
01142 return FALSE;
01143 }
01144
01145 position->mX = window_rect.left;
01146 position->mY = window_rect.top;
01147 return TRUE;
01148 }
01149
01150 BOOL LLWindowWin32::getSize(LLCoordScreen *size)
01151 {
01152 RECT window_rect;
01153
01154 if (!mWindowHandle ||
01155 !GetWindowRect(mWindowHandle, &window_rect) ||
01156 NULL == size)
01157 {
01158 return FALSE;
01159 }
01160
01161 size->mX = window_rect.right - window_rect.left;
01162 size->mY = window_rect.bottom - window_rect.top;
01163 return TRUE;
01164 }
01165
01166 BOOL LLWindowWin32::getSize(LLCoordWindow *size)
01167 {
01168 RECT client_rect;
01169
01170 if (!mWindowHandle ||
01171 !GetClientRect(mWindowHandle, &client_rect) ||
01172 NULL == size)
01173 {
01174 return FALSE;
01175 }
01176
01177 size->mX = client_rect.right - client_rect.left;
01178 size->mY = client_rect.bottom - client_rect.top;
01179 return TRUE;
01180 }
01181
01182 BOOL LLWindowWin32::setPosition(const LLCoordScreen position)
01183 {
01184 LLCoordScreen size;
01185
01186 if (!mWindowHandle)
01187 {
01188 return FALSE;
01189 }
01190 getSize(&size);
01191 moveWindow(position, size);
01192 return TRUE;
01193 }
01194
01195 BOOL LLWindowWin32::setSize(const LLCoordScreen size)
01196 {
01197 LLCoordScreen position;
01198
01199 getPosition(&position);
01200 if (!mWindowHandle)
01201 {
01202 return FALSE;
01203 }
01204
01205 moveWindow(position, size);
01206 return TRUE;
01207 }
01208
01209
01210 BOOL LLWindowWin32::switchContext(BOOL fullscreen, LLCoordScreen size, BOOL disable_vsync)
01211 {
01212 GLuint pixel_format;
01213 DEVMODE dev_mode;
01214 DWORD current_refresh;
01215 DWORD dw_ex_style;
01216 DWORD dw_style;
01217 RECT window_rect;
01218 S32 width = size.mX;
01219 S32 height = size.mY;
01220
01221 resetDisplayResolution();
01222
01223 if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode))
01224 {
01225 current_refresh = dev_mode.dmDisplayFrequency;
01226 }
01227 else
01228 {
01229 current_refresh = 60;
01230 }
01231
01232 gGLManager.shutdownGL();
01233
01234 if (mhRC)
01235 {
01236 if (!wglMakeCurrent(NULL, NULL))
01237 {
01238 llwarns << "Release of DC and RC failed" << llendl;
01239 }
01240
01241 if (!wglDeleteContext(mhRC))
01242 {
01243 llwarns << "Release of rendering context failed" << llendl;
01244 }
01245
01246 mhRC = NULL;
01247 }
01248
01249 if (fullscreen)
01250 {
01251 mFullscreen = TRUE;
01252 BOOL success = FALSE;
01253 DWORD closest_refresh = 0;
01254
01255 for (S32 mode_num = 0;; mode_num++)
01256 {
01257 if (!EnumDisplaySettings(NULL, mode_num, &dev_mode))
01258 {
01259 break;
01260 }
01261
01262 if (dev_mode.dmPelsWidth == width &&
01263 dev_mode.dmPelsHeight == height &&
01264 dev_mode.dmBitsPerPel == BITS_PER_PIXEL)
01265 {
01266 success = TRUE;
01267 if ((dev_mode.dmDisplayFrequency - current_refresh)
01268 < (closest_refresh - current_refresh))
01269 {
01270 closest_refresh = dev_mode.dmDisplayFrequency;
01271 }
01272 }
01273 }
01274
01275 if (closest_refresh == 0)
01276 {
01277 llwarns << "Couldn't find display mode " << width << " by " << height << " at " << BITS_PER_PIXEL << " bits per pixel" << llendl;
01278 return FALSE;
01279 }
01280
01281
01282 if (success)
01283 {
01284 success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh);
01285 }
01286
01287
01288
01289 EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode);
01290
01291 if (success)
01292 {
01293 mFullscreen = TRUE;
01294 mFullscreenWidth = dev_mode.dmPelsWidth;
01295 mFullscreenHeight = dev_mode.dmPelsHeight;
01296 mFullscreenBits = dev_mode.dmBitsPerPel;
01297 mFullscreenRefresh = dev_mode.dmDisplayFrequency;
01298
01299 llinfos << "Running at " << dev_mode.dmPelsWidth
01300 << "x" << dev_mode.dmPelsHeight
01301 << "x" << dev_mode.dmBitsPerPel
01302 << " @ " << dev_mode.dmDisplayFrequency
01303 << llendl;
01304
01305 window_rect.left = (long) 0;
01306 window_rect.right = (long) width;
01307 window_rect.top = (long) 0;
01308 window_rect.bottom = (long) height;
01309 dw_ex_style = WS_EX_APPWINDOW;
01310 dw_style = WS_POPUP;
01311
01312
01313 AdjustWindowRectEx(&window_rect, dw_style, FALSE, dw_ex_style);
01314 }
01315
01316 else
01317 {
01318 mFullscreen = FALSE;
01319 mFullscreenWidth = -1;
01320 mFullscreenHeight = -1;
01321 mFullscreenBits = -1;
01322 mFullscreenRefresh = -1;
01323
01324 llinfos << "Unable to run fullscreen at " << width << "x" << height << llendl;
01325 llinfos << "Running in window." << llendl;
01326 return FALSE;
01327 }
01328 }
01329 else
01330 {
01331 mFullscreen = FALSE;
01332 window_rect.left = (long) 0;
01333 window_rect.right = (long) width;
01334 window_rect.top = (long) 0;
01335 window_rect.bottom = (long) height;
01336
01337 dw_ex_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
01338 dw_style = WS_OVERLAPPEDWINDOW;
01339 }
01340
01341
01342 mPostQuit = FALSE;
01343
01344
01345 DestroyWindow(mWindowHandle);
01346 mWindowHandle = CreateWindowEx(dw_ex_style,
01347 mWindowClassName,
01348 mWindowTitle,
01349 WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style,
01350 window_rect.left,
01351 window_rect.top,
01352 window_rect.right - window_rect.left,
01353 window_rect.bottom - window_rect.top,
01354 NULL,
01355 NULL,
01356 mhInstance,
01357 NULL);
01358
01359
01360
01361
01362 static PIXELFORMATDESCRIPTOR pfd =
01363 {
01364 sizeof(PIXELFORMATDESCRIPTOR),
01365 1,
01366 PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
01367 PFD_TYPE_RGBA,
01368 BITS_PER_PIXEL,
01369 0, 0, 0, 0, 0, 0,
01370 8,
01371 0,
01372 0,
01373 0, 0, 0, 0,
01374 24,
01375 8,
01376 0,
01377 PFD_MAIN_PLANE,
01378 0,
01379 0, 0, 0
01380 };
01381
01382 if (!(mhDC = GetDC(mWindowHandle)))
01383 {
01384 close();
01385 OSMessageBox("Can't make GL device context", "Error", OSMB_OK);
01386 return FALSE;
01387 }
01388
01389 if (!(pixel_format = ChoosePixelFormat(mhDC, &pfd)))
01390 {
01391 close();
01392 OSMessageBox("Can't find suitable pixel format", "Error", OSMB_OK);
01393 return FALSE;
01394 }
01395
01396
01397 if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),
01398 &pfd))
01399 {
01400 close();
01401 OSMessageBox("Can't get pixel format description", "Error", OSMB_OK);
01402 return FALSE;
01403 }
01404
01405 if (pfd.cColorBits < 32)
01406 {
01407 close();
01408 OSMessageBox(
01409 "Second Life requires True Color (32-bit) to run in a window.\n"
01410 "Please go to Control Panels -> Display -> Settings and\n"
01411 "set the screen to 32-bit color.\n"
01412 "Alternately, if you choose to run fullscreen, Second Life\n"
01413 "will automatically adjust the screen each time it runs.",
01414 "Error",
01415 OSMB_OK);
01416 return FALSE;
01417 }
01418
01419 if (pfd.cAlphaBits < 8)
01420 {
01421 close();
01422 OSMessageBox(
01423 "Second Life is unable to run because it can't get an 8 bit alpha\n"
01424 "channel. Usually this is due to video card driver issues.\n"
01425 "Please make sure you have the latest video card drivers installed.\n"
01426 "Also be sure your monitor is set to True Color (32-bit) in\n"
01427 "Control Panels -> Display -> Settings.\n"
01428 "If you continue to receive this message, contact customer service.",
01429 "Error",
01430 OSMB_OK);
01431 return FALSE;
01432 }
01433
01434 if (!SetPixelFormat(mhDC, pixel_format, &pfd))
01435 {
01436 close();
01437 OSMessageBox("Can't set pixel format", "Error", OSMB_OK);
01438 return FALSE;
01439 }
01440
01441 if (!(mhRC = wglCreateContext(mhDC)))
01442 {
01443 close();
01444 OSMessageBox("Can't create GL rendering context", "Error", OSMB_OK);
01445 return FALSE;
01446 }
01447
01448 if (!wglMakeCurrent(mhDC, mhRC))
01449 {
01450 close();
01451 OSMessageBox("Can't activate GL rendering context", "Error", OSMB_OK);
01452 return FALSE;
01453 }
01454
01455 gGLManager.initWGL();
01456
01457 if (wglChoosePixelFormatARB)
01458 {
01459
01460
01461 GLint attrib_list[256];
01462 S32 cur_attrib = 0;
01463
01464 attrib_list[cur_attrib++] = WGL_DEPTH_BITS_ARB;
01465 attrib_list[cur_attrib++] = 24;
01466
01467 attrib_list[cur_attrib++] = WGL_STENCIL_BITS_ARB;
01468 attrib_list[cur_attrib++] = 8;
01469
01470 attrib_list[cur_attrib++] = WGL_DRAW_TO_WINDOW_ARB;
01471 attrib_list[cur_attrib++] = GL_TRUE;
01472
01473 attrib_list[cur_attrib++] = WGL_ACCELERATION_ARB;
01474 attrib_list[cur_attrib++] = WGL_FULL_ACCELERATION_ARB;
01475
01476 attrib_list[cur_attrib++] = WGL_SUPPORT_OPENGL_ARB;
01477 attrib_list[cur_attrib++] = GL_TRUE;
01478
01479 attrib_list[cur_attrib++] = WGL_DOUBLE_BUFFER_ARB;
01480 attrib_list[cur_attrib++] = GL_TRUE;
01481
01482 attrib_list[cur_attrib++] = WGL_COLOR_BITS_ARB;
01483 attrib_list[cur_attrib++] = 24;
01484
01485 attrib_list[cur_attrib++] = WGL_RED_BITS_ARB;
01486 attrib_list[cur_attrib++] = 8;
01487
01488 attrib_list[cur_attrib++] = WGL_GREEN_BITS_ARB;
01489 attrib_list[cur_attrib++] = 8;
01490
01491 attrib_list[cur_attrib++] = WGL_BLUE_BITS_ARB;
01492 attrib_list[cur_attrib++] = 8;
01493
01494 attrib_list[cur_attrib++] = WGL_ALPHA_BITS_ARB;
01495 attrib_list[cur_attrib++] = 8;
01496
01497
01498 attrib_list[cur_attrib++] = 0;
01499
01500 GLint pixel_formats[256];
01501 U32 num_formats = 0;
01502
01503
01504 BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
01505 if (!result)
01506 {
01507 close();
01508 show_window_creation_error("Error after wglChoosePixelFormatARB 32-bit");
01509 return FALSE;
01510 }
01511
01512 if (!num_formats)
01513 {
01514 llinfos << "No 32 bit z-buffer, trying 24 bits instead" << llendl;
01515
01516 attrib_list[1] = 24;
01517 BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
01518 if (!result)
01519 {
01520 close();
01521 show_window_creation_error("Error after wglChoosePixelFormatARB 24-bit");
01522 return FALSE;
01523 }
01524
01525 if (!num_formats)
01526 {
01527 llwarns << "Couldn't get 24 bit z-buffer,trying 16 bits instead!" << llendl;
01528 attrib_list[1] = 16;
01529 BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
01530 if (!result || !num_formats)
01531 {
01532 close();
01533 show_window_creation_error("Error after wglChoosePixelFormatARB 16-bit");
01534 return FALSE;
01535 }
01536 }
01537
01538 llinfos << "Choosing pixel formats: " << num_formats << " pixel formats returned" << llendl;
01539
01540 pixel_format = pixel_formats[0];
01541 }
01542
01543 DestroyWindow(mWindowHandle);
01544 mWindowHandle = CreateWindowEx(dw_ex_style,
01545 mWindowClassName,
01546 mWindowTitle,
01547 WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style,
01548 window_rect.left,
01549 window_rect.top,
01550 window_rect.right - window_rect.left,
01551 window_rect.bottom - window_rect.top,
01552 NULL,
01553 NULL,
01554 mhInstance,
01555 NULL);
01556
01557 if (!(mhDC = GetDC(mWindowHandle)))
01558 {
01559 close();
01560 OSMessageBox("Can't make GL device context", "Error", OSMB_OK);
01561 return FALSE;
01562 }
01563
01564 if (!SetPixelFormat(mhDC, pixel_format, &pfd))
01565 {
01566 close();
01567 OSMessageBox("Can't set pixel format", "Error", OSMB_OK);
01568 return FALSE;
01569 }
01570
01571 int swap_method = 0;
01572 GLint swap_query = WGL_SWAP_METHOD_ARB;
01573
01574 if (wglGetPixelFormatAttribivARB(mhDC, pixel_format, 0, 1, &swap_query, &swap_method))
01575 {
01576 switch (swap_method)
01577 {
01578 case WGL_SWAP_EXCHANGE_ARB:
01579 mSwapMethod = SWAP_METHOD_EXCHANGE;
01580 llinfos << "Swap Method: Exchange" << llendl;
01581 break;
01582 case WGL_SWAP_COPY_ARB:
01583 mSwapMethod = SWAP_METHOD_COPY;
01584 llinfos << "Swap Method: Copy" << llendl;
01585 break;
01586 case WGL_SWAP_UNDEFINED_ARB:
01587 mSwapMethod = SWAP_METHOD_UNDEFINED;
01588 llinfos << "Swap Method: Undefined" << llendl;
01589 break;
01590 default:
01591 mSwapMethod = SWAP_METHOD_UNDEFINED;
01592 llinfos << "Swap Method: Unknown" << llendl;
01593 break;
01594 }
01595 }
01596 }
01597 else
01598 {
01599 llwarns << "No wgl_ARB_pixel_format extension, using default ChoosePixelFormat!" << llendl;
01600 }
01601
01602
01603 if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),
01604 &pfd))
01605 {
01606 close();
01607 OSMessageBox("Can't get pixel format description", "Error", OSMB_OK);
01608 return FALSE;
01609 }
01610
01611 llinfos << "GL buffer: Color Bits " << S32(pfd.cColorBits)
01612 << " Alpha Bits " << S32(pfd.cAlphaBits)
01613 << " Depth Bits " << S32(pfd.cDepthBits)
01614 << llendl;
01615
01616 if (pfd.cColorBits < 32)
01617 {
01618 close();
01619 OSMessageBox(
01620 "Second Life requires True Color (32-bit) to run in a window.\n"
01621 "Please go to Control Panels -> Display -> Settings and\n"
01622 "set the screen to 32-bit color.\n"
01623 "Alternately, if you choose to run fullscreen, Second Life\n"
01624 "will automatically adjust the screen each time it runs.",
01625 "Error",
01626 OSMB_OK);
01627 return FALSE;
01628 }
01629
01630 if (pfd.cAlphaBits < 8)
01631 {
01632 close();
01633 OSMessageBox(
01634 "Second Life is unable to run because it can't get an 8 bit alpha\n"
01635 "channel. Usually this is due to video card driver issues.\n"
01636 "Please make sure you have the latest video card drivers installed.\n"
01637 "Also be sure your monitor is set to True Color (32-bit) in\n"
01638 "Control Panels -> Display -> Settings.\n"
01639 "If you continue to receive this message, contact customer service.",
01640 "Error",
01641 OSMB_OK);
01642 return FALSE;
01643 }
01644
01645 if (!(mhRC = wglCreateContext(mhDC)))
01646 {
01647 close();
01648 OSMessageBox("Can't create GL rendering context", "Error", OSMB_OK);
01649 return FALSE;
01650 }
01651
01652 if (!wglMakeCurrent(mhDC, mhRC))
01653 {
01654 close();
01655 OSMessageBox("Can't activate GL rendering context", "Error", OSMB_OK);
01656 return FALSE;
01657 }
01658
01659 if (!gGLManager.initGL())
01660 {
01661 close();
01662 OSMessageBox(
01663 "Second Life is unable to run because your video card drivers\n"
01664 "are out of date or unsupported. Please make sure you have\n"
01665 "the latest video card drivers installed.\n\n"
01666 "If you continue to receive this message, contact customer service.",
01667 "Error",
01668 OSMB_OK);
01669 return FALSE;
01670 }
01671
01672
01673 if (disable_vsync && wglSwapIntervalEXT)
01674 {
01675 llinfos << "Disabling vertical sync" << llendl;
01676 wglSwapIntervalEXT(0);
01677 }
01678 else
01679 {
01680 llinfos << "Keeping vertical sync" << llendl;
01681 }
01682
01683 SetWindowLong(mWindowHandle, GWL_USERDATA, (U32)this);
01684 show();
01685
01686
01687 mPostQuit = TRUE;
01688 return TRUE;
01689 }
01690
01691 void LLWindowWin32::moveWindow( const LLCoordScreen& position, const LLCoordScreen& size )
01692 {
01693 if( mIsMouseClipping )
01694 {
01695 RECT client_rect_in_screen_space;
01696 if( getClientRectInScreenSpace( &client_rect_in_screen_space ) )
01697 {
01698 ClipCursor( &client_rect_in_screen_space );
01699 }
01700 }
01701
01702
01703
01704
01705 ShowWindow(mWindowHandle, SW_RESTORE);
01706
01707 MoveWindow(mWindowHandle, position.mX, position.mY, size.mX, size.mY, TRUE);
01708 }
01709
01710 BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position)
01711 {
01712 LLCoordScreen screen_pos;
01713
01714 mMousePositionModified = TRUE;
01715 if (!mWindowHandle)
01716 {
01717 return FALSE;
01718 }
01719
01720 if (!convertCoords(position, &screen_pos))
01721 {
01722 return FALSE;
01723 }
01724
01725 return SetCursorPos(screen_pos.mX, screen_pos.mY);
01726 }
01727
01728 BOOL LLWindowWin32::getCursorPosition(LLCoordWindow *position)
01729 {
01730 POINT cursor_point;
01731 LLCoordScreen screen_pos;
01732
01733 if (!mWindowHandle ||
01734 !GetCursorPos(&cursor_point))
01735 {
01736 return FALSE;
01737 }
01738
01739 screen_pos.mX = cursor_point.x;
01740 screen_pos.mY = cursor_point.y;
01741
01742 return convertCoords(screen_pos, position);
01743 }
01744
01745 void LLWindowWin32::hideCursor()
01746 {
01747 while (ShowCursor(FALSE) >= 0)
01748 {
01749
01750 }
01751 mCursorHidden = TRUE;
01752 mHideCursorPermanent = TRUE;
01753 }
01754
01755 void LLWindowWin32::showCursor()
01756 {
01757
01758 while (ShowCursor(TRUE) < 0)
01759 {
01760
01761 }
01762 mCursorHidden = FALSE;
01763 mHideCursorPermanent = FALSE;
01764 }
01765
01766 void LLWindowWin32::showCursorFromMouseMove()
01767 {
01768 if (!mHideCursorPermanent)
01769 {
01770 showCursor();
01771 }
01772 }
01773
01774 void LLWindowWin32::hideCursorUntilMouseMove()
01775 {
01776 if (!mHideCursorPermanent)
01777 {
01778 hideCursor();
01779 mHideCursorPermanent = FALSE;
01780 }
01781 }
01782
01783 BOOL LLWindowWin32::isCursorHidden()
01784 {
01785 return mCursorHidden;
01786 }
01787
01788
01789 HCURSOR LLWindowWin32::loadColorCursor(LPCTSTR name)
01790 {
01791 return (HCURSOR)LoadImage(mhInstance,
01792 name,
01793 IMAGE_CURSOR,
01794 0,
01795 0,
01796 LR_DEFAULTCOLOR);
01797 }
01798
01799
01800 void LLWindowWin32::initCursors()
01801 {
01802 mCursor[ UI_CURSOR_ARROW ] = LoadCursor(NULL, IDC_ARROW);
01803 mCursor[ UI_CURSOR_WAIT ] = LoadCursor(NULL, IDC_WAIT);
01804 mCursor[ UI_CURSOR_HAND ] = LoadCursor(NULL, IDC_HAND);
01805 mCursor[ UI_CURSOR_IBEAM ] = LoadCursor(NULL, IDC_IBEAM);
01806 mCursor[ UI_CURSOR_CROSS ] = LoadCursor(NULL, IDC_CROSS);
01807 mCursor[ UI_CURSOR_SIZENWSE ] = LoadCursor(NULL, IDC_SIZENWSE);
01808 mCursor[ UI_CURSOR_SIZENESW ] = LoadCursor(NULL, IDC_SIZENESW);
01809 mCursor[ UI_CURSOR_SIZEWE ] = LoadCursor(NULL, IDC_SIZEWE);
01810 mCursor[ UI_CURSOR_SIZENS ] = LoadCursor(NULL, IDC_SIZENS);
01811 mCursor[ UI_CURSOR_NO ] = LoadCursor(NULL, IDC_NO);
01812 mCursor[ UI_CURSOR_WORKING ] = LoadCursor(NULL, IDC_APPSTARTING);
01813
01814 HMODULE module = GetModuleHandle(NULL);
01815 mCursor[ UI_CURSOR_TOOLGRAB ] = LoadCursor(module, TEXT("TOOLGRAB"));
01816 mCursor[ UI_CURSOR_TOOLLAND ] = LoadCursor(module, TEXT("TOOLLAND"));
01817 mCursor[ UI_CURSOR_TOOLFOCUS ] = LoadCursor(module, TEXT("TOOLFOCUS"));
01818 mCursor[ UI_CURSOR_TOOLCREATE ] = LoadCursor(module, TEXT("TOOLCREATE"));
01819 mCursor[ UI_CURSOR_ARROWDRAG ] = LoadCursor(module, TEXT("ARROWDRAG"));
01820 mCursor[ UI_CURSOR_ARROWCOPY ] = LoadCursor(module, TEXT("ARROWCOPY"));
01821 mCursor[ UI_CURSOR_ARROWDRAGMULTI ] = LoadCursor(module, TEXT("ARROWDRAGMULTI"));
01822 mCursor[ UI_CURSOR_ARROWCOPYMULTI ] = LoadCursor(module, TEXT("ARROWCOPYMULTI"));
01823 mCursor[ UI_CURSOR_NOLOCKED ] = LoadCursor(module, TEXT("NOLOCKED"));
01824 mCursor[ UI_CURSOR_ARROWLOCKED ]= LoadCursor(module, TEXT("ARROWLOCKED"));
01825 mCursor[ UI_CURSOR_GRABLOCKED ] = LoadCursor(module, TEXT("GRABLOCKED"));
01826 mCursor[ UI_CURSOR_TOOLTRANSLATE ] = LoadCursor(module, TEXT("TOOLTRANSLATE"));
01827 mCursor[ UI_CURSOR_TOOLROTATE ] = LoadCursor(module, TEXT("TOOLROTATE"));
01828 mCursor[ UI_CURSOR_TOOLSCALE ] = LoadCursor(module, TEXT("TOOLSCALE"));
01829 mCursor[ UI_CURSOR_TOOLCAMERA ] = LoadCursor(module, TEXT("TOOLCAMERA"));
01830 mCursor[ UI_CURSOR_TOOLPAN ] = LoadCursor(module, TEXT("TOOLPAN"));
01831 mCursor[ UI_CURSOR_TOOLZOOMIN ] = LoadCursor(module, TEXT("TOOLZOOMIN"));
01832 mCursor[ UI_CURSOR_TOOLPICKOBJECT3 ] = LoadCursor(module, TEXT("TOOLPICKOBJECT3"));
01833 mCursor[ UI_CURSOR_PIPETTE ] = LoadCursor(module, TEXT("TOOLPIPETTE"));
01834
01835
01836 mCursor[UI_CURSOR_TOOLSIT] = loadColorCursor(TEXT("TOOLSIT"));
01837 mCursor[UI_CURSOR_TOOLBUY] = loadColorCursor(TEXT("TOOLBUY"));
01838 mCursor[UI_CURSOR_TOOLPAY] = loadColorCursor(TEXT("TOOLPAY"));
01839 mCursor[UI_CURSOR_TOOLOPEN] = loadColorCursor(TEXT("TOOLOPEN"));
01840
01841
01842 for( S32 i = 0; i < UI_CURSOR_COUNT; i++ )
01843 {
01844 if( !mCursor[i] )
01845 {
01846 mCursor[i] = LoadCursor(NULL, IDC_ARROW);
01847 }
01848 }
01849 }
01850
01851
01852
01853 void LLWindowWin32::setCursor(ECursorType cursor)
01854 {
01855 if (cursor == UI_CURSOR_ARROW
01856 && mBusyCount > 0)
01857 {
01858 cursor = UI_CURSOR_WORKING;
01859 }
01860
01861 if( mCurrentCursor != cursor )
01862 {
01863 mCurrentCursor = cursor;
01864 SetCursor( mCursor[cursor] );
01865 }
01866 }
01867
01868 ECursorType LLWindowWin32::getCursor() const
01869 {
01870 return mCurrentCursor;
01871 }
01872
01873 void LLWindowWin32::captureMouse()
01874 {
01875 SetCapture(mWindowHandle);
01876 }
01877
01878 void LLWindowWin32::releaseMouse()
01879 {
01880 ReleaseCapture();
01881 }
01882
01883
01884 void LLWindowWin32::delayInputProcessing()
01885 {
01886 mInputProcessingPaused = TRUE;
01887 }
01888
01889 void LLWindowWin32::gatherInput()
01890 {
01891 MSG msg;
01892 int msg_count = 0;
01893
01894 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) && msg_count < MAX_MESSAGE_PER_UPDATE)
01895 {
01896 TranslateMessage(&msg);
01897 DispatchMessage(&msg);
01898 msg_count++;
01899
01900 if ( mInputProcessingPaused )
01901 {
01902 break;
01903 }
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925 if (gAsyncMsgCallback && (LL_WM_HOST_RESOLVED == msg.message))
01926 {
01927 gAsyncMsgCallback(msg);
01928 }
01929 }
01930
01931 mInputProcessingPaused = FALSE;
01932
01933
01934
01935 mMousePositionModified = FALSE;
01936 }
01937
01938 LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_param, LPARAM l_param)
01939 {
01940 LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(h_wnd, GWL_USERDATA);
01941
01942 if (NULL != window_imp)
01943 {
01944
01945 if (NULL != window_imp->mWndProc)
01946 {
01947 if (!window_imp->mWndProc(h_wnd, u_msg, w_param, l_param))
01948 {
01949
01950 return 0;
01951 }
01952 }
01953
01954
01955
01956 LLCoordWindow window_coord((S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param));
01957
01958
01959
01960 LLCoordGL gl_coord;
01961
01962
01963 MASK mask = (l_param>>16 & KF_EXTENDED) ? MASK_EXTENDED : 0x0;
01964 BOOL eat_keystroke = TRUE;
01965
01966 switch(u_msg)
01967 {
01968 RECT update_rect;
01969 S32 update_width;
01970 S32 update_height;
01971
01972 case WM_TIMER:
01973 window_imp->updateJoystick( );
01974 break;
01975
01976 case WM_PAINT:
01977 GetUpdateRect(window_imp->mWindowHandle, &update_rect, FALSE);
01978 update_width = update_rect.right - update_rect.left + 1;
01979 update_height = update_rect.bottom - update_rect.top + 1;
01980 window_imp->mCallbacks->handlePaint(window_imp, update_rect.left, update_rect.top,
01981 update_width, update_height);
01982 break;
01983 case WM_PARENTNOTIFY:
01984 u_msg = u_msg;
01985 break;
01986
01987 case WM_SETCURSOR:
01988
01989
01990
01991
01992
01993 if (LOWORD(l_param) == HTCLIENT)
01994 {
01995 SetCursor(window_imp->mCursor[ window_imp->mCurrentCursor] );
01996 return 0;
01997 }
01998 break;
01999
02000 case WM_ENTERMENULOOP:
02001 window_imp->mCallbacks->handleWindowBlock(window_imp);
02002 break;
02003
02004 case WM_EXITMENULOOP:
02005 window_imp->mCallbacks->handleWindowUnblock(window_imp);
02006 break;
02007
02008 case WM_ACTIVATEAPP:
02009 {
02010
02011 BOOL activating = (BOOL) w_param;
02012 BOOL minimized = window_imp->getMinimized();
02013
02014 if (gDebugWindowProc)
02015 {
02016 llinfos << "WINDOWPROC ActivateApp "
02017 << " activating " << S32(activating)
02018 << " minimized " << S32(minimized)
02019 << " fullscreen " << S32(window_imp->mFullscreen)
02020 << llendl;
02021 }
02022
02023 if (window_imp->mFullscreen)
02024 {
02025
02026
02027 if (activating)
02028 {
02029 window_imp->setFullscreenResolution();
02030 window_imp->restore();
02031 }
02032 else
02033 {
02034 window_imp->minimize();
02035 window_imp->resetDisplayResolution();
02036 }
02037 }
02038 break;
02039 }
02040
02041 case WM_ACTIVATE:
02042 {
02043
02044 BOOL activating = (LOWORD(w_param) != WA_INACTIVE);
02045
02046 BOOL minimized = BOOL(HIWORD(w_param));
02047
02048
02049
02050
02051 if (gDebugWindowProc)
02052 {
02053 llinfos << "WINDOWPROC Activate "
02054 << " activating " << S32(activating)
02055 << " minimized " << S32(minimized)
02056 << llendl;
02057 }
02058
02059
02060 break;
02061 }
02062
02063 case WM_QUERYOPEN:
02064
02065 break;
02066
02067 case WM_SYSCOMMAND:
02068 switch(w_param)
02069 {
02070 case SC_KEYMENU:
02071
02072 return 0;
02073
02074 case SC_SCREENSAVE:
02075 case SC_MONITORPOWER:
02076
02077 return 0;
02078 }
02079 break;
02080
02081 case WM_CLOSE:
02082
02083 if (window_imp->mCallbacks->handleCloseRequest(window_imp))
02084 {
02085
02086 window_imp->mCallbacks->handleQuit(window_imp);
02087
02088 }
02089 return 0;
02090
02091 case WM_DESTROY:
02092 if (window_imp->shouldPostQuit())
02093 {
02094 PostQuitMessage(0);
02095 }
02096 return 0;
02097
02098 case WM_COMMAND:
02099 if (!HIWORD(w_param))
02100 {
02101 window_imp->mCallbacks->handleMenuSelect(window_imp, LOWORD(w_param));
02102 }
02103 break;
02104
02105 case WM_SYSKEYDOWN:
02106
02107 eat_keystroke = FALSE;
02108 case WM_KEYDOWN:
02109 {
02110 if (gDebugWindowProc)
02111 {
02112 llinfos << "Debug WindowProc WM_KEYDOWN "
02113 << " key " << S32(w_param)
02114 << llendl;
02115 }
02116 if(gKeyboard->handleKeyDown(w_param, mask) && eat_keystroke)
02117 {
02118 return 0;
02119 }
02120
02121 break;
02122 }
02123 case WM_SYSKEYUP:
02124 eat_keystroke = FALSE;
02125 case WM_KEYUP:
02126 if (gDebugWindowProc)
02127 {
02128 llinfos << "Debug WindowProc WM_KEYUP "
02129 << " key " << S32(w_param)
02130 << llendl;
02131 }
02132 if (gKeyboard->handleKeyUp(w_param, mask) && eat_keystroke)
02133 {
02134 return 0;
02135 }
02136
02137
02138 break;
02139
02140
02141 case WM_CHAR:
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154 if (gDebugWindowProc)
02155 {
02156 llinfos << "Debug WindowProc WM_CHAR "
02157 << " key " << S32(w_param)
02158 << llendl;
02159 }
02160
02161
02162 window_imp->handleUnicodeUTF16((U16)w_param, gKeyboard->currentMask(FALSE));
02163 return 0;
02164
02165 case WM_LBUTTONDOWN:
02166 {
02167
02168
02169
02170
02171
02172 LLCoordWindow cursor_coord_window;
02173 if (window_imp->mMousePositionModified)
02174 {
02175 window_imp->getCursorPosition(&cursor_coord_window);
02176 window_imp->convertCoords(cursor_coord_window, &gl_coord);
02177 }
02178 else
02179 {
02180 window_imp->convertCoords(window_coord, &gl_coord);
02181 }
02182 MASK mask = gKeyboard->currentMask(TRUE);
02183 if (window_imp->mCallbacks->handleMouseDown(window_imp, gl_coord, mask))
02184 {
02185 return 0;
02186 }
02187 }
02188 break;
02189
02190 case WM_LBUTTONDBLCLK:
02191
02192
02193 {
02194
02195
02196
02197
02198
02199 LLCoordWindow cursor_coord_window;
02200 if (window_imp->mMousePositionModified)
02201 {
02202 window_imp->getCursorPosition(&cursor_coord_window);
02203 window_imp->convertCoords(cursor_coord_window, &gl_coord);
02204 }
02205 else
02206 {
02207 window_imp->convertCoords(window_coord, &gl_coord);
02208 }
02209 MASK mask = gKeyboard->currentMask(TRUE);
02210 if (window_imp->mCallbacks->handleDoubleClick(window_imp, gl_coord, mask) )
02211 {
02212 return 0;
02213 }
02214 }
02215 break;
02216
02217 case WM_LBUTTONUP:
02218 {
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228 LLCoordWindow cursor_coord_window;
02229 if (window_imp->mMousePositionModified)
02230 {
02231 window_imp->getCursorPosition(&cursor_coord_window);
02232 window_imp->convertCoords(cursor_coord_window, &gl_coord);
02233 }
02234 else
02235 {
02236 window_imp->convertCoords(window_coord, &gl_coord);
02237 }
02238 MASK mask = gKeyboard->currentMask(TRUE);
02239 if (window_imp->mCallbacks->handleMouseUp(window_imp, gl_coord, mask))
02240 {
02241 return 0;
02242 }
02243 }
02244 break;
02245
02246 case WM_RBUTTONDBLCLK:
02247 case WM_RBUTTONDOWN:
02248 {
02249
02250
02251
02252
02253
02254 LLCoordWindow cursor_coord_window;
02255 if (window_imp->mMousePositionModified)
02256 {
02257 window_imp->getCursorPosition(&cursor_coord_window);
02258 window_imp->convertCoords(cursor_coord_window, &gl_coord);
02259 }
02260 else
02261 {
02262 window_imp->convertCoords(window_coord, &gl_coord);
02263 }
02264 MASK mask = gKeyboard->currentMask(TRUE);
02265 if (window_imp->mCallbacks->handleRightMouseDown(window_imp, gl_coord, mask))
02266 {
02267 return 0;
02268 }
02269 }
02270 break;
02271
02272 case WM_RBUTTONUP:
02273 {
02274
02275
02276
02277
02278
02279 LLCoordWindow cursor_coord_window;
02280 if (window_imp->mMousePositionModified)
02281 {
02282 window_imp->getCursorPosition(&cursor_coord_window);
02283 window_imp->convertCoords(cursor_coord_window, &gl_coord);
02284 }
02285 else
02286 {
02287 window_imp->convertCoords(window_coord, &gl_coord);
02288 }
02289 MASK mask = gKeyboard->currentMask(TRUE);
02290 if (window_imp->mCallbacks->handleRightMouseUp(window_imp, gl_coord, mask))
02291 {
02292 return 0;
02293 }
02294 }
02295 break;
02296
02297 case WM_MBUTTONDOWN:
02298
02299 {
02300
02301
02302
02303
02304
02305 LLCoordWindow cursor_coord_window;
02306 if (window_imp->mMousePositionModified)
02307 {
02308 window_imp->getCursorPosition(&cursor_coord_window);
02309 window_imp->convertCoords(cursor_coord_window, &gl_coord);
02310 }
02311 else
02312 {
02313 window_imp->convertCoords(window_coord, &gl_coord);
02314 }
02315 MASK mask = gKeyboard->currentMask(TRUE);
02316 if (window_imp->mCallbacks->handleMiddleMouseDown(window_imp, gl_coord, mask))
02317 {
02318 return 0;
02319 }
02320 }
02321 break;
02322
02323 case WM_MBUTTONUP:
02324 {
02325
02326
02327
02328
02329
02330 LLCoordWindow cursor_coord_window;
02331 if (window_imp->mMousePositionModified)
02332 {
02333 window_imp->getCursorPosition(&cursor_coord_window);
02334 window_imp->convertCoords(cursor_coord_window, &gl_coord);
02335 }
02336 else
02337 {
02338 window_imp->convertCoords(window_coord, &gl_coord);
02339 }
02340 MASK mask = gKeyboard->currentMask(TRUE);
02341 if (window_imp->mCallbacks->handleMiddleMouseUp(window_imp, gl_coord, mask))
02342 {
02343 return 0;
02344 }
02345 }
02346 break;
02347
02348 case WM_MOUSEWHEEL:
02349 {
02350 static short z_delta = 0;
02351
02352 z_delta += HIWORD(w_param);
02353
02354
02355
02356
02357
02358
02359
02360
02361 if (z_delta <= -WHEEL_DELTA || WHEEL_DELTA <= z_delta)
02362 {
02363 window_imp->mCallbacks->handleScrollWheel(window_imp, -z_delta / WHEEL_DELTA);
02364 z_delta = 0;
02365 }
02366 return 0;
02367 }
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382
02383
02384 case WM_MOUSEMOVE:
02385 {
02386 window_imp->convertCoords(window_coord, &gl_coord);
02387 MASK mask = gKeyboard->currentMask(TRUE);
02388 window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
02389 return 0;
02390 }
02391
02392 case WM_SIZE:
02393 {
02394 S32 width = S32( LOWORD(l_param) );
02395 S32 height = S32( HIWORD(l_param) );
02396
02397 if (gDebugWindowProc)
02398 {
02399 BOOL maximized = ( w_param == SIZE_MAXIMIZED );
02400 BOOL restored = ( w_param == SIZE_RESTORED );
02401 BOOL minimized = ( w_param == SIZE_MINIMIZED );
02402
02403 llinfos << "WINDOWPROC Size "
02404 << width << "x" << height
02405 << " max " << S32(maximized)
02406 << " min " << S32(minimized)
02407 << " rest " << S32(restored)
02408 << llendl;
02409 }
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420 if (w_param == SIZE_RESTORED && window_imp->mLastSizeWParam != SIZE_RESTORED)
02421 {
02422 window_imp->mCallbacks->handleActivate(window_imp, TRUE);
02423 }
02424
02425
02426 if (w_param == SIZE_MAXIMIZED && window_imp->mLastSizeWParam != SIZE_MAXIMIZED)
02427 {
02428 window_imp->mCallbacks->handleActivate(window_imp, TRUE);
02429 }
02430
02431
02432 if (w_param == SIZE_MINIMIZED && window_imp->mLastSizeWParam != SIZE_MINIMIZED)
02433 {
02434 window_imp->mCallbacks->handleActivate(window_imp, FALSE);
02435 }
02436
02437
02438 if (w_param != SIZE_MINIMIZED)
02439 {
02440
02441 window_imp->mCallbacks->handleResize( window_imp,
02442 LOWORD(l_param),
02443 HIWORD(l_param) );
02444 }
02445
02446 window_imp->mLastSizeWParam = w_param;
02447
02448 return 0;
02449 }
02450
02451 case WM_SETFOCUS:
02452 if (gDebugWindowProc)
02453 {
02454 llinfos << "WINDOWPROC SetFocus" << llendl;
02455 }
02456 window_imp->mCallbacks->handleFocus(window_imp);
02457 return 0;
02458
02459 case WM_KILLFOCUS:
02460 if (gDebugWindowProc)
02461 {
02462 llinfos << "WINDOWPROC KillFocus" << llendl;
02463 }
02464 window_imp->mCallbacks->handleFocusLost(window_imp);
02465 return 0;
02466
02467 case WM_COPYDATA:
02468
02469 PCOPYDATASTRUCT myCDS = (PCOPYDATASTRUCT) l_param;
02470 window_imp->mCallbacks->handleDataCopy(window_imp, myCDS->dwData, myCDS->lpData);
02471 return 0;
02472 }
02473 }
02474
02475
02476 return DefWindowProc(h_wnd, u_msg, w_param, l_param);
02477 }
02478
02479 BOOL LLWindowWin32::convertCoords(LLCoordGL from, LLCoordWindow *to)
02480 {
02481 S32 client_height;
02482 RECT client_rect;
02483 LLCoordWindow window_position;
02484
02485 if (!mWindowHandle ||
02486 !GetClientRect(mWindowHandle, &client_rect) ||
02487 NULL == to)
02488 {
02489 return FALSE;
02490 }
02491
02492 to->mX = from.mX;
02493 client_height = client_rect.bottom - client_rect.top;
02494 to->mY = client_height - from.mY - 1;
02495
02496 return TRUE;
02497 }
02498
02499 BOOL LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordGL* to)
02500 {
02501 S32 client_height;
02502 RECT client_rect;
02503
02504 if (!mWindowHandle ||
02505 !GetClientRect(mWindowHandle, &client_rect) ||
02506 NULL == to)
02507 {
02508 return FALSE;
02509 }
02510
02511 to->mX = from.mX;
02512 client_height = client_rect.bottom - client_rect.top;
02513 to->mY = client_height - from.mY - 1;
02514
02515 return TRUE;
02516 }
02517
02518 BOOL LLWindowWin32::convertCoords(LLCoordScreen from, LLCoordWindow* to)
02519 {
02520 POINT mouse_point;
02521
02522 mouse_point.x = from.mX;
02523 mouse_point.y = from.mY;
02524 BOOL result = ScreenToClient(mWindowHandle, &mouse_point);
02525
02526 if (result)
02527 {
02528 to->mX = mouse_point.x;
02529 to->mY = mouse_point.y;
02530 }
02531
02532 return result;
02533 }
02534
02535 BOOL LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordScreen *to)
02536 {
02537 POINT mouse_point;
02538
02539 mouse_point.x = from.mX;
02540 mouse_point.y = from.mY;
02541 BOOL result = ClientToScreen(mWindowHandle, &mouse_point);
02542
02543 if (result)
02544 {
02545 to->mX = mouse_point.x;
02546 to->mY = mouse_point.y;
02547 }
02548
02549 return result;
02550 }
02551
02552 BOOL LLWindowWin32::convertCoords(LLCoordScreen from, LLCoordGL *to)
02553 {
02554 LLCoordWindow window_coord;
02555
02556 if (!mWindowHandle || (NULL == to))
02557 {
02558 return FALSE;
02559 }
02560
02561 convertCoords(from, &window_coord);
02562 convertCoords(window_coord, to);
02563 return TRUE;
02564 }
02565
02566 BOOL LLWindowWin32::convertCoords(LLCoordGL from, LLCoordScreen *to)
02567 {
02568 LLCoordWindow window_coord;
02569
02570 if (!mWindowHandle || (NULL == to))
02571 {
02572 return FALSE;
02573 }
02574
02575 convertCoords(from, &window_coord);
02576 convertCoords(window_coord, to);
02577 return TRUE;
02578 }
02579
02580
02581 BOOL LLWindowWin32::isClipboardTextAvailable()
02582 {
02583 return IsClipboardFormatAvailable(CF_UNICODETEXT);
02584 }
02585
02586
02587 BOOL LLWindowWin32::pasteTextFromClipboard(LLWString &dst)
02588 {
02589 BOOL success = FALSE;
02590
02591 if (IsClipboardFormatAvailable(CF_UNICODETEXT))
02592 {
02593 if (OpenClipboard(mWindowHandle))
02594 {
02595 HGLOBAL h_data = GetClipboardData(CF_UNICODETEXT);
02596 if (h_data)
02597 {
02598 WCHAR *utf16str = (WCHAR*) GlobalLock(h_data);
02599 if (utf16str)
02600 {
02601 dst = utf16str_to_wstring(utf16str);
02602 LLWString::removeCRLF(dst);
02603 GlobalUnlock(h_data);
02604 success = TRUE;
02605 }
02606 }
02607 CloseClipboard();
02608 }
02609 }
02610
02611 return success;
02612 }
02613
02614
02615 BOOL LLWindowWin32::copyTextToClipboard(const LLWString& wstr)
02616 {
02617 BOOL success = FALSE;
02618
02619 if (OpenClipboard(mWindowHandle))
02620 {
02621 EmptyClipboard();
02622
02623
02624 LLWString sanitized_string(wstr);
02625 LLWString::addCRLF(sanitized_string);
02626 llutf16string out_utf16 = wstring_to_utf16str(sanitized_string);
02627 const size_t size_utf16 = (out_utf16.length() + 1) * sizeof(WCHAR);
02628
02629
02630 HGLOBAL hglobal_copy_utf16 = GlobalAlloc(GMEM_MOVEABLE, size_utf16);
02631 if (hglobal_copy_utf16)
02632 {
02633 WCHAR* copy_utf16 = (WCHAR*) GlobalLock(hglobal_copy_utf16);
02634 if (copy_utf16)
02635 {
02636 memcpy(copy_utf16, out_utf16.c_str(), size_utf16);
02637 GlobalUnlock(hglobal_copy_utf16);
02638
02639 if (SetClipboardData(CF_UNICODETEXT, hglobal_copy_utf16))
02640 {
02641 success = TRUE;
02642 }
02643 }
02644 }
02645
02646 CloseClipboard();
02647 }
02648
02649 return success;
02650 }
02651
02652
02653 void LLWindowWin32::setMouseClipping( BOOL b )
02654 {
02655 if( b != mIsMouseClipping )
02656 {
02657 BOOL success = FALSE;
02658
02659 if( b )
02660 {
02661 GetClipCursor( &mOldMouseClip );
02662
02663 RECT client_rect_in_screen_space;
02664 if( getClientRectInScreenSpace( &client_rect_in_screen_space ) )
02665 {
02666 success = ClipCursor( &client_rect_in_screen_space );
02667 }
02668 }
02669 else
02670 {
02671
02672 success = ClipCursor( &mOldMouseClip );
02673 SetRect( &mOldMouseClip, 0, 0, 0, 0 );
02674 }
02675
02676 if( success )
02677 {
02678 mIsMouseClipping = b;
02679 }
02680 }
02681 }
02682
02683 BOOL LLWindowWin32::getClientRectInScreenSpace( RECT* rectp )
02684 {
02685 BOOL success = FALSE;
02686
02687 RECT client_rect;
02688 if( mWindowHandle && GetClientRect(mWindowHandle, &client_rect) )
02689 {
02690 POINT top_left;
02691 top_left.x = client_rect.left;
02692 top_left.y = client_rect.top;
02693 ClientToScreen(mWindowHandle, &top_left);
02694
02695 POINT bottom_right;
02696 bottom_right.x = client_rect.right;
02697 bottom_right.y = client_rect.bottom;
02698 ClientToScreen(mWindowHandle, &bottom_right);
02699
02700 SetRect( rectp,
02701 top_left.x,
02702 top_left.y,
02703 bottom_right.x,
02704 bottom_right.y );
02705
02706 success = TRUE;
02707 }
02708
02709 return success;
02710 }
02711
02712
02713 BOOL LLWindowWin32::sendEmail(const char* address, const char* subject, const char* body_text,
02714 const char* attachment, const char* attachment_displayed_name )
02715 {
02716
02717
02718
02719
02720 enum SendResult
02721 {
02722 LL_EMAIL_SUCCESS,
02723 LL_EMAIL_MAPI_NOT_INSTALLED,
02724 LL_EMAIL_MAPILOAD_FAILED,
02725 LL_EMAIL_SEND_FAILED
02726 };
02727
02728 SendResult result = LL_EMAIL_SUCCESS;
02729
02730 U32 mapi_installed = GetProfileInt(L"Mail", L"MAPI", 0);
02731 if( !mapi_installed)
02732 {
02733 result = LL_EMAIL_MAPI_NOT_INSTALLED;
02734 }
02735 else
02736 {
02737 HINSTANCE hMAPIInst = LoadLibrary(L"MAPI32.DLL");
02738 if(!hMAPIInst)
02739 {
02740 result = LL_EMAIL_MAPILOAD_FAILED;
02741 }
02742 else
02743 {
02744 LPMAPISENDMAIL pMAPISendMail = (LPMAPISENDMAIL) GetProcAddress(hMAPIInst, "MAPISendMail");
02745
02746
02747 MapiRecipDesc recipients[1];
02748 recipients[0].ulReserved = 0;
02749 recipients[0].ulRecipClass = MAPI_TO;
02750 recipients[0].lpszName = (char*)address;
02751 recipients[0].lpszAddress = (char*)address;
02752 recipients[0].ulEIDSize = 0;
02753 recipients[0].lpEntryID = 0;
02754
02755 MapiFileDesc files[1];
02756 files[0].ulReserved = 0;
02757 files[0].flFlags = 0;
02758 files[0].nPosition = -1;
02759 files[0].lpszPathName = (char*)attachment;
02760 files[0].lpszFileName = (char*)attachment_displayed_name;
02761 files[0].lpFileType = NULL;
02762
02763 MapiMessage msg;
02764 memset(&msg, 0, sizeof(msg));
02765 msg.lpszSubject = (char*)subject;
02766 msg.lpszNoteText = (char*)body_text;
02767 msg.nRecipCount = address ? 1 : 0;
02768 msg.lpRecips = address ? recipients : NULL;
02769 msg.nFileCount = attachment ? 1 : 0;
02770 msg.lpFiles = attachment ? files : NULL;
02771
02772 U32 success = pMAPISendMail(0, (U32) mWindowHandle, &msg, MAPI_DIALOG|MAPI_LOGON_UI|MAPI_NEW_SESSION, 0);
02773 if(success != SUCCESS_SUCCESS)
02774 {
02775 result = LL_EMAIL_SEND_FAILED;
02776 }
02777
02778 FreeLibrary(hMAPIInst);
02779 }
02780 }
02781
02782 return result == LL_EMAIL_SUCCESS;
02783 }
02784
02785
02786 S32 LLWindowWin32::stat(const char* file_name, struct stat* stat_info)
02787 {
02788 llassert( sizeof(struct stat) == sizeof(struct _stat) );
02789 return LLFile::stat( file_name, (struct _stat*) stat_info );
02790 }
02791
02792 void LLWindowWin32::flashIcon(F32 seconds)
02793 {
02794 FLASHWINFO flash_info;
02795
02796 flash_info.cbSize = sizeof(FLASHWINFO);
02797 flash_info.hwnd = mWindowHandle;
02798 flash_info.dwFlags = FLASHW_TRAY;
02799 flash_info.uCount = UINT(seconds / ICON_FLASH_TIME);
02800 flash_info.dwTimeout = DWORD(1000.f * ICON_FLASH_TIME);
02801 FlashWindowEx(&flash_info);
02802 }
02803
02804 F32 LLWindowWin32::getGamma()
02805 {
02806 return mCurrentGamma;
02807 }
02808
02809 BOOL LLWindowWin32::restoreGamma()
02810 {
02811 return SetDeviceGammaRamp(mhDC, mPrevGammaRamp);
02812 }
02813
02814 BOOL LLWindowWin32::setGamma(const F32 gamma)
02815 {
02816 mCurrentGamma = gamma;
02817
02818 llinfos << "Setting gamma to " << gamma << llendl;
02819
02820 for ( int i = 0; i < 256; ++i )
02821 {
02822 int mult = 256 - ( int ) ( ( gamma - 1.0f ) * 128.0f );
02823
02824 int value = mult * i;
02825
02826 if ( value > 0xffff )
02827 value = 0xffff;
02828
02829 mCurrentGammaRamp [ 0 * 256 + i ] =
02830 mCurrentGammaRamp [ 1 * 256 + i ] =
02831 mCurrentGammaRamp [ 2 * 256 + i ] = ( WORD )value;
02832 };
02833
02834 return SetDeviceGammaRamp ( mhDC, mCurrentGammaRamp );
02835 }
02836
02837 LLWindow::LLWindowResolution* LLWindowWin32::getSupportedResolutions(S32 &num_resolutions)
02838 {
02839 if (!mSupportedResolutions)
02840 {
02841 mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS];
02842 DEVMODE dev_mode;
02843
02844 mNumSupportedResolutions = 0;
02845 for (S32 mode_num = 0; mNumSupportedResolutions < MAX_NUM_RESOLUTIONS; mode_num++)
02846 {
02847 if (!EnumDisplaySettings(NULL, mode_num, &dev_mode))
02848 {
02849 break;
02850 }
02851
02852 if (dev_mode.dmBitsPerPel == BITS_PER_PIXEL &&
02853 dev_mode.dmPelsWidth >= 800 &&
02854 dev_mode.dmPelsHeight >= 600)
02855 {
02856 BOOL resolution_exists = FALSE;
02857 for(S32 i = 0; i < mNumSupportedResolutions; i++)
02858 {
02859 if (mSupportedResolutions[i].mWidth == dev_mode.dmPelsWidth &&
02860 mSupportedResolutions[i].mHeight == dev_mode.dmPelsHeight)
02861 {
02862 resolution_exists = TRUE;
02863 }
02864 }
02865 if (!resolution_exists)
02866 {
02867 mSupportedResolutions[mNumSupportedResolutions].mWidth = dev_mode.dmPelsWidth;
02868 mSupportedResolutions[mNumSupportedResolutions].mHeight = dev_mode.dmPelsHeight;
02869 mNumSupportedResolutions++;
02870 }
02871 }
02872 }
02873 }
02874
02875 num_resolutions = mNumSupportedResolutions;
02876 return mSupportedResolutions;
02877 }
02878
02879
02880 F32 LLWindowWin32::getNativeAspectRatio()
02881 {
02882 if (mOverrideAspectRatio > 0.f)
02883 {
02884 return mOverrideAspectRatio;
02885 }
02886 else if (mNativeAspectRatio > 0.f)
02887 {
02888
02889 return mNativeAspectRatio;
02890 }
02891
02892
02893
02894 S32 num_resolutions;
02895 LLWindowResolution* resolutions = getSupportedResolutions(num_resolutions);
02896
02897 return ((F32)resolutions[num_resolutions - 1].mWidth / (F32)resolutions[num_resolutions - 1].mHeight);
02898 }
02899
02900 F32 LLWindowWin32::getPixelAspectRatio()
02901 {
02902 F32 pixel_aspect = 1.f;
02903 if (getFullscreen())
02904 {
02905 LLCoordScreen screen_size;
02906 getSize(&screen_size);
02907 pixel_aspect = getNativeAspectRatio() * (F32)screen_size.mY / (F32)screen_size.mX;
02908 }
02909
02910 return pixel_aspect;
02911 }
02912
02913
02914
02915 BOOL LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh)
02916 {
02917 DEVMODE dev_mode;
02918 dev_mode.dmSize = sizeof(dev_mode);
02919 BOOL success = FALSE;
02920
02921
02922 if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode))
02923 {
02924 if (dev_mode.dmPelsWidth == width &&
02925 dev_mode.dmPelsHeight == height &&
02926 dev_mode.dmBitsPerPel == bits &&
02927 dev_mode.dmDisplayFrequency == refresh )
02928 {
02929
02930 return TRUE;
02931 }
02932 }
02933
02934 memset(&dev_mode, 0, sizeof(dev_mode));
02935 dev_mode.dmSize = sizeof(dev_mode);
02936 dev_mode.dmPelsWidth = width;
02937 dev_mode.dmPelsHeight = height;
02938 dev_mode.dmBitsPerPel = bits;
02939 dev_mode.dmDisplayFrequency = refresh;
02940 dev_mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
02941
02942
02943 LONG cds_result = ChangeDisplaySettings(&dev_mode, CDS_FULLSCREEN);
02944
02945 success = (DISP_CHANGE_SUCCESSFUL == cds_result);
02946
02947 if (!success)
02948 {
02949 llwarns << "setDisplayResolution failed, "
02950 << width << "x" << height << "x" << bits << " @ " << refresh << llendl;
02951 }
02952
02953 return success;
02954 }
02955
02956
02957 BOOL LLWindowWin32::setFullscreenResolution()
02958 {
02959 if (mFullscreen)
02960 {
02961 return setDisplayResolution( mFullscreenWidth, mFullscreenHeight, mFullscreenBits, mFullscreenRefresh);
02962 }
02963 else
02964 {
02965 return FALSE;
02966 }
02967 }
02968
02969
02970 BOOL LLWindowWin32::resetDisplayResolution()
02971 {
02972 llinfos << "resetDisplayResolution START" << llendl;
02973
02974 LONG cds_result = ChangeDisplaySettings(NULL, 0);
02975
02976 BOOL success = (DISP_CHANGE_SUCCESSFUL == cds_result);
02977
02978 if (!success)
02979 {
02980 llwarns << "resetDisplayResolution failed" << llendl;
02981 }
02982
02983 llinfos << "resetDisplayResolution END" << llendl;
02984
02985 return success;
02986 }
02987
02988 void LLWindowWin32::swapBuffers()
02989 {
02990 SwapBuffers(mhDC);
02991 }
02992
02993
02994 BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance,
02995 VOID* pContext )
02996 {
02997 HRESULT hr;
02998
02999
03000 hr = g_pDI->CreateDevice( pdidInstance->guidInstance, &g_pJoystick, NULL );
03001
03002
03003
03004 if( FAILED(hr) )
03005 return DIENUM_CONTINUE;
03006
03007
03008
03009 return DIENUM_STOP;
03010 }
03011
03012 BOOL CALLBACK EnumObjectsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
03013 VOID* pContext )
03014 {
03015 if( pdidoi->dwType & DIDFT_AXIS )
03016 {
03017 DIPROPRANGE diprg;
03018 diprg.diph.dwSize = sizeof(DIPROPRANGE);
03019 diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
03020 diprg.diph.dwHow = DIPH_BYID;
03021 diprg.diph.dwObj = pdidoi->dwType;
03022 diprg.lMin = -1000;
03023 diprg.lMax = +1000;
03024
03025
03026 if( FAILED( g_pJoystick->SetProperty( DIPROP_RANGE, &diprg.diph ) ) )
03027 return DIENUM_STOP;
03028
03029 }
03030 return DIENUM_CONTINUE;
03031 }
03032
03033 void LLWindowWin32::updateJoystick( )
03034 {
03035 HRESULT hr;
03036 DIJOYSTATE js;
03037
03038 if (!g_pJoystick)
03039 return;
03040 hr = g_pJoystick->Poll();
03041 if ( hr == DIERR_INPUTLOST )
03042 {
03043 hr = g_pJoystick->Acquire();
03044 return;
03045 }
03046 else if ( FAILED(hr) )
03047 return;
03048
03049
03050 if( FAILED( hr = g_pJoystick->GetDeviceState( sizeof(DIJOYSTATE), &js ) ) )
03051 return;
03052
03053 mJoyAxis[0] = js.lX/1000.f;
03054 mJoyAxis[1] = js.lY/1000.f;
03055 mJoyAxis[2] = js.lZ/1000.f;
03056 mJoyAxis[3] = js.lRx/1000.f;
03057 mJoyAxis[4] = js.lRy/1000.f;
03058 mJoyAxis[5] = js.lRz/1000.f;
03059
03060 for (U32 i = 0; i < 16; i++)
03061 {
03062 mJoyButtonState[i] = js.rgbButtons[i];
03063 }
03064 }
03065
03066
03067
03068
03069
03070 LLSplashScreenWin32::LLSplashScreenWin32()
03071 : mWindow(NULL)
03072 {
03073 }
03074
03075 LLSplashScreenWin32::~LLSplashScreenWin32()
03076 {
03077 }
03078
03079 void LLSplashScreenWin32::showImpl()
03080 {
03081
03082 HINSTANCE hinst = GetModuleHandle(NULL);
03083
03084 mWindow = CreateDialog(hinst,
03085 TEXT("SPLASHSCREEN"),
03086 NULL,
03087 (DLGPROC) LLSplashScreenWin32::windowProc);
03088 ShowWindow(mWindow, SW_SHOW);
03089 }
03090
03091
03092 void LLSplashScreenWin32::updateImpl(const char *mesg)
03093 {
03094 if (!mWindow) return;
03095
03096 WCHAR w_mesg[1024];
03097 mbstowcs(w_mesg, mesg, 1024);
03098
03099 SendDlgItemMessage(mWindow,
03100 666,
03101 WM_SETTEXT,
03102 FALSE,
03103 (LPARAM)w_mesg);
03104 }
03105
03106
03107 void LLSplashScreenWin32::hideImpl()
03108 {
03109 if (mWindow)
03110 {
03111 DestroyWindow(mWindow);
03112 mWindow = NULL;
03113 }
03114 }
03115
03116
03117
03118 LRESULT CALLBACK LLSplashScreenWin32::windowProc(HWND h_wnd, UINT u_msg,
03119 WPARAM w_param, LPARAM l_param)
03120 {
03121
03122 return DefWindowProc(h_wnd, u_msg, w_param, l_param);
03123 }
03124
03125
03126
03127
03128
03129 S32 OSMessageBoxWin32(const char* text, const char* caption, U32 type)
03130 {
03131 UINT uType;
03132
03133 switch(type)
03134 {
03135 case OSMB_OK:
03136 uType = MB_OK;
03137 break;
03138 case OSMB_OKCANCEL:
03139 uType = MB_OKCANCEL;
03140 break;
03141 case OSMB_YESNO:
03142 uType = MB_YESNO;
03143 break;
03144 default:
03145 uType = MB_OK;
03146 break;
03147 }
03148
03149
03150 int retval_win = MessageBoxA(NULL, text, caption, uType);
03151 S32 retval;
03152
03153 switch(retval_win)
03154 {
03155 case IDYES:
03156 retval = OSBTN_YES;
03157 break;
03158 case IDNO:
03159 retval = OSBTN_NO;
03160 break;
03161 case IDOK:
03162 retval = OSBTN_OK;
03163 break;
03164 case IDCANCEL:
03165 retval = OSBTN_CANCEL;
03166 break;
03167 default:
03168 retval = OSBTN_CANCEL;
03169 break;
03170 }
03171
03172 return retval;
03173 }
03174
03175
03176 void spawn_web_browser(const char* escaped_url )
03177 {
03178 bool found = false;
03179 S32 i;
03180 for (i = 0; i < gURLProtocolWhitelistCount; i++)
03181 {
03182 S32 len = strlen(gURLProtocolWhitelist[i]);
03183 if (!strncmp(escaped_url, gURLProtocolWhitelist[i], len)
03184 && escaped_url[len] == ':')
03185 {
03186 found = true;
03187 break;
03188 }
03189 }
03190
03191 if (!found)
03192 {
03193 llwarns << "spawn_web_browser() called for url with protocol not on whitelist: " << escaped_url << llendl;
03194 return;
03195 }
03196
03197 llinfos << "Opening URL " << escaped_url << llendl;
03198
03199
03200
03201 char reg_path_str[256];
03202 snprintf(reg_path_str, sizeof(reg_path_str), "%s\\shell\\open\\command", gURLProtocolWhitelistHandler[i]);
03203 WCHAR reg_path_wstr[256];
03204 mbstowcs(reg_path_wstr, reg_path_str, sizeof(reg_path_wstr)/sizeof(reg_path_wstr[0]));
03205
03206 HKEY key;
03207 WCHAR browser_open_wstr[1024];
03208 DWORD buffer_length = 1024;
03209 RegOpenKeyEx(HKEY_CLASSES_ROOT, reg_path_wstr, 0, KEY_QUERY_VALUE, &key);
03210 RegQueryValueEx(key, NULL, NULL, NULL, (LPBYTE)browser_open_wstr, &buffer_length);
03211 RegCloseKey(key);
03212
03213
03214 LLWString browser_open_wstring = utf16str_to_wstring(browser_open_wstr);
03215
03216 if (browser_open_wstring.length() < 2)
03217 {
03218 llwarns << "Invalid browser executable in registry " << browser_open_wstring << llendl;
03219 return;
03220 }
03221
03222
03223 LLWString browser_executable;
03224 if (browser_open_wstring[0] == '"')
03225 {
03226
03227 size_t quote_pos = browser_open_wstring.find('"', 1);
03228
03229 browser_executable = browser_open_wstring.substr(0, quote_pos+1);
03230 }
03231 else
03232 {
03233
03234 size_t space_pos = browser_open_wstring.find(' ', 1);
03235 browser_executable = browser_open_wstring.substr(0, space_pos);
03236 }
03237
03238 llinfos << "Browser reg key: " << wstring_to_utf8str(browser_open_wstring) << llendl;
03239 llinfos << "Browser executable: " << wstring_to_utf8str(browser_executable) << llendl;
03240
03241
03242
03243 LLWString url_wstring = utf8str_to_wstring(escaped_url);
03244 llutf16string url_utf16 = wstring_to_utf16str(url_wstring);
03245
03246
03247 llutf16string browser_exec_utf16 = wstring_to_utf16str(browser_executable);
03248
03249
03250
03251 HWND our_window = NULL;
03252 LPCWSTR directory_wstr = NULL;
03253 int retval = (int) ShellExecute(our_window,
03254 L"open",
03255 browser_exec_utf16.c_str(),
03256 url_utf16.c_str(),
03257 directory_wstr,
03258 SW_SHOWNORMAL);
03259 if (retval > 32)
03260 {
03261 llinfos << "load_url success with " << retval << llendl;
03262 }
03263 else
03264 {
03265 llinfos << "load_url failure with " << retval << llendl;
03266 }
03267 }
03268
03269 void shell_open( const char* file_path )
03270 {
03271 llinfos << "Opening " << file_path << llendl;
03272
03273 WCHAR wstr[1024];
03274 mbstowcs(wstr, file_path, 1024);
03275
03276 HWND our_window = NULL;
03277 int retval = (int) ShellExecute(our_window, L"open", wstr, NULL, NULL, SW_SHOWNORMAL);
03278 if (retval > 32)
03279 {
03280 llinfos << "ShellExecute success with " << retval << llendl;
03281 }
03282 else
03283 {
03284 llinfos << "ShellExecute failure with " << retval << llendl;
03285 }
03286 }
03287
03288 BOOL LLWindowWin32::dialog_color_picker ( F32 *r, F32 *g, F32 *b )
03289 {
03290 BOOL retval = FALSE;
03291
03292 static CHOOSECOLOR cc;
03293 static COLORREF crCustColors[16];
03294 cc.lStructSize = sizeof(CHOOSECOLOR);
03295 cc.hwndOwner = mWindowHandle;
03296 cc.hInstance = NULL;
03297 cc.rgbResult = RGB ((*r * 255.f),(*g *255.f),(*b * 255.f));
03298
03299 cc.lpCustColors = crCustColors;
03300 cc.Flags = CC_RGBINIT | CC_FULLOPEN;
03301 cc.lCustData = 0;
03302 cc.lpfnHook = NULL;
03303 cc.lpTemplateName = NULL;
03304
03305
03306
03307 {
03308 retval = ChooseColor(&cc);
03309 }
03310
03311
03312 *b = ((F32)((cc.rgbResult >> 16) & 0xff)) / 255.f;
03313
03314 *g = ((F32)((cc.rgbResult >> 8) & 0xff)) / 255.f;
03315
03316 *r = ((F32)(cc.rgbResult & 0xff)) / 255.f;
03317
03318 return (retval);
03319 }
03320
03321 void *LLWindowWin32::getPlatformWindow()
03322 {
03323 return (void*)mWindowHandle;
03324 }
03325
03326 void LLWindowWin32::bringToFront()
03327 {
03328 BringWindowToTop(mWindowHandle);
03329 }
03330
03331
03332 void LLWindowWin32::focusClient()
03333 {
03334 SetFocus ( mWindowHandle );
03335 }
03336
03337 void LLWindowWin32::allowLanguageTextInput(BOOL b)
03338 {
03339 if (b == sLanguageTextInputAllowed || !LLWinImm::isAvailable())
03340 {
03341 return;
03342 }
03343 sLanguageTextInputAllowed = b;
03344
03345 if (b)
03346 {
03347
03348
03349
03350 if (sWinIMEOpened && GetKeyboardLayout(0) == sWinInputLocale)
03351 {
03352 HIMC himc = LLWinImm::getContext(mWindowHandle);
03353 LLWinImm::setOpenStatus(himc, TRUE);
03354 LLWinImm::setConversionStatus(himc, sWinIMEConversionMode, sWinIMESentenceMode);
03355 LLWinImm::releaseContext(mWindowHandle, himc);
03356 }
03357 }
03358 else
03359 {
03360
03361
03362
03363 sWinInputLocale = GetKeyboardLayout(0);
03364 sWinIMEOpened = LLWinImm::isIME(sWinInputLocale);
03365 if (sWinIMEOpened)
03366 {
03367 HIMC himc = LLWinImm::getContext(mWindowHandle);
03368 sWinIMEOpened = LLWinImm::getOpenStatus(himc);
03369 if (sWinIMEOpened)
03370 {
03371 LLWinImm::getConversionStatus(himc, &sWinIMEConversionMode, &sWinIMESentenceMode);
03372
03373
03374
03375 LLWinImm::setConversionStatus(himc, IME_CMODE_NOCONVERSION, sWinIMESentenceMode);
03376 LLWinImm::setOpenStatus(himc, FALSE);
03377 }
03378 LLWinImm::releaseContext(mWindowHandle, himc);
03379 }
03380 }
03381
03382 }
03383
03384
03385
03386 void LLWindowWin32::setLanguageTextInput( const LLCoordGL & position )
03387 {
03388 if (sLanguageTextInputAllowed && LLWinImm::isAvailable())
03389 {
03390 HIMC himc = LLWinImm::getContext(mWindowHandle);
03391
03392 LLCoordWindow win_pos;
03393 convertCoords( position, &win_pos );
03394
03395 if ( win_pos.mX >= 0 && win_pos.mY >= 0 )
03396 {
03397 COMPOSITIONFORM ime_form;
03398 memset( &ime_form, 0, sizeof(ime_form) );
03399 ime_form.dwStyle = CFS_POINT;
03400 ime_form.ptCurrentPos.x = win_pos.mX;
03401 ime_form.ptCurrentPos.y = win_pos.mY;
03402
03403 LLWinImm::setCompositionWindow( himc, &ime_form );
03404 }
03405
03406 LLWinImm::releaseContext(mWindowHandle, himc);
03407
03408 }
03409 }
03410
03411 #endif // LL_WINDOWS