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