1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 21 #include <com/sun/star/container/XIndexAccess.hpp> 22 #include <com/sun/star/beans/XPropertySet.hpp> 23 #include <com/sun/star/awt/Rectangle.hpp> 24 25 #include <officecfg/Office/Common.hxx> 26 27 #include <memory> 28 #include <string.h> 29 #include <limits.h> 30 31 #include <svsys.h> 32 33 #include <comphelper/windowserrorstring.hxx> 34 35 #include <fstream> 36 #include <boost/property_tree/ptree.hpp> 37 #include <boost/property_tree/ini_parser.hpp> 38 #include <osl/file.hxx> 39 #include <osl/process.h> 40 41 #include <rtl/character.hxx> 42 #include <rtl/string.h> 43 #include <rtl/ustring.h> 44 #include <sal/log.hxx> 45 46 #include <osl/module.h> 47 #include <comphelper/scopeguard.hxx> 48 #include <tools/debug.hxx> 49 #include <o3tl/enumarray.hxx> 50 #include <o3tl/char16_t2wchar_t.hxx> 51 52 #include <vcl/event.hxx> 53 #include <vcl/sysdata.hxx> 54 #include <vcl/timer.hxx> 55 #include <vcl/settings.hxx> 56 #include <vcl/keycodes.hxx> 57 #include <vcl/window.hxx> 58 #include <vcl/wrkwin.hxx> 59 #include <vcl/svapp.hxx> 60 #include <vcl/ptrstyle.hxx> 61 62 #include <win/wincomp.hxx> 63 #include <win/salids.hrc> 64 #include <win/saldata.hxx> 65 #include <win/salinst.h> 66 #include <win/salbmp.h> 67 #include <win/salgdi.h> 68 #include <win/salsys.h> 69 #include <win/salframe.h> 70 #include <win/salvd.h> 71 #include <win/salmenu.h> 72 #include <win/salobj.h> 73 #include <win/saltimer.h> 74 75 #include <helpwin.hxx> 76 #include <window.h> 77 #include <sallayout.hxx> 78 79 #define COMPILE_MULTIMON_STUBS 80 #pragma warning(push) 81 #pragma warning(disable:4996) // 'GetVersionExA': was declared deprecated 82 #include <multimon.h> 83 #pragma warning(pop) 84 #include <vector> 85 86 #include <com/sun/star/uno/Exception.hpp> 87 88 #include <oleacc.h> 89 #include <com/sun/star/accessibility/XMSAAService.hpp> 90 91 #include <time.h> 92 93 #if !defined WIN32_LEAN_AND_MEAN 94 # define WIN32_LEAN_AND_MEAN 95 #endif 96 #include <windows.h> 97 #include <dwmapi.h> 98 #include <shobjidl.h> 99 #include <propkey.h> 100 #include <propvarutil.h> 101 #include <shellapi.h> 102 #include <uxtheme.h> 103 #include <Vssym32.h> 104 105 using namespace ::com::sun::star; 106 using namespace ::com::sun::star::uno; 107 using namespace ::com::sun::star::lang; 108 using namespace ::com::sun::star::container; 109 using namespace ::com::sun::star::beans; 110 111 #ifndef SPI_GETWHEELSCROLLCHARS 112 # define SPI_GETWHEELSCROLLCHARS 0x006C 113 #endif 114 #ifndef SPI_SETWHEELSCROLLCHARS 115 # define SPI_SETWHEELSCROLLCHARS 0x006D 116 #endif 117 #ifndef WM_MOUSEHWHEEL 118 # define WM_MOUSEHWHEEL 0x020E 119 #endif 120 #ifndef IDC_PEN 121 # define IDC_PEN MAKEINTRESOURCE(32631) 122 #endif 123 124 const unsigned int WM_USER_SYSTEM_WINDOW_ACTIVATED = RegisterWindowMessageW(L"SYSTEM_WINDOW_ACTIVATED"); 125 126 bool WinSalFrame::mbInReparent = false; 127 128 // Macros for support of WM_UNICHAR & Keyman 6.0 129 #define Uni_SupplementaryPlanesStart 0x10000 130 131 static void UpdateFrameGeometry(WinSalFrame* pFrame); 132 static void SetMaximizedFrameGeometry( HWND hWnd, WinSalFrame* pFrame, RECT* pParentRect = nullptr ); 133 134 static void SetGeometrySize(vcl::WindowPosSize& rWinPosSize, const Size& rSize) 135 { 136 rWinPosSize.setWidth(rSize.Width() < 0 ? 0 : rSize.Width()); 137 rWinPosSize.setHeight(rSize.Height() < 0 ? 0 : rSize.Height()); 138 } 139 140 // If called with UpdateFrameGeometry, it must be called after it, as UpdateFrameGeometry 141 // updates the geometry depending on the old state! 142 void WinSalFrame::UpdateFrameState() 143 { 144 // don't overwrite restore state in fullscreen mode 145 if (isFullScreen()) 146 return; 147 148 const bool bVisible = (GetWindowStyle(mhWnd) & WS_VISIBLE); 149 if (IsIconic(mhWnd)) 150 { 151 m_eState &= ~vcl::WindowState(vcl::WindowState::Normal | vcl::WindowState::Maximized); 152 m_eState |= vcl::WindowState::Minimized; 153 if (bVisible) 154 mnShowState = SW_SHOWMINIMIZED; 155 } 156 else if (IsZoomed(mhWnd)) 157 { 158 m_eState &= ~vcl::WindowState(vcl::WindowState::Minimized | vcl::WindowState::Normal); 159 m_eState |= vcl::WindowState::Maximized; 160 if (bVisible) 161 mnShowState = SW_SHOWMAXIMIZED; 162 mbRestoreMaximize = true; 163 } 164 else 165 { 166 m_eState &= ~vcl::WindowState(vcl::WindowState::Minimized | vcl::WindowState::Maximized); 167 m_eState |= vcl::WindowState::Normal; 168 if (bVisible) 169 mnShowState = SW_SHOWNORMAL; 170 mbRestoreMaximize = false; 171 } 172 } 173 174 // if pParentRect is set, the workarea of the monitor that contains pParentRect is returned 175 void ImplSalGetWorkArea( HWND hWnd, RECT *pRect, const RECT *pParentRect ) 176 { 177 if (Application::IsHeadlessModeEnabled()) { 178 pRect->left = 0; 179 pRect->top = 0; 180 pRect->right = VIRTUAL_DESKTOP_WIDTH; 181 pRect->bottom = VIRTUAL_DESKTOP_HEIGHT; 182 return; 183 } 184 // check if we or our parent is fullscreen, then the taskbar should be ignored 185 bool bIgnoreTaskbar = false; 186 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 187 if( pFrame ) 188 { 189 vcl::Window *pWin = pFrame->GetWindow(); 190 while( pWin ) 191 { 192 WorkWindow *pWorkWin = (pWin->GetType() == WindowType::WORKWINDOW) ? static_cast<WorkWindow *>(pWin) : nullptr; 193 if( pWorkWin && pWorkWin->ImplGetWindowImpl()->mbReallyVisible && pWorkWin->IsFullScreenMode() ) 194 { 195 bIgnoreTaskbar = true; 196 break; 197 } 198 else 199 pWin = pWin->ImplGetWindowImpl()->mpParent; 200 } 201 } 202 203 // calculates the work area taking multiple monitors into account 204 static int nMonitors = GetSystemMetrics( SM_CMONITORS ); 205 if( nMonitors == 1 ) 206 { 207 if( bIgnoreTaskbar ) 208 { 209 pRect->left = pRect->top = 0; 210 pRect->right = GetSystemMetrics( SM_CXSCREEN ); 211 pRect->bottom = GetSystemMetrics( SM_CYSCREEN ); 212 } 213 else 214 SystemParametersInfoW( SPI_GETWORKAREA, 0, pRect, 0 ); 215 } 216 else 217 { 218 if( pParentRect != nullptr ) 219 { 220 // return the size of the monitor where pParentRect lives 221 HMONITOR hMonitor; 222 MONITORINFO mi; 223 224 // get the nearest monitor to the passed rect. 225 hMonitor = MonitorFromRect(pParentRect, MONITOR_DEFAULTTONEAREST); 226 227 // get the work area or entire monitor rect. 228 mi.cbSize = sizeof(mi); 229 GetMonitorInfo(hMonitor, &mi); 230 if( !bIgnoreTaskbar ) 231 *pRect = mi.rcWork; 232 else 233 *pRect = mi.rcMonitor; 234 } 235 else 236 { 237 // return the union of all monitors 238 pRect->left = GetSystemMetrics( SM_XVIRTUALSCREEN ); 239 pRect->top = GetSystemMetrics( SM_YVIRTUALSCREEN ); 240 pRect->right = pRect->left + GetSystemMetrics( SM_CXVIRTUALSCREEN ); 241 pRect->bottom = pRect->top + GetSystemMetrics( SM_CYVIRTUALSCREEN ); 242 243 // virtualscreen does not take taskbar into account, so use the corresponding 244 // diffs between screen and workarea from the default screen 245 // however, this is still not perfect: the taskbar might not be on the primary screen 246 if( !bIgnoreTaskbar ) 247 { 248 RECT wRect, scrRect; 249 SystemParametersInfoW( SPI_GETWORKAREA, 0, &wRect, 0 ); 250 scrRect.left = 0; 251 scrRect.top = 0; 252 scrRect.right = GetSystemMetrics( SM_CXSCREEN ); 253 scrRect.bottom = GetSystemMetrics( SM_CYSCREEN ); 254 255 pRect->left += wRect.left; 256 pRect->top += wRect.top; 257 pRect->right -= scrRect.right - wRect.right; 258 pRect->bottom -= scrRect.bottom - wRect.bottom; 259 } 260 } 261 } 262 } 263 264 static void UpdateDarkMode(HWND hWnd) 265 { 266 static bool bOSSupportsDarkMode = OSSupportsDarkMode(); 267 if (!bOSSupportsDarkMode) 268 return; 269 270 HINSTANCE hUxthemeLib = LoadLibraryExW(L"uxtheme.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); 271 if (!hUxthemeLib) 272 return; 273 274 typedef void(WINAPI* AllowDarkModeForWindow_t)(HWND, BOOL); 275 if (auto AllowDarkModeForWindow = reinterpret_cast<AllowDarkModeForWindow_t>(GetProcAddress(hUxthemeLib, MAKEINTRESOURCEA(133)))) 276 AllowDarkModeForWindow(hWnd, TRUE); 277 278 typedef bool(WINAPI* ShouldAppsUseDarkMode_t)(); 279 if (auto ShouldAppsUseDarkMode = reinterpret_cast<ShouldAppsUseDarkMode_t>(GetProcAddress(hUxthemeLib, MAKEINTRESOURCEA(132)))) 280 { 281 BOOL bDarkMode = ShouldAppsUseDarkMode(); 282 DwmSetWindowAttribute(hWnd, 20, &bDarkMode, sizeof(bDarkMode)); 283 } 284 285 FreeLibrary(hUxthemeLib); 286 } 287 288 SalFrame* ImplSalCreateFrame( WinSalInstance* pInst, 289 HWND hWndParent, SalFrameStyleFlags nSalFrameStyle ) 290 { 291 WinSalFrame* pFrame = new WinSalFrame; 292 HWND hWnd; 293 DWORD nSysStyle = 0; 294 DWORD nExSysStyle = 0; 295 bool bSubFrame = false; 296 297 static const char* pEnvSynchronize = getenv("SAL_SYNCHRONIZE"); 298 if ( pEnvSynchronize ) // no buffering of drawing commands 299 GdiSetBatchLimit( 1 ); 300 301 static const char* pEnvTransparentFloats = getenv("SAL_TRANSPARENT_FLOATS" ); 302 303 // determine creation data 304 if ( nSalFrameStyle & (SalFrameStyleFlags::PLUG | SalFrameStyleFlags::SYSTEMCHILD) ) 305 { 306 nSysStyle |= WS_CHILD; 307 if( nSalFrameStyle & SalFrameStyleFlags::SYSTEMCHILD ) 308 nSysStyle |= WS_CLIPSIBLINGS; 309 } 310 else 311 { 312 // #i87402# commenting out WS_CLIPCHILDREN 313 // this breaks SalFrameStyleFlags::SYSTEMCHILD handling, which is not 314 // used currently. Probably SalFrameStyleFlags::SYSTEMCHILD should be 315 // removed again. 316 317 // nSysStyle |= WS_CLIPCHILDREN; 318 if ( hWndParent ) 319 { 320 nSysStyle |= WS_POPUP; 321 bSubFrame = true; 322 pFrame->mbNoIcon = true; 323 } 324 else 325 { 326 // Only with WS_OVERLAPPED we get a useful default position/size 327 if ( (nSalFrameStyle & (SalFrameStyleFlags::SIZEABLE | SalFrameStyleFlags::MOVEABLE)) == 328 (SalFrameStyleFlags::SIZEABLE | SalFrameStyleFlags::MOVEABLE) ) 329 nSysStyle |= WS_OVERLAPPED; 330 else 331 { 332 nSysStyle |= WS_POPUP; 333 if ( !(nSalFrameStyle & SalFrameStyleFlags::MOVEABLE) ) 334 nExSysStyle |= WS_EX_TOOLWINDOW; // avoid taskbar appearance, for eg splash screen 335 } 336 } 337 338 if ( nSalFrameStyle & SalFrameStyleFlags::MOVEABLE ) 339 { 340 pFrame->mbCaption = true; 341 nSysStyle |= WS_SYSMENU | WS_CAPTION; 342 if ( !hWndParent ) 343 nSysStyle |= WS_SYSMENU | WS_MINIMIZEBOX; 344 else 345 nExSysStyle |= WS_EX_DLGMODALFRAME; 346 347 if ( nSalFrameStyle & SalFrameStyleFlags::SIZEABLE ) 348 { 349 pFrame->mbSizeBorder = true; 350 nSysStyle |= WS_THICKFRAME; 351 if ( !hWndParent ) 352 nSysStyle |= WS_MAXIMIZEBOX; 353 } 354 else 355 pFrame->mbFixBorder = true; 356 357 if ( nSalFrameStyle & SalFrameStyleFlags::DEFAULT ) 358 nExSysStyle |= WS_EX_APPWINDOW; 359 } 360 if( nSalFrameStyle & SalFrameStyleFlags::TOOLWINDOW 361 // #100656# toolwindows lead to bad alt-tab behaviour, if they have the focus 362 // you must press it twice to leave the application 363 // so toolwindows are only used for non sizeable windows 364 // which are typically small, so a small caption makes sense 365 366 // #103578# looked too bad - above changes reverted 367 /* && !(nSalFrameStyle & SalFrameStyleFlags::SIZEABLE) */ ) 368 { 369 pFrame->mbNoIcon = true; 370 nExSysStyle |= WS_EX_TOOLWINDOW; 371 if ( pEnvTransparentFloats /*&& !(nSalFrameStyle & SalFrameStyleFlags::MOVEABLE) */) 372 nExSysStyle |= WS_EX_LAYERED; 373 } 374 } 375 if ( nSalFrameStyle & SalFrameStyleFlags::FLOAT ) 376 { 377 nExSysStyle |= WS_EX_TOOLWINDOW; 378 pFrame->mbFloatWin = true; 379 380 if (pEnvTransparentFloats) 381 nExSysStyle |= WS_EX_LAYERED; 382 383 } 384 if (nSalFrameStyle & SalFrameStyleFlags::TOOLTIP) 385 nExSysStyle |= WS_EX_TOPMOST; 386 387 // init frame data 388 pFrame->mnStyle = nSalFrameStyle; 389 390 // determine show style 391 pFrame->mnShowState = SW_SHOWNORMAL; 392 if ( (nSysStyle & (WS_POPUP | WS_MAXIMIZEBOX | WS_THICKFRAME)) == (WS_MAXIMIZEBOX | WS_THICKFRAME) ) 393 { 394 if ( GetSystemMetrics( SM_CXSCREEN ) <= 1024 ) 395 pFrame->mnShowState = SW_SHOWMAXIMIZED; 396 else 397 { 398 if ( nSalFrameStyle & SalFrameStyleFlags::DEFAULT ) 399 { 400 SalData* pSalData = GetSalData(); 401 pFrame->mnShowState = pSalData->mnCmdShow; 402 if ( (pFrame->mnShowState != SW_SHOWMINIMIZED) && 403 (pFrame->mnShowState != SW_MINIMIZE) && 404 (pFrame->mnShowState != SW_SHOWMINNOACTIVE) ) 405 { 406 if ( (pFrame->mnShowState == SW_SHOWMAXIMIZED) || 407 (pFrame->mnShowState == SW_MAXIMIZE) ) 408 pFrame->mbOverwriteState = false; 409 pFrame->mnShowState = SW_SHOWMAXIMIZED; 410 } 411 else 412 pFrame->mbOverwriteState = false; 413 } 414 else 415 { 416 // Document Windows are also maximized, if the current Document Window 417 // is also maximized 418 HWND hWnd2 = GetForegroundWindow(); 419 if ( hWnd2 && IsMaximized( hWnd2 ) && 420 (GetWindowInstance( hWnd2 ) == pInst->mhInst) && 421 ((GetWindowStyle( hWnd2 ) & (WS_POPUP | WS_MAXIMIZEBOX | WS_THICKFRAME)) == (WS_MAXIMIZEBOX | WS_THICKFRAME)) ) 422 pFrame->mnShowState = SW_SHOWMAXIMIZED; 423 } 424 } 425 } 426 427 // create frame 428 LPCWSTR pClassName; 429 if ( bSubFrame ) 430 { 431 if ( nSalFrameStyle & (SalFrameStyleFlags::MOVEABLE|SalFrameStyleFlags::NOSHADOW) ) // check if shadow not wanted 432 pClassName = SAL_SUBFRAME_CLASSNAMEW; 433 else 434 pClassName = SAL_TMPSUBFRAME_CLASSNAMEW; // undecorated floaters will get shadow on XP 435 } 436 else 437 { 438 if ( nSalFrameStyle & SalFrameStyleFlags::MOVEABLE ) 439 pClassName = SAL_FRAME_CLASSNAMEW; 440 else 441 pClassName = SAL_TMPSUBFRAME_CLASSNAMEW; 442 } 443 hWnd = CreateWindowExW( nExSysStyle, pClassName, L"", nSysStyle, 444 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 445 hWndParent, nullptr, pInst->mhInst, pFrame ); 446 SAL_WARN_IF(!hWnd, "vcl", "CreateWindowExW failed: " << WindowsErrorString(GetLastError())); 447 448 #if OSL_DEBUG_LEVEL > 1 449 // set transparency value 450 if( GetWindowExStyle( hWnd ) & WS_EX_LAYERED ) 451 SetLayeredWindowAttributes( hWnd, 0, 230, 0x00000002 /*LWA_ALPHA*/ ); 452 #endif 453 if ( !hWnd ) 454 { 455 delete pFrame; 456 return nullptr; 457 } 458 459 // If we have a Window with a Caption Bar and without 460 // a MaximizeBox, we change the SystemMenu 461 if ( (nSysStyle & (WS_CAPTION | WS_MAXIMIZEBOX)) == (WS_CAPTION) ) 462 { 463 HMENU hSysMenu = GetSystemMenu( hWnd, FALSE ); 464 if ( hSysMenu ) 465 { 466 if ( !(nSysStyle & (WS_MINIMIZEBOX | WS_MAXIMIZEBOX)) ) 467 DeleteMenu( hSysMenu, SC_RESTORE, MF_BYCOMMAND ); 468 else 469 EnableMenuItem( hSysMenu, SC_RESTORE, MF_BYCOMMAND | MF_GRAYED | MF_DISABLED ); 470 if ( !(nSysStyle & WS_MINIMIZEBOX) ) 471 DeleteMenu( hSysMenu, SC_MINIMIZE, MF_BYCOMMAND ); 472 if ( !(nSysStyle & WS_MAXIMIZEBOX) ) 473 DeleteMenu( hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND ); 474 if ( !(nSysStyle & WS_THICKFRAME) ) 475 DeleteMenu( hSysMenu, SC_SIZE, MF_BYCOMMAND ); 476 } 477 } 478 if ( (nSysStyle & WS_SYSMENU) && !(nSalFrameStyle & SalFrameStyleFlags::CLOSEABLE) ) 479 { 480 HMENU hSysMenu = GetSystemMenu( hWnd, FALSE ); 481 if ( hSysMenu ) 482 EnableMenuItem( hSysMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED | MF_DISABLED ); 483 } 484 485 // reset input context 486 pFrame->mhDefIMEContext = ImmAssociateContext( hWnd, nullptr ); 487 488 // determine output size and state 489 RECT aRect; 490 GetClientRect( hWnd, &aRect ); 491 pFrame->mbDefPos = true; 492 493 UpdateFrameGeometry(pFrame); 494 pFrame->UpdateFrameState(); 495 496 if( pFrame->mnShowState == SW_SHOWMAXIMIZED ) 497 { 498 // #96084 set a useful internal window size because 499 // the window will not be maximized (and the size updated) before show() 500 501 SetMaximizedFrameGeometry( hWnd, pFrame ); 502 } 503 504 return pFrame; 505 } 506 507 // helper that only creates the HWND 508 // to allow for easy reparenting of system windows, (i.e. destroy and create new) 509 HWND ImplSalReCreateHWND( HWND hWndParent, HWND oldhWnd, bool bAsChild ) 510 { 511 HINSTANCE hInstance = GetSalData()->mhInst; 512 sal_uLong nSysStyle = GetWindowLongW( oldhWnd, GWL_STYLE ); 513 sal_uLong nExSysStyle = GetWindowLongW( oldhWnd, GWL_EXSTYLE ); 514 515 if( bAsChild ) 516 { 517 nSysStyle = WS_CHILD; 518 nExSysStyle = 0; 519 } 520 521 LPCWSTR pClassName = SAL_SUBFRAME_CLASSNAMEW; 522 return CreateWindowExW( nExSysStyle, pClassName, L"", nSysStyle, 523 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 524 hWndParent, nullptr, hInstance, GetWindowPtr( oldhWnd ) ); 525 } 526 527 // translation table from System keycodes into StartView keycodes 528 #define KEY_TAB_SIZE 146 529 530 const sal_uInt16 aImplTranslateKeyTab[KEY_TAB_SIZE] = 531 { 532 // StarView-Code System-Code Index 533 0, // 0 534 0, // VK_LBUTTON 1 535 0, // VK_RBUTTON 2 536 0, // VK_CANCEL 3 537 0, // VK_MBUTTON 4 538 0, // 5 539 0, // 6 540 0, // 7 541 KEY_BACKSPACE, // VK_BACK 8 542 KEY_TAB, // VK_TAB 9 543 0, // 10 544 0, // 11 545 0, // VK_CLEAR 12 546 KEY_RETURN, // VK_RETURN 13 547 0, // 14 548 0, // 15 549 0, // VK_SHIFT 16 550 0, // VK_CONTROL 17 551 0, // VK_MENU 18 552 0, // VK_PAUSE 19 553 0, // VK_CAPITAL 20 554 0, // VK_HANGUL 21 555 0, // 22 556 0, // 23 557 0, // 24 558 KEY_HANGUL_HANJA, // VK_HANJA 25 559 0, // 26 560 KEY_ESCAPE, // VK_ESCAPE 27 561 0, // 28 562 0, // 29 563 0, // 30 564 0, // 31 565 KEY_SPACE, // VK_SPACE 32 566 KEY_PAGEUP, // VK_PRIOR 33 567 KEY_PAGEDOWN, // VK_NEXT 34 568 KEY_END, // VK_END 35 569 KEY_HOME, // VK_HOME 36 570 KEY_LEFT, // VK_LEFT 37 571 KEY_UP, // VK_UP 38 572 KEY_RIGHT, // VK_RIGHT 39 573 KEY_DOWN, // VK_DOWN 40 574 0, // VK_SELECT 41 575 0, // VK_PRINT 42 576 0, // VK_EXECUTE 43 577 0, // VK_SNAPSHOT 44 578 KEY_INSERT, // VK_INSERT 45 579 KEY_DELETE, // VK_DELETE 46 580 KEY_HELP, // VK_HELP 47 581 KEY_0, // 48 582 KEY_1, // 49 583 KEY_2, // 50 584 KEY_3, // 51 585 KEY_4, // 52 586 KEY_5, // 53 587 KEY_6, // 54 588 KEY_7, // 55 589 KEY_8, // 56 590 KEY_9, // 57 591 0, // 58 592 0, // 59 593 0, // 60 594 0, // 61 595 0, // 62 596 0, // 63 597 0, // 64 598 KEY_A, // 65 599 KEY_B, // 66 600 KEY_C, // 67 601 KEY_D, // 68 602 KEY_E, // 69 603 KEY_F, // 70 604 KEY_G, // 71 605 KEY_H, // 72 606 KEY_I, // 73 607 KEY_J, // 74 608 KEY_K, // 75 609 KEY_L, // 76 610 KEY_M, // 77 611 KEY_N, // 78 612 KEY_O, // 79 613 KEY_P, // 80 614 KEY_Q, // 81 615 KEY_R, // 82 616 KEY_S, // 83 617 KEY_T, // 84 618 KEY_U, // 85 619 KEY_V, // 86 620 KEY_W, // 87 621 KEY_X, // 88 622 KEY_Y, // 89 623 KEY_Z, // 90 624 0, // VK_LWIN 91 625 0, // VK_RWIN 92 626 KEY_CONTEXTMENU, // VK_APPS 93 627 0, // 94 628 0, // 95 629 KEY_0, // VK_NUMPAD0 96 630 KEY_1, // VK_NUMPAD1 97 631 KEY_2, // VK_NUMPAD2 98 632 KEY_3, // VK_NUMPAD3 99 633 KEY_4, // VK_NUMPAD4 100 634 KEY_5, // VK_NUMPAD5 101 635 KEY_6, // VK_NUMPAD6 102 636 KEY_7, // VK_NUMPAD7 103 637 KEY_8, // VK_NUMPAD8 104 638 KEY_9, // VK_NUMPAD9 105 639 KEY_MULTIPLY, // VK_MULTIPLY 106 640 KEY_ADD, // VK_ADD 107 641 KEY_DECIMAL, // VK_SEPARATOR 108 642 KEY_SUBTRACT, // VK_SUBTRACT 109 643 KEY_DECIMAL, // VK_DECIMAL 110 644 KEY_DIVIDE, // VK_DIVIDE 111 645 KEY_F1, // VK_F1 112 646 KEY_F2, // VK_F2 113 647 KEY_F3, // VK_F3 114 648 KEY_F4, // VK_F4 115 649 KEY_F5, // VK_F5 116 650 KEY_F6, // VK_F6 117 651 KEY_F7, // VK_F7 118 652 KEY_F8, // VK_F8 119 653 KEY_F9, // VK_F9 120 654 KEY_F10, // VK_F10 121 655 KEY_F11, // VK_F11 122 656 KEY_F12, // VK_F12 123 657 KEY_F13, // VK_F13 124 658 KEY_F14, // VK_F14 125 659 KEY_F15, // VK_F15 126 660 KEY_F16, // VK_F16 127 661 KEY_F17, // VK_F17 128 662 KEY_F18, // VK_F18 129 663 KEY_F19, // VK_F19 130 664 KEY_F20, // VK_F20 131 665 KEY_F21, // VK_F21 132 666 KEY_F22, // VK_F22 133 667 KEY_F23, // VK_F23 134 668 KEY_F24, // VK_F24 135 669 0, // 136 670 0, // 137 671 0, // 138 672 0, // 139 673 0, // 140 674 0, // 141 675 0, // 142 676 0, // 143 677 0, // NUMLOCK 144 678 0 // SCROLLLOCK 145 679 }; 680 681 static UINT ImplSalGetWheelScrollLines() 682 { 683 UINT nScrLines = 0; 684 HWND hWndMsWheel = FindWindowW( MSH_WHEELMODULE_CLASS, MSH_WHEELMODULE_TITLE ); 685 if ( hWndMsWheel ) 686 { 687 UINT nGetScrollLinesMsgId = RegisterWindowMessageW( MSH_SCROLL_LINES ); 688 nScrLines = static_cast<UINT>(SendMessageW( hWndMsWheel, nGetScrollLinesMsgId, 0, 0 )); 689 } 690 691 if ( !nScrLines ) 692 if( !SystemParametersInfoW( SPI_GETWHEELSCROLLLINES, 0, &nScrLines, 0 ) ) 693 nScrLines = 0 ; 694 695 if ( !nScrLines ) 696 nScrLines = 3; 697 698 return nScrLines; 699 } 700 701 static UINT ImplSalGetWheelScrollChars() 702 { 703 UINT nScrChars = 0; 704 if( !SystemParametersInfoW( SPI_GETWHEELSCROLLCHARS, 0, &nScrChars, 0 ) ) 705 { 706 return 3; 707 } 708 709 // system settings successfully read 710 return nScrChars; 711 } 712 713 static void ImplSalAddBorder( const WinSalFrame* pFrame, int& width, int& height ) 714 { 715 // transform client size into window size 716 RECT aWinRect; 717 aWinRect.left = 0; 718 aWinRect.right = width-1; 719 aWinRect.top = 0; 720 aWinRect.bottom = height-1; 721 AdjustWindowRectEx( &aWinRect, GetWindowStyle( pFrame->mhWnd ), 722 FALSE, GetWindowExStyle( pFrame->mhWnd ) ); 723 width = aWinRect.right - aWinRect.left + 1; 724 height = aWinRect.bottom - aWinRect.top + 1; 725 } 726 727 static void ImplSalCalcFullScreenSize( const WinSalFrame* pFrame, 728 int& rX, int& rY, int& rDX, int& rDY ) 729 { 730 // set window to screen size 731 int nFrameX; 732 int nFrameY; 733 int nCaptionY; 734 int nScreenX = 0; 735 int nScreenY = 0; 736 int nScreenDX = 0; 737 int nScreenDY = 0; 738 739 if ( pFrame->mbSizeBorder ) 740 { 741 nFrameX = GetSystemMetrics( SM_CXSIZEFRAME ); 742 nFrameY = GetSystemMetrics( SM_CYSIZEFRAME ); 743 } 744 else if ( pFrame->mbFixBorder ) 745 { 746 nFrameX = GetSystemMetrics( SM_CXFIXEDFRAME ); 747 nFrameY = GetSystemMetrics( SM_CYFIXEDFRAME ); 748 } 749 else if ( pFrame->mbBorder ) 750 { 751 nFrameX = GetSystemMetrics( SM_CXBORDER ); 752 nFrameY = GetSystemMetrics( SM_CYBORDER ); 753 } 754 else 755 { 756 nFrameX = 0; 757 nFrameY = 0; 758 } 759 if ( pFrame->mbCaption ) 760 nCaptionY = GetSystemMetrics( SM_CYCAPTION ); 761 else 762 nCaptionY = 0; 763 764 try 765 { 766 tools::Rectangle aRect; 767 sal_Int32 nMonitors = Application::GetScreenCount(); 768 if( (pFrame->mnDisplay >= 0) && (pFrame->mnDisplay < nMonitors) ) 769 { 770 aRect = Application::GetScreenPosSizePixel(pFrame->mnDisplay); 771 } 772 else 773 { 774 for (sal_Int32 i = 0; i < nMonitors; i++) 775 aRect.Union(Application::GetScreenPosSizePixel(i)); 776 } 777 nScreenX = aRect.Left(); 778 nScreenY = aRect.Top(); 779 nScreenDX = aRect.GetWidth(); 780 nScreenDY = aRect.GetHeight(); 781 } 782 catch( Exception& ) 783 { 784 } 785 786 if( !nScreenDX || !nScreenDY ) 787 { 788 nScreenDX = GetSystemMetrics( SM_CXSCREEN ); 789 nScreenDY = GetSystemMetrics( SM_CYSCREEN ); 790 } 791 792 rX = nScreenX -nFrameX; 793 rY = nScreenY -(nFrameY+nCaptionY); 794 rDX = nScreenDX+(nFrameX*2); 795 rDY = nScreenDY+(nFrameY*2)+nCaptionY; 796 } 797 798 static void ImplSalFrameFullScreenPos( WinSalFrame* pFrame, bool bAlways = false ) 799 { 800 if ( bAlways || !IsIconic( pFrame->mhWnd ) ) 801 { 802 // set window to screen size 803 int nX; 804 int nY; 805 int nWidth; 806 int nHeight; 807 ImplSalCalcFullScreenSize( pFrame, nX, nY, nWidth, nHeight ); 808 SetWindowPos( pFrame->mhWnd, nullptr, 809 nX, nY, nWidth, nHeight, 810 SWP_NOZORDER | SWP_NOACTIVATE ); 811 } 812 } 813 814 namespace { 815 816 void SetForegroundWindow_Impl(HWND hwnd) 817 { 818 if (!Application::IsHeadlessModeEnabled()) 819 SetForegroundWindow(hwnd); 820 } 821 822 } 823 824 WinSalFrame::WinSalFrame() 825 { 826 SalData* pSalData = GetSalData(); 827 828 mhWnd = nullptr; 829 mhCursor = LoadCursor( nullptr, IDC_ARROW ); 830 mhDefIMEContext = nullptr; 831 mpLocalGraphics = nullptr; 832 mpThreadGraphics = nullptr; 833 m_eState = vcl::WindowState::Normal; 834 mnShowState = SW_SHOWNORMAL; 835 mnMinWidth = 0; 836 mnMinHeight = 0; 837 mnMaxWidth = SHRT_MAX; 838 mnMaxHeight = SHRT_MAX; 839 mnInputLang = 0; 840 mnInputCodePage = 0; 841 mbGraphics = false; 842 mbCaption = false; 843 mbBorder = false; 844 mbFixBorder = false; 845 mbSizeBorder = false; 846 mbFullScreenCaption = false; 847 mbPresentation = false; 848 mbInShow = false; 849 mbRestoreMaximize = false; 850 mbInMoveMsg = false; 851 mbInSizeMsg = false; 852 mbFullScreenToolWin = false; 853 mbDefPos = true; 854 mbOverwriteState = true; 855 mbIME = false; 856 mbHandleIME = false; 857 mbSpezIME = false; 858 mbAtCursorIME = false; 859 mbCandidateMode = false; 860 mbFloatWin = false; 861 mbNoIcon = false; 862 mSelectedhMenu = nullptr; 863 mLastActivatedhMenu = nullptr; 864 mpClipRgnData = nullptr; 865 mbFirstClipRect = true; 866 mpNextClipRect = nullptr; 867 mnDisplay = 0; 868 mbPropertiesStored = false; 869 870 // get data, when making 1st frame 871 if ( !pSalData->mpFirstFrame ) 872 { 873 if ( !aSalShlData.mnWheelScrollLines ) 874 aSalShlData.mnWheelScrollLines = ImplSalGetWheelScrollLines(); 875 if ( !aSalShlData.mnWheelScrollChars ) 876 aSalShlData.mnWheelScrollChars = ImplSalGetWheelScrollChars(); 877 } 878 879 // insert frame in framelist 880 mpNextFrame = pSalData->mpFirstFrame; 881 pSalData->mpFirstFrame = this; 882 } 883 884 void WinSalFrame::updateScreenNumber() 885 { 886 if( mnDisplay == -1 ) // spans all monitors 887 return; 888 WinSalSystem* pSys = static_cast<WinSalSystem*>(ImplGetSalSystem()); 889 if( pSys ) 890 { 891 const std::vector<WinSalSystem::DisplayMonitor>& rMonitors = 892 pSys->getMonitors(); 893 Point aPoint(maGeometry.pos()); 894 size_t nMon = rMonitors.size(); 895 for( size_t i = 0; i < nMon; i++ ) 896 { 897 if( rMonitors[i].m_aArea.Contains( aPoint ) ) 898 { 899 mnDisplay = static_cast<sal_Int32>(i); 900 maGeometry.setScreen(static_cast<unsigned int>(i)); 901 } 902 } 903 } 904 } 905 906 bool WinSalFrame::ReleaseFrameGraphicsDC( WinSalGraphics* pGraphics ) 907 { 908 assert( pGraphics ); 909 SalData* pSalData = GetSalData(); 910 HDC hDC = pGraphics->getHDC(); 911 if ( !hDC ) 912 return false; 913 pGraphics->setHDC(nullptr); 914 SendMessageW( pSalData->mpInstance->mhComWnd, SAL_MSG_RELEASEDC, 915 reinterpret_cast<WPARAM>(mhWnd), reinterpret_cast<LPARAM>(hDC) ); 916 if ( pGraphics == mpThreadGraphics ) 917 pSalData->mnCacheDCInUse--; 918 return true; 919 } 920 921 WinSalFrame::~WinSalFrame() 922 { 923 SalData* pSalData = GetSalData(); 924 925 if( mpClipRgnData ) 926 delete [] reinterpret_cast<BYTE*>(mpClipRgnData); 927 928 // remove frame from framelist 929 WinSalFrame** ppFrame = &pSalData->mpFirstFrame; 930 for(; (*ppFrame != this) && *ppFrame; ppFrame = &(*ppFrame)->mpNextFrame ); 931 if( *ppFrame ) 932 *ppFrame = mpNextFrame; 933 mpNextFrame = nullptr; 934 935 // destroy the thread SalGraphics 936 if ( mpThreadGraphics ) 937 { 938 ReleaseFrameGraphicsDC( mpThreadGraphics ); 939 delete mpThreadGraphics; 940 mpThreadGraphics = nullptr; 941 } 942 943 // destroy the local SalGraphics 944 if ( mpLocalGraphics ) 945 { 946 ReleaseFrameGraphicsDC( mpLocalGraphics ); 947 delete mpLocalGraphics; 948 mpLocalGraphics = nullptr; 949 } 950 951 if ( mhWnd ) 952 { 953 // reset mouse leave data 954 if ( pSalData->mhWantLeaveMsg == mhWnd ) 955 { 956 pSalData->mhWantLeaveMsg = nullptr; 957 if ( pSalData->mpMouseLeaveTimer ) 958 { 959 delete pSalData->mpMouseLeaveTimer; 960 pSalData->mpMouseLeaveTimer = nullptr; 961 } 962 } 963 964 // remove windows properties 965 if ( mbPropertiesStored ) 966 SetApplicationID( OUString() ); 967 968 // destroy system frame 969 if ( !DestroyWindow( mhWnd ) ) 970 SetWindowPtr( mhWnd, nullptr ); 971 972 mhWnd = nullptr; 973 } 974 } 975 976 bool WinSalFrame::InitFrameGraphicsDC( WinSalGraphics *pGraphics, HDC hDC, HWND hWnd ) 977 { 978 SalData* pSalData = GetSalData(); 979 assert( pGraphics ); 980 pGraphics->setHWND( hWnd ); 981 982 HDC hCurrentDC = pGraphics->getHDC(); 983 assert( !hCurrentDC || (hCurrentDC == hDC) ); 984 if ( hCurrentDC ) 985 return true; 986 pGraphics->setHDC( hDC ); 987 988 if ( !hDC ) 989 return false; 990 991 if ( pSalData->mhDitherPal ) 992 pGraphics->setPalette(pSalData->mhDitherPal); 993 994 if ( pGraphics == mpThreadGraphics ) 995 pSalData->mnCacheDCInUse++; 996 return true; 997 } 998 999 SalGraphics* WinSalFrame::AcquireGraphics() 1000 { 1001 if ( mbGraphics || !mhWnd ) 1002 return nullptr; 1003 1004 SalData* pSalData = GetSalData(); 1005 WinSalGraphics *pGraphics = nullptr; 1006 HDC hDC = nullptr; 1007 1008 // Other threads get an own DC, because Windows modify in the 1009 // other case our DC (changing clip region), when they send a 1010 // WM_ERASEBACKGROUND message 1011 if ( !pSalData->mpInstance->IsMainThread() ) 1012 { 1013 // We use only three CacheDC's for all threads, because W9x is limited 1014 // to max. 5 Cache DC's per thread 1015 if ( pSalData->mnCacheDCInUse >= 3 ) 1016 return nullptr; 1017 1018 if ( !mpThreadGraphics ) 1019 mpThreadGraphics = new WinSalGraphics(WinSalGraphics::WINDOW, true, mhWnd, this); 1020 pGraphics = mpThreadGraphics; 1021 assert( !pGraphics->getHDC() ); 1022 hDC = reinterpret_cast<HDC>(static_cast<sal_IntPtr>(SendMessageW( pSalData->mpInstance->mhComWnd, 1023 SAL_MSG_GETCACHEDDC, reinterpret_cast<WPARAM>(mhWnd), 0 ))); 1024 } 1025 else 1026 { 1027 if ( !mpLocalGraphics ) 1028 mpLocalGraphics = new WinSalGraphics(WinSalGraphics::WINDOW, true, mhWnd, this); 1029 pGraphics = mpLocalGraphics; 1030 hDC = pGraphics->getHDC(); 1031 if ( !hDC ) 1032 hDC = GetDC( mhWnd ); 1033 } 1034 1035 mbGraphics = InitFrameGraphicsDC( pGraphics, hDC, mhWnd ); 1036 return mbGraphics ? pGraphics : nullptr; 1037 } 1038 1039 void WinSalFrame::ReleaseGraphics( SalGraphics* pGraphics ) 1040 { 1041 if ( mpThreadGraphics == pGraphics ) 1042 ReleaseFrameGraphicsDC( mpThreadGraphics ); 1043 mbGraphics = false; 1044 } 1045 1046 bool WinSalFrame::PostEvent(std::unique_ptr<ImplSVEvent> pData) 1047 { 1048 bool const ret = PostMessageW(mhWnd, SAL_MSG_USEREVENT, 0, reinterpret_cast<LPARAM>(pData.get())); 1049 SAL_WARN_IF(!ret, "vcl", "ERROR: PostMessage() failed!"); 1050 if (ret) 1051 pData.release(); 1052 return ret; 1053 } 1054 1055 void WinSalFrame::SetTitle( const OUString& rTitle ) 1056 { 1057 static_assert( sizeof( WCHAR ) == sizeof( sal_Unicode ), "must be the same size" ); 1058 1059 SetWindowTextW( mhWnd, o3tl::toW(rTitle.getStr()) ); 1060 } 1061 1062 void WinSalFrame::SetIcon( sal_uInt16 nIcon ) 1063 { 1064 // If we have a window without an Icon (for example a dialog), ignore this call 1065 if ( mbNoIcon ) 1066 return; 1067 1068 // 0 means default (class) icon 1069 HICON hIcon = nullptr, hSmIcon = nullptr; 1070 if ( !nIcon ) 1071 nIcon = 1; 1072 1073 ImplLoadSalIcon( nIcon, hIcon, hSmIcon ); 1074 1075 SAL_WARN_IF( !hIcon , "vcl", "WinSalFrame::SetIcon(): Could not load large icon !" ); 1076 SAL_WARN_IF( !hSmIcon , "vcl", "WinSalFrame::SetIcon(): Could not load small icon !" ); 1077 1078 SendMessageW( mhWnd, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(hIcon) ); 1079 SendMessageW( mhWnd, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(hSmIcon) ); 1080 } 1081 1082 void WinSalFrame::SetMenu( SalMenu* pSalMenu ) 1083 { 1084 WinSalMenu* pWMenu = static_cast<WinSalMenu*>(pSalMenu); 1085 if( pSalMenu && pWMenu->mbMenuBar ) 1086 ::SetMenu( mhWnd, pWMenu->mhMenu ); 1087 } 1088 1089 static HWND ImplGetParentHwnd( HWND hWnd ) 1090 { 1091 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 1092 if( !pFrame || !pFrame->GetWindow()) 1093 return ::GetParent( hWnd ); 1094 vcl::Window *pRealParent = pFrame->GetWindow()->ImplGetWindowImpl()->mpRealParent; 1095 if( pRealParent ) 1096 return static_cast<WinSalFrame*>(pRealParent->ImplGetWindowImpl()->mpFrame)->mhWnd; 1097 else 1098 return ::GetParent( hWnd ); 1099 1100 } 1101 1102 SalFrame* WinSalFrame::GetParent() const 1103 { 1104 return GetWindowPtr( ImplGetParentHwnd( mhWnd ) ); 1105 } 1106 1107 static void ImplSalShow( HWND hWnd, bool bVisible, bool bNoActivate ) 1108 { 1109 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 1110 if ( !pFrame ) 1111 return; 1112 1113 if ( bVisible ) 1114 { 1115 pFrame->mbDefPos = false; 1116 pFrame->mbOverwriteState = true; 1117 pFrame->mbInShow = true; 1118 1119 // #i4715, save position 1120 RECT aRectPreMatrox, aRectPostMatrox; 1121 GetWindowRect( hWnd, &aRectPreMatrox ); 1122 1123 vcl::DeletionListener aDogTag( pFrame ); 1124 if( bNoActivate ) 1125 ShowWindow( hWnd, SW_SHOWNOACTIVATE ); 1126 else 1127 ShowWindow( hWnd, pFrame->mnShowState ); 1128 if( aDogTag.isDeleted() ) 1129 return; 1130 1131 if (pFrame->mbFloatWin && !(pFrame->mnStyle & SalFrameStyleFlags::NOSHADOW)) 1132 { 1133 // erase the window immediately to improve XP shadow effect 1134 // otherwise the shadow may appears long time before the rest of the window 1135 // especially when accessibility is on 1136 HDC dc = GetDC( hWnd ); 1137 RECT aRect; 1138 GetClientRect( hWnd, &aRect ); 1139 FillRect( dc, &aRect, reinterpret_cast<HBRUSH>(COLOR_MENU+1) ); // choose the menucolor, because its mostly noticeable for menus 1140 ReleaseDC( hWnd, dc ); 1141 } 1142 1143 // #i4715, matrox centerpopup might have changed our position 1144 // reposition popups without caption (menus, dropdowns, tooltips) 1145 GetWindowRect( hWnd, &aRectPostMatrox ); 1146 if( (GetWindowStyle( hWnd ) & WS_POPUP) && 1147 !pFrame->mbCaption && 1148 (aRectPreMatrox.left != aRectPostMatrox.left || aRectPreMatrox.top != aRectPostMatrox.top) ) 1149 SetWindowPos( hWnd, nullptr, aRectPreMatrox.left, aRectPreMatrox.top, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE ); 1150 1151 if( aDogTag.isDeleted() ) 1152 return; 1153 vcl::Window *pClientWin = pFrame->GetWindow()->ImplGetClientWindow(); 1154 if ( pFrame->mbFloatWin || ( pClientWin && (pClientWin->GetStyle() & WB_SYSTEMFLOATWIN) ) ) 1155 pFrame->mnShowState = SW_SHOWNOACTIVATE; 1156 else 1157 pFrame->mnShowState = SW_SHOW; 1158 // hide toolbar for W98 1159 if ( pFrame->mbPresentation ) 1160 { 1161 HWND hWndParent = ::GetParent( hWnd ); 1162 if ( hWndParent ) 1163 SetForegroundWindow_Impl( hWndParent ); 1164 SetForegroundWindow_Impl( hWnd ); 1165 } 1166 1167 pFrame->mbInShow = false; 1168 pFrame->updateScreenNumber(); 1169 1170 // Direct Paint only, if we get the SolarMutex 1171 if ( ImplSalYieldMutexTryToAcquire() ) 1172 { 1173 UpdateWindow( hWnd ); 1174 ImplSalYieldMutexRelease(); 1175 } 1176 } 1177 else 1178 { 1179 ShowWindow( hWnd, SW_HIDE ); 1180 } 1181 } 1182 1183 void WinSalFrame::SetExtendedFrameStyle( SalExtStyle ) 1184 { 1185 } 1186 1187 void WinSalFrame::Show( bool bVisible, bool bNoActivate ) 1188 { 1189 // Post this Message to the window, because this only works 1190 // in the thread of the window, which has create this window. 1191 // We post this message to avoid deadlocks 1192 if ( GetSalData()->mnAppThreadId != GetCurrentThreadId() ) 1193 { 1194 bool const ret = PostMessageW(mhWnd, SAL_MSG_SHOW, WPARAM(bVisible), LPARAM(bNoActivate)); 1195 SAL_WARN_IF(!ret, "vcl", "ERROR: PostMessage() failed!"); 1196 } 1197 else 1198 ImplSalShow( mhWnd, bVisible, bNoActivate ); 1199 } 1200 1201 void WinSalFrame::SetMinClientSize( tools::Long nWidth, tools::Long nHeight ) 1202 { 1203 mnMinWidth = nWidth; 1204 mnMinHeight = nHeight; 1205 } 1206 1207 void WinSalFrame::SetMaxClientSize( tools::Long nWidth, tools::Long nHeight ) 1208 { 1209 mnMaxWidth = nWidth; 1210 mnMaxHeight = nHeight; 1211 } 1212 1213 void WinSalFrame::SetPosSize( tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, 1214 sal_uInt16 nFlags ) 1215 { 1216 bool bVisible = (GetWindowStyle( mhWnd ) & WS_VISIBLE) != 0; 1217 if ( !bVisible ) 1218 { 1219 vcl::Window *pClientWin = GetWindow()->ImplGetClientWindow(); 1220 if ( mbFloatWin || ( pClientWin && (pClientWin->GetStyle() & WB_SYSTEMFLOATWIN) ) ) 1221 mnShowState = SW_SHOWNOACTIVATE; 1222 else 1223 mnShowState = SW_SHOWNORMAL; 1224 } 1225 else 1226 { 1227 if ( IsIconic( mhWnd ) || IsZoomed( mhWnd ) ) 1228 ShowWindow( mhWnd, SW_RESTORE ); 1229 } 1230 1231 SalEvent nEvent = SalEvent::NONE; 1232 UINT nPosSize = 0; 1233 RECT aClientRect, aWindowRect; 1234 GetClientRect( mhWnd, &aClientRect ); // x,y always 0,0, but width and height without border 1235 GetWindowRect( mhWnd, &aWindowRect ); // x,y in screen coordinates, width and height with border 1236 1237 if ( !(nFlags & (SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y)) ) 1238 nPosSize |= SWP_NOMOVE; 1239 else 1240 { 1241 //SAL_WARN_IF( !nX || !nY, "vcl", " Windowposition of (0,0) requested!" ); 1242 nEvent = SalEvent::Move; 1243 } 1244 if ( !(nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT)) ) 1245 nPosSize |= SWP_NOSIZE; 1246 else 1247 nEvent = (nEvent == SalEvent::Move) ? SalEvent::MoveResize : SalEvent::Resize; 1248 1249 if ( !(nFlags & SAL_FRAME_POSSIZE_X) ) 1250 nX = aWindowRect.left; 1251 if ( !(nFlags & SAL_FRAME_POSSIZE_Y) ) 1252 nY = aWindowRect.top; 1253 if ( !(nFlags & SAL_FRAME_POSSIZE_WIDTH) ) 1254 nWidth = aClientRect.right-aClientRect.left; 1255 if ( !(nFlags & SAL_FRAME_POSSIZE_HEIGHT) ) 1256 nHeight = aClientRect.bottom-aClientRect.top; 1257 1258 // Calculate window size including the border 1259 RECT aWinRect; 1260 aWinRect.left = 0; 1261 aWinRect.right = static_cast<int>(nWidth)-1; 1262 aWinRect.top = 0; 1263 aWinRect.bottom = static_cast<int>(nHeight)-1; 1264 AdjustWindowRectEx( &aWinRect, GetWindowStyle( mhWnd ), 1265 FALSE, GetWindowExStyle( mhWnd ) ); 1266 nWidth = aWinRect.right - aWinRect.left + 1; 1267 nHeight = aWinRect.bottom - aWinRect.top + 1; 1268 1269 HWND hWndParent = ImplGetParentHwnd(mhWnd); 1270 // For dialogs (WS_POPUP && WS_DLGFRAME), we need to find the "real" parent, 1271 // in case multiple dialogs are stacked on each other 1272 // (we don't want to position the second dialog relative to the first one, but relative to the main window) 1273 if ( (GetWindowStyle( mhWnd ) & WS_POPUP) && (GetWindowStyle( mhWnd ) & WS_DLGFRAME) ) // mhWnd is a dialog 1274 { 1275 while ( hWndParent && (GetWindowStyle( hWndParent ) & WS_POPUP) && (GetWindowStyle( hWndParent ) & WS_DLGFRAME) ) 1276 { 1277 hWndParent = ::ImplGetParentHwnd( hWndParent ); 1278 } 1279 } 1280 1281 if ( !(nPosSize & SWP_NOMOVE) && hWndParent ) 1282 { 1283 RECT aParentRect; 1284 GetClientRect( hWndParent, &aParentRect ); 1285 if( AllSettings::GetLayoutRTL() ) 1286 nX = (aParentRect.right - aParentRect.left) - nWidth-1 - nX; 1287 1288 //#110386#, do not transform coordinates for system child windows 1289 if( !(GetWindowStyle( mhWnd ) & WS_CHILD) ) 1290 { 1291 POINT aPt; 1292 aPt.x = nX; 1293 aPt.y = nY; 1294 1295 WinSalFrame* pParentFrame = GetWindowPtr( hWndParent ); 1296 if ( pParentFrame && pParentFrame->mnShowState == SW_SHOWMAXIMIZED ) 1297 { 1298 // #i42485#: parent will be shown maximized in which case 1299 // a ClientToScreen uses the wrong coordinates (i.e. those from the restore pos) 1300 // so use the (already updated) frame geometry for the transformation 1301 aPt.x += pParentFrame->maGeometry.x(); 1302 aPt.y += pParentFrame->maGeometry.y(); 1303 } 1304 else 1305 ClientToScreen( hWndParent, &aPt ); 1306 1307 nX = aPt.x; 1308 nY = aPt.y; 1309 1310 // the position is set 1311 mbDefPos = false; 1312 } 1313 } 1314 1315 // #i3338# to be conformant to UNIX we must position the client window, ie without the decoration 1316 // #i43250# if the position was read from the system (GetWindowRect(), see above), it must not be modified 1317 if ( nFlags & SAL_FRAME_POSSIZE_X ) 1318 nX += aWinRect.left; 1319 if ( nFlags & SAL_FRAME_POSSIZE_Y ) 1320 nY += aWinRect.top; 1321 1322 int nScreenX; 1323 int nScreenY; 1324 int nScreenWidth; 1325 int nScreenHeight; 1326 1327 RECT aRect; 1328 ImplSalGetWorkArea( mhWnd, &aRect, nullptr ); 1329 nScreenX = aRect.left; 1330 nScreenY = aRect.top; 1331 nScreenWidth = aRect.right-aRect.left; 1332 nScreenHeight = aRect.bottom-aRect.top; 1333 1334 if ( mbDefPos && (nPosSize & SWP_NOMOVE)) // we got no positioning request, so choose default position 1335 { 1336 // center window 1337 1338 HWND hWndParent2 = ::GetParent( mhWnd ); 1339 // Search for TopLevel Frame 1340 while ( hWndParent2 && (GetWindowStyle( hWndParent2 ) & WS_CHILD) ) 1341 hWndParent2 = ::GetParent( hWndParent2 ); 1342 // if the Window has a Parent, then center the window to 1343 // the parent, in the other case to the screen 1344 if ( hWndParent2 && !IsIconic( hWndParent2 ) && 1345 (GetWindowStyle( hWndParent2 ) & WS_VISIBLE) ) 1346 { 1347 RECT aParentRect; 1348 GetWindowRect( hWndParent2, &aParentRect ); 1349 int nParentWidth = aParentRect.right-aParentRect.left; 1350 int nParentHeight = aParentRect.bottom-aParentRect.top; 1351 1352 // We don't center, when Parent is smaller than our window 1353 if ( (nParentWidth-GetSystemMetrics( SM_CXFIXEDFRAME ) <= nWidth) && 1354 (nParentHeight-GetSystemMetrics( SM_CYFIXEDFRAME ) <= nHeight) ) 1355 { 1356 int nOff = GetSystemMetrics( SM_CYSIZEFRAME ) + GetSystemMetrics( SM_CYCAPTION ); 1357 nX = aParentRect.left+nOff; 1358 nY = aParentRect.top+nOff; 1359 } 1360 else 1361 { 1362 nX = (nParentWidth-nWidth)/2 + aParentRect.left; 1363 nY = (nParentHeight-nHeight)/2 + aParentRect.top; 1364 } 1365 } 1366 else 1367 { 1368 POINT pt; 1369 GetCursorPos( &pt ); 1370 RECT aRect2; 1371 aRect2.left = pt.x; 1372 aRect2.top = pt.y; 1373 aRect2.right = pt.x+2; 1374 aRect2.bottom = pt.y+2; 1375 1376 // dualmonitor support: 1377 // Get screensize of the monitor with the mouse pointer 1378 ImplSalGetWorkArea( mhWnd, &aRect2, &aRect2 ); 1379 1380 nX = ((aRect2.right-aRect2.left)-nWidth)/2 + aRect2.left; 1381 nY = ((aRect2.bottom-aRect2.top)-nHeight)/2 + aRect2.top; 1382 } 1383 1384 //if ( bVisible ) 1385 // mbDefPos = FALSE; 1386 1387 mbDefPos = false; // center only once 1388 nPosSize &= ~SWP_NOMOVE; // activate positioning 1389 nEvent = SalEvent::MoveResize; 1390 } 1391 1392 // Adjust Window in the screen 1393 bool bCheckOffScreen = true; 1394 1395 // but don't do this for floaters or ownerdraw windows that are currently moved interactively 1396 if( (mnStyle & SalFrameStyleFlags::FLOAT) && !(mnStyle & SalFrameStyleFlags::OWNERDRAWDECORATION) ) 1397 bCheckOffScreen = false; 1398 1399 if( mnStyle & SalFrameStyleFlags::OWNERDRAWDECORATION ) 1400 { 1401 // may be the window is currently being moved (mouse is captured), then no check is required 1402 if( mhWnd == ::GetCapture() ) 1403 bCheckOffScreen = false; 1404 else 1405 bCheckOffScreen = true; 1406 } 1407 1408 if( bCheckOffScreen ) 1409 { 1410 if ( nX+nWidth > nScreenX+nScreenWidth ) 1411 nX = (nScreenX+nScreenWidth) - nWidth; 1412 if ( nY+nHeight > nScreenY+nScreenHeight ) 1413 nY = (nScreenY+nScreenHeight) - nHeight; 1414 if ( nX < nScreenX ) 1415 nX = nScreenX; 1416 if ( nY < nScreenY ) 1417 nY = nScreenY; 1418 } 1419 1420 UINT nPosFlags = SWP_NOACTIVATE | SWP_NOOWNERZORDER | nPosSize; 1421 // bring floating windows always to top 1422 if( !(mnStyle & SalFrameStyleFlags::FLOAT) ) 1423 nPosFlags |= SWP_NOZORDER; // do not change z-order 1424 1425 SetWindowPos( mhWnd, HWND_TOP, nX, nY, static_cast<int>(nWidth), static_cast<int>(nHeight), nPosFlags ); 1426 1427 UpdateFrameGeometry(this); 1428 1429 // Notification -- really ??? 1430 if( nEvent != SalEvent::NONE ) 1431 CallCallback( nEvent, nullptr ); 1432 } 1433 1434 void WinSalFrame::ImplSetParentFrame( HWND hNewParentWnd, bool bAsChild ) 1435 { 1436 // save hwnd, will be overwritten in WM_CREATE during createwindow 1437 HWND hWndOld = mhWnd; 1438 HWND hWndOldParent = ::GetParent( hWndOld ); 1439 SalData* pSalData = GetSalData(); 1440 1441 if( hNewParentWnd == hWndOldParent ) 1442 return; 1443 1444 ::std::vector< WinSalFrame* > children; 1445 ::std::vector< WinSalObject* > systemChildren; 1446 1447 // search child windows 1448 WinSalFrame *pFrame = pSalData->mpFirstFrame; 1449 while( pFrame ) 1450 { 1451 HWND hWndParent = ::GetParent( pFrame->mhWnd ); 1452 if( mhWnd == hWndParent ) 1453 children.push_back( pFrame ); 1454 pFrame = pFrame->mpNextFrame; 1455 } 1456 1457 // search system child windows (plugins etc.) 1458 WinSalObject *pObject = pSalData->mpFirstObject; 1459 while( pObject ) 1460 { 1461 HWND hWndParent = ::GetParent( pObject->mhWnd ); 1462 if( mhWnd == hWndParent ) 1463 systemChildren.push_back( pObject ); 1464 pObject = pObject->mpNextObject; 1465 } 1466 1467 // to recreate the DCs, if they were destroyed 1468 bool bHadLocalGraphics = false, bHadThreadGraphics = false; 1469 1470 HFONT hFont = nullptr; 1471 HPEN hPen = nullptr; 1472 HBRUSH hBrush = nullptr; 1473 1474 int oldCount = pSalData->mnCacheDCInUse; 1475 1476 // release the thread DC 1477 if ( mpThreadGraphics ) 1478 { 1479 // save current gdi objects before hdc is gone 1480 HDC hDC = mpThreadGraphics->getHDC(); 1481 if ( hDC ) 1482 { 1483 hFont = static_cast<HFONT>(GetCurrentObject( hDC, OBJ_FONT )); 1484 hPen = static_cast<HPEN>(GetCurrentObject( hDC, OBJ_PEN )); 1485 hBrush = static_cast<HBRUSH>(GetCurrentObject( hDC, OBJ_BRUSH )); 1486 } 1487 1488 bHadThreadGraphics = ReleaseFrameGraphicsDC( mpThreadGraphics ); 1489 assert( (bHadThreadGraphics && hDC) || (!bHadThreadGraphics && !hDC) ); 1490 } 1491 1492 // release the local DC 1493 if ( mpLocalGraphics ) 1494 bHadLocalGraphics = ReleaseFrameGraphicsDC( mpLocalGraphics ); 1495 1496 // create a new hwnd with the same styles 1497 HWND hWndParent = hNewParentWnd; 1498 // forward to main thread 1499 HWND hWnd = reinterpret_cast<HWND>(static_cast<sal_IntPtr>(SendMessageW( pSalData->mpInstance->mhComWnd, 1500 bAsChild ? SAL_MSG_RECREATECHILDHWND : SAL_MSG_RECREATEHWND, 1501 reinterpret_cast<WPARAM>(hWndParent), reinterpret_cast<LPARAM>(mhWnd) ))); 1502 1503 // succeeded ? 1504 SAL_WARN_IF( !IsWindow( hWnd ), "vcl", "WinSalFrame::SetParent not successful"); 1505 1506 // re-create thread DC 1507 if( bHadThreadGraphics ) 1508 { 1509 HDC hDC = reinterpret_cast<HDC>(static_cast<sal_IntPtr>( 1510 SendMessageW( pSalData->mpInstance->mhComWnd, 1511 SAL_MSG_GETCACHEDDC, reinterpret_cast<WPARAM>(hWnd), 0 ))); 1512 InitFrameGraphicsDC( mpThreadGraphics, hDC, hWnd ); 1513 if ( hDC ) 1514 { 1515 // re-select saved gdi objects 1516 if( hFont ) 1517 SelectObject( hDC, hFont ); 1518 if( hPen ) 1519 SelectObject( hDC, hPen ); 1520 if( hBrush ) 1521 SelectObject( hDC, hBrush ); 1522 1523 SAL_WARN_IF( oldCount != pSalData->mnCacheDCInUse, "vcl", "WinSalFrame::SetParent() hDC count corrupted"); 1524 } 1525 } 1526 1527 // re-create local DC 1528 if( bHadLocalGraphics ) 1529 InitFrameGraphicsDC( mpLocalGraphics, GetDC( hWnd ), hWnd ); 1530 1531 // TODO: add SetParent() call for SalObjects 1532 SAL_WARN_IF( !systemChildren.empty(), "vcl", "WinSalFrame::SetParent() parent of living system child window will be destroyed!"); 1533 1534 // reparent children before old parent is destroyed 1535 for (auto & child : children) 1536 child->ImplSetParentFrame( hWnd, false ); 1537 1538 children.clear(); 1539 systemChildren.clear(); 1540 1541 // Now destroy original HWND in the thread where it was created. 1542 SendMessageW( GetSalData()->mpInstance->mhComWnd, 1543 SAL_MSG_DESTROYHWND, WPARAM(0), reinterpret_cast<LPARAM>(hWndOld)); 1544 } 1545 1546 void WinSalFrame::SetParent( SalFrame* pNewParent ) 1547 { 1548 WinSalFrame::mbInReparent = true; 1549 ImplSetParentFrame( static_cast<WinSalFrame*>(pNewParent)->mhWnd, false ); 1550 WinSalFrame::mbInReparent = false; 1551 } 1552 1553 void WinSalFrame::SetPluginParent( SystemParentData* pNewParent ) 1554 { 1555 if ( pNewParent->hWnd == nullptr ) 1556 { 1557 pNewParent->hWnd = GetDesktopWindow(); 1558 } 1559 1560 WinSalFrame::mbInReparent = true; 1561 ImplSetParentFrame( pNewParent->hWnd, true ); 1562 WinSalFrame::mbInReparent = false; 1563 } 1564 1565 void WinSalFrame::GetWorkArea( tools::Rectangle &rRect ) 1566 { 1567 RECT aRect; 1568 ImplSalGetWorkArea( mhWnd, &aRect, nullptr ); 1569 rRect.SetLeft( aRect.left ); 1570 rRect.SetRight( aRect.right-1 ); 1571 rRect.SetTop( aRect.top ); 1572 rRect.SetBottom( aRect.bottom-1 ); 1573 } 1574 1575 void WinSalFrame::GetClientSize( tools::Long& rWidth, tools::Long& rHeight ) 1576 { 1577 rWidth = maGeometry.width(); 1578 rHeight = maGeometry.height(); 1579 } 1580 1581 void WinSalFrame::SetWindowState(const vcl::WindowData* pState) 1582 { 1583 // Check if the window fits into the screen, in case the screen 1584 // resolution changed 1585 int nX; 1586 int nY; 1587 int nWidth; 1588 int nHeight; 1589 int nScreenX; 1590 int nScreenY; 1591 int nScreenWidth; 1592 int nScreenHeight; 1593 1594 RECT aRect; 1595 ImplSalGetWorkArea( mhWnd, &aRect, nullptr ); 1596 // #102500# allow some overlap, the window could have been made a little larger than the physical screen 1597 nScreenX = aRect.left-10; 1598 nScreenY = aRect.top-10; 1599 nScreenWidth = aRect.right-aRect.left+20; 1600 nScreenHeight = aRect.bottom-aRect.top+20; 1601 1602 UINT nPosSize = 0; 1603 RECT aWinRect; 1604 GetWindowRect( mhWnd, &aWinRect ); 1605 1606 // to be consistent with Unix, the frame state is without(!) decoration 1607 // ->add the decoration 1608 RECT aRect2 = aWinRect; 1609 AdjustWindowRectEx( &aRect2, GetWindowStyle( mhWnd ), 1610 FALSE, GetWindowExStyle( mhWnd ) ); 1611 tools::Long nTopDeco = abs( aWinRect.top - aRect2.top ); 1612 tools::Long nLeftDeco = abs( aWinRect.left - aRect2.left ); 1613 tools::Long nBottomDeco = abs( aWinRect.bottom - aRect2.bottom ); 1614 tools::Long nRightDeco = abs( aWinRect.right - aRect2.right ); 1615 1616 // adjust window position/size to fit the screen 1617 if ( !(pState->mask() & vcl::WindowDataMask::Pos) ) 1618 nPosSize |= SWP_NOMOVE; 1619 if ( !(pState->mask() & vcl::WindowDataMask::Size) ) 1620 nPosSize |= SWP_NOSIZE; 1621 if ( pState->mask() & vcl::WindowDataMask::X ) 1622 nX = static_cast<int>(pState->x()) - nLeftDeco; 1623 else 1624 nX = aWinRect.left; 1625 if ( pState->mask() & vcl::WindowDataMask::Y ) 1626 nY = static_cast<int>(pState->y()) - nTopDeco; 1627 else 1628 nY = aWinRect.top; 1629 if ( pState->mask() & vcl::WindowDataMask::Width ) 1630 nWidth = static_cast<int>(pState->width()) + nLeftDeco + nRightDeco; 1631 else 1632 nWidth = aWinRect.right-aWinRect.left; 1633 if ( pState->mask() & vcl::WindowDataMask::Height ) 1634 nHeight = static_cast<int>(pState->height()) + nTopDeco + nBottomDeco; 1635 else 1636 nHeight = aWinRect.bottom-aWinRect.top; 1637 1638 // Adjust Window in the screen: 1639 // if it does not fit into the screen do nothing, ie default pos/size will be used 1640 // if there is an overlap with the screen border move the window while keeping its size 1641 1642 if( nWidth > nScreenWidth || nHeight > nScreenHeight ) 1643 nPosSize |= (SWP_NOMOVE | SWP_NOSIZE); 1644 1645 if ( nX+nWidth > nScreenX+nScreenWidth ) 1646 nX = (nScreenX+nScreenWidth) - nWidth; 1647 if ( nY+nHeight > nScreenY+nScreenHeight ) 1648 nY = (nScreenY+nScreenHeight) - nHeight; 1649 if ( nX < nScreenX ) 1650 nX = nScreenX; 1651 if ( nY < nScreenY ) 1652 nY = nScreenY; 1653 1654 // set Restore-Position 1655 WINDOWPLACEMENT aPlacement; 1656 aPlacement.length = sizeof( aPlacement ); 1657 GetWindowPlacement( mhWnd, &aPlacement ); 1658 1659 // set State 1660 const bool bIsMinimized = IsIconic(mhWnd); 1661 const bool bIsMaximized = IsZoomed(mhWnd); 1662 const bool bVisible = (GetWindowStyle(mhWnd) & WS_VISIBLE); 1663 bool bUpdateHiddenFramePos = false; 1664 if ( !bVisible ) 1665 { 1666 aPlacement.showCmd = SW_HIDE; 1667 1668 if (mbOverwriteState && (pState->mask() & vcl::WindowDataMask::State)) 1669 { 1670 if (pState->state() & vcl::WindowState::Minimized) 1671 mnShowState = SW_SHOWMINIMIZED; 1672 else if (pState->state() & vcl::WindowState::Maximized) 1673 { 1674 mnShowState = SW_SHOWMAXIMIZED; 1675 bUpdateHiddenFramePos = true; 1676 } 1677 else if (pState->state() & vcl::WindowState::Normal) 1678 mnShowState = SW_SHOWNORMAL; 1679 } 1680 } 1681 else 1682 { 1683 if ( pState->mask() & vcl::WindowDataMask::State ) 1684 { 1685 if ( pState->state() & vcl::WindowState::Minimized ) 1686 { 1687 if ( pState->state() & vcl::WindowState::Maximized ) 1688 aPlacement.flags |= WPF_RESTORETOMAXIMIZED; 1689 aPlacement.showCmd = SW_SHOWMINIMIZED; 1690 } 1691 else if ( pState->state() & vcl::WindowState::Maximized ) 1692 aPlacement.showCmd = SW_SHOWMAXIMIZED; 1693 else if ( pState->state() & vcl::WindowState::Normal ) 1694 aPlacement.showCmd = SW_RESTORE; 1695 } 1696 } 1697 1698 // if a window is neither minimized nor maximized or need not be 1699 // positioned visibly (that is in visible state), do not use 1700 // SetWindowPlacement since it calculates including the TaskBar 1701 if (!bIsMinimized && !bIsMaximized && (!bVisible || (aPlacement.showCmd == SW_RESTORE))) 1702 { 1703 if( bUpdateHiddenFramePos ) 1704 { 1705 RECT aStateRect; 1706 aStateRect.left = nX; 1707 aStateRect.top = nY; 1708 aStateRect.right = nX+nWidth; 1709 aStateRect.bottom = nY+nHeight; 1710 // #96084 set a useful internal window size because 1711 // the window will not be maximized (and the size updated) before show() 1712 SetMaximizedFrameGeometry( mhWnd, this, &aStateRect ); 1713 SetWindowPos( mhWnd, nullptr, 1714 maGeometry.x(), maGeometry.y(), maGeometry.width(), maGeometry.height(), 1715 SWP_NOZORDER | SWP_NOACTIVATE | nPosSize ); 1716 } 1717 else 1718 SetWindowPos( mhWnd, nullptr, 1719 nX, nY, nWidth, nHeight, 1720 SWP_NOZORDER | SWP_NOACTIVATE | nPosSize ); 1721 } 1722 else 1723 { 1724 if( !(nPosSize & (SWP_NOMOVE|SWP_NOSIZE)) ) 1725 { 1726 aPlacement.rcNormalPosition.left = nX-nScreenX; 1727 aPlacement.rcNormalPosition.top = nY-nScreenY; 1728 aPlacement.rcNormalPosition.right = nX+nWidth-nScreenX; 1729 aPlacement.rcNormalPosition.bottom = nY+nHeight-nScreenY; 1730 } 1731 SetWindowPlacement( mhWnd, &aPlacement ); 1732 } 1733 1734 if( !(nPosSize & SWP_NOMOVE) ) 1735 mbDefPos = false; // window was positioned 1736 } 1737 1738 bool WinSalFrame::GetWindowState(vcl::WindowData* pState) 1739 { 1740 pState->setPosSize(maGeometry.posSize()); 1741 pState->setState(m_eState); 1742 pState->setMask(vcl::WindowDataMask::PosSizeState); 1743 return true; 1744 } 1745 1746 void WinSalFrame::SetScreenNumber( unsigned int nNewScreen ) 1747 { 1748 WinSalSystem* pSys = static_cast<WinSalSystem*>(ImplGetSalSystem()); 1749 if( pSys ) 1750 { 1751 const std::vector<WinSalSystem::DisplayMonitor>& rMonitors = 1752 pSys->getMonitors(); 1753 size_t nMon = rMonitors.size(); 1754 if( nNewScreen < nMon ) 1755 { 1756 Point aOldMonPos, aNewMonPos( rMonitors[nNewScreen].m_aArea.TopLeft() ); 1757 Point aCurPos(maGeometry.pos()); 1758 for( size_t i = 0; i < nMon; i++ ) 1759 { 1760 if( rMonitors[i].m_aArea.Contains( aCurPos ) ) 1761 { 1762 aOldMonPos = rMonitors[i].m_aArea.TopLeft(); 1763 break; 1764 } 1765 } 1766 mnDisplay = nNewScreen; 1767 maGeometry.setScreen(nNewScreen); 1768 SetPosSize( aNewMonPos.X() + (maGeometry.x() - aOldMonPos.X()), 1769 aNewMonPos.Y() + (maGeometry.y() - aOldMonPos.Y()), 1770 0, 0, 1771 SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y ); 1772 } 1773 } 1774 } 1775 1776 void WinSalFrame::SetApplicationID( const OUString &rApplicationID ) 1777 { 1778 // http://msdn.microsoft.com/en-us/library/windows/desktop/dd378430(v=vs.85).aspx 1779 // A window's properties must be removed before the window is closed. 1780 1781 IPropertyStore *pps; 1782 HRESULT hr = SHGetPropertyStoreForWindow(mhWnd, IID_PPV_ARGS(&pps)); 1783 if (SUCCEEDED(hr)) 1784 { 1785 PROPVARIANT pv; 1786 if (!rApplicationID.isEmpty()) 1787 { 1788 hr = InitPropVariantFromString(o3tl::toW(rApplicationID.getStr()), &pv); 1789 mbPropertiesStored = true; 1790 } 1791 else 1792 // if rApplicationID we remove the property from the window, if present 1793 PropVariantInit(&pv); 1794 1795 if (SUCCEEDED(hr)) 1796 { 1797 hr = pps->SetValue(PKEY_AppUserModel_ID, pv); 1798 PropVariantClear(&pv); 1799 } 1800 pps->Release(); 1801 } 1802 } 1803 1804 void WinSalFrame::ShowFullScreen(const bool bFullScreen, const sal_Int32 nDisplay) 1805 { 1806 if ((isFullScreen() == bFullScreen) && (!bFullScreen || (mnDisplay == nDisplay))) 1807 return; 1808 1809 mnDisplay = nDisplay; 1810 1811 if ( bFullScreen ) 1812 { 1813 m_eState |= vcl::WindowState::FullScreen; 1814 // to hide the Windows taskbar 1815 DWORD nExStyle = GetWindowExStyle( mhWnd ); 1816 if ( nExStyle & WS_EX_TOOLWINDOW ) 1817 { 1818 mbFullScreenToolWin = true; 1819 nExStyle &= ~WS_EX_TOOLWINDOW; 1820 SetWindowExStyle( mhWnd, nExStyle ); 1821 } 1822 // save old position 1823 GetWindowRect( mhWnd, &maFullScreenRect ); 1824 1825 // save show state 1826 mnFullScreenShowState = mnShowState; 1827 if ( !(GetWindowStyle( mhWnd ) & WS_VISIBLE) ) 1828 mnShowState = SW_SHOW; 1829 1830 // Save caption state. 1831 mbFullScreenCaption = mbCaption; 1832 if (mbCaption) 1833 { 1834 DWORD nStyle = GetWindowStyle(mhWnd); 1835 SetWindowStyle(mhWnd, nStyle & ~WS_CAPTION); 1836 mbCaption = false; 1837 } 1838 1839 // set window to screen size 1840 ImplSalFrameFullScreenPos( this, true ); 1841 } 1842 else 1843 { 1844 m_eState &= ~vcl::WindowState::FullScreen; 1845 // when the ShowState has to be reset, hide the window first to 1846 // reduce flicker 1847 bool bVisible = (GetWindowStyle( mhWnd ) & WS_VISIBLE) != 0; 1848 if ( bVisible && (mnShowState != mnFullScreenShowState) ) 1849 ShowWindow( mhWnd, SW_HIDE ); 1850 1851 if ( mbFullScreenToolWin ) 1852 SetWindowExStyle( mhWnd, GetWindowExStyle( mhWnd ) | WS_EX_TOOLWINDOW ); 1853 mbFullScreenToolWin = false; 1854 1855 // Restore caption state. 1856 if (mbFullScreenCaption) 1857 { 1858 DWORD nStyle = GetWindowStyle(mhWnd); 1859 SetWindowStyle(mhWnd, nStyle | WS_CAPTION); 1860 } 1861 mbCaption = mbFullScreenCaption; 1862 1863 SetWindowPos( mhWnd, nullptr, 1864 maFullScreenRect.left, 1865 maFullScreenRect.top, 1866 maFullScreenRect.right-maFullScreenRect.left, 1867 maFullScreenRect.bottom-maFullScreenRect.top, 1868 SWP_NOZORDER | SWP_NOACTIVATE ); 1869 1870 // restore show state 1871 if ( mnShowState != mnFullScreenShowState ) 1872 { 1873 mnShowState = mnFullScreenShowState; 1874 if ( bVisible ) 1875 { 1876 mbInShow = true; 1877 ShowWindow( mhWnd, mnShowState ); 1878 mbInShow = false; 1879 UpdateWindow( mhWnd ); 1880 } 1881 } 1882 } 1883 } 1884 1885 void WinSalFrame::StartPresentation( bool bStart ) 1886 { 1887 if ( mbPresentation == bStart ) 1888 return; 1889 1890 mbPresentation = bStart; 1891 1892 if ( bStart ) 1893 { 1894 // turn off screen-saver / power saving when in Presentation mode 1895 SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED); 1896 } 1897 else 1898 { 1899 // turn on screen-saver / power saving back 1900 SetThreadExecutionState(ES_CONTINUOUS); 1901 } 1902 } 1903 1904 void WinSalFrame::SetAlwaysOnTop( bool bOnTop ) 1905 { 1906 HWND hWnd; 1907 if ( bOnTop ) 1908 hWnd = HWND_TOPMOST; 1909 else 1910 hWnd = HWND_NOTOPMOST; 1911 SetWindowPos( mhWnd, hWnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE ); 1912 } 1913 1914 static bool EnableAttachThreadInputHack() 1915 { 1916 OUString aBootstrapUri; 1917 if (osl_getProcessWorkingDir(&aBootstrapUri.pData) != osl_Process_E_None) 1918 return false; 1919 aBootstrapUri += "/bootstrap.ini"; 1920 1921 OUString aSystemFileName; 1922 if (osl::FileBase::getSystemPathFromFileURL(aBootstrapUri, aSystemFileName) != osl::FileBase::E_None) 1923 return false; 1924 if (aSystemFileName.getLength() > MAX_PATH) 1925 return false; 1926 1927 // this uses the Boost ini parser, instead of tools::Config, as we already use it to read other 1928 // values from bootstrap.ini in desktop/win32/source/loader.cxx, because that watchdog process 1929 // can't access LO libs. This way the handling is consistent. 1930 try 1931 { 1932 boost::property_tree::ptree pt; 1933 std::ifstream aFile(o3tl::toW(aSystemFileName.getStr())); 1934 boost::property_tree::ini_parser::read_ini(aFile, pt); 1935 const bool bEnabled = pt.get("Win32.EnableAttachThreadInputHack", false); 1936 SAL_WARN_IF(bEnabled, "vcl", "AttachThreadInput hack is enabled. Watch out for deadlocks!"); 1937 return bEnabled; 1938 } 1939 catch (...) 1940 { 1941 return false; 1942 } 1943 } 1944 1945 static void ImplSalToTop( HWND hWnd, SalFrameToTop nFlags ) 1946 { 1947 static const bool bEnableAttachThreadInputHack = EnableAttachThreadInputHack(); 1948 1949 WinSalFrame* pToTopFrame = GetWindowPtr( hWnd ); 1950 if( pToTopFrame && (pToTopFrame->mnStyle & SalFrameStyleFlags::SYSTEMCHILD) ) 1951 BringWindowToTop( hWnd ); 1952 1953 if ( nFlags & SalFrameToTop::ForegroundTask ) 1954 { 1955 // LO used to always call AttachThreadInput here, which resulted in deadlocks 1956 // in some installations for unknown reasons! 1957 if (bEnableAttachThreadInputHack) 1958 { 1959 // This magic code is necessary to connect the input focus of the 1960 // current window thread and the thread which owns the window that 1961 // should be the new foreground window. 1962 HWND hCurrWnd = GetForegroundWindow(); 1963 DWORD myThreadID = GetCurrentThreadId(); 1964 DWORD currThreadID = GetWindowThreadProcessId(hCurrWnd,nullptr); 1965 AttachThreadInput(myThreadID, currThreadID, TRUE); 1966 SetForegroundWindow_Impl(hWnd); 1967 AttachThreadInput(myThreadID, currThreadID, FALSE); 1968 } 1969 else 1970 SetForegroundWindow_Impl(hWnd); 1971 } 1972 1973 if ( nFlags & SalFrameToTop::RestoreWhenMin ) 1974 { 1975 HWND hIconicWnd = hWnd; 1976 while ( hIconicWnd ) 1977 { 1978 if ( IsIconic( hIconicWnd ) ) 1979 { 1980 WinSalFrame* pFrame = GetWindowPtr( hIconicWnd ); 1981 if ( pFrame ) 1982 { 1983 if ( GetWindowPtr( hWnd )->mbRestoreMaximize ) 1984 ShowWindow( hIconicWnd, SW_MAXIMIZE ); 1985 else 1986 ShowWindow( hIconicWnd, SW_RESTORE ); 1987 } 1988 else 1989 ShowWindow( hIconicWnd, SW_RESTORE ); 1990 } 1991 1992 hIconicWnd = ::GetParent( hIconicWnd ); 1993 } 1994 } 1995 1996 if ( !IsIconic( hWnd ) && IsWindowVisible( hWnd ) ) 1997 { 1998 SetFocus( hWnd ); 1999 2000 // Windows sometimes incorrectly reports to have the focus; 2001 // thus make sure to really get the focus 2002 if ( ::GetFocus() == hWnd ) 2003 SetForegroundWindow_Impl( hWnd ); 2004 } 2005 } 2006 2007 void WinSalFrame::ToTop( SalFrameToTop nFlags ) 2008 { 2009 nFlags &= ~SalFrameToTop::GrabFocus; // this flag is not needed on win32 2010 // Post this Message to the window, because this only works 2011 // in the thread of the window, which has create this window. 2012 // We post this message to avoid deadlocks 2013 if ( GetSalData()->mnAppThreadId != GetCurrentThreadId() ) 2014 { 2015 bool const ret = PostMessageW( mhWnd, SAL_MSG_TOTOP, static_cast<WPARAM>(nFlags), 0 ); 2016 SAL_WARN_IF(!ret, "vcl", "ERROR: PostMessage() failed!"); 2017 } 2018 else 2019 ImplSalToTop( mhWnd, nFlags ); 2020 } 2021 2022 void WinSalFrame::SetPointer( PointerStyle ePointerStyle ) 2023 { 2024 struct ImplPtrData 2025 { 2026 HCURSOR mhCursor; 2027 LPCTSTR mnSysId; 2028 UINT mnOwnId; 2029 }; 2030 2031 static o3tl::enumarray<PointerStyle, ImplPtrData> aImplPtrTab = 2032 { 2033 // [-loplugin:redundantfcast]: 2034 ImplPtrData{ nullptr, IDC_ARROW, 0 }, // POINTER_ARROW 2035 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_NULL }, // POINTER_NULL 2036 ImplPtrData{ nullptr, IDC_WAIT, 0 }, // POINTER_WAIT 2037 ImplPtrData{ nullptr, IDC_IBEAM, 0 }, // POINTER_TEXT 2038 ImplPtrData{ nullptr, IDC_HELP, 0 }, // POINTER_HELP 2039 ImplPtrData{ nullptr, IDC_CROSS, 0 }, // POINTER_CROSS 2040 ImplPtrData{ nullptr, IDC_SIZEALL, 0 }, // POINTER_MOVE 2041 ImplPtrData{ nullptr, IDC_SIZENS, 0 }, // POINTER_NSIZE 2042 ImplPtrData{ nullptr, IDC_SIZENS, 0 }, // POINTER_SSIZE 2043 ImplPtrData{ nullptr, IDC_SIZEWE, 0 }, // POINTER_WSIZE 2044 ImplPtrData{ nullptr, IDC_SIZEWE, 0 }, // POINTER_ESIZE 2045 ImplPtrData{ nullptr, IDC_SIZENWSE, 0 }, // POINTER_NWSIZE 2046 ImplPtrData{ nullptr, IDC_SIZENESW, 0 }, // POINTER_NESIZE 2047 ImplPtrData{ nullptr, IDC_SIZENESW, 0 }, // POINTER_SWSIZE 2048 ImplPtrData{ nullptr, IDC_SIZENWSE, 0 }, // POINTER_SESIZE 2049 ImplPtrData{ nullptr, IDC_SIZENS, 0 }, // POINTER_WINDOW_NSIZE 2050 ImplPtrData{ nullptr, IDC_SIZENS, 0 }, // POINTER_WINDOW_SSIZE 2051 ImplPtrData{ nullptr, IDC_SIZEWE, 0 }, // POINTER_WINDOW_WSIZE 2052 ImplPtrData{ nullptr, IDC_SIZEWE, 0 }, // POINTER_WINDOW_ESIZE 2053 ImplPtrData{ nullptr, IDC_SIZENWSE, 0 }, // POINTER_WINDOW_NWSIZE 2054 ImplPtrData{ nullptr, IDC_SIZENESW, 0 }, // POINTER_WINDOW_NESIZE 2055 ImplPtrData{ nullptr, IDC_SIZENESW, 0 }, // POINTER_WINDOW_SWSIZE 2056 ImplPtrData{ nullptr, IDC_SIZENWSE, 0 }, // POINTER_WINDOW_SESIZE 2057 ImplPtrData{ nullptr, IDC_SIZEWE, 0 }, // POINTER_HSPLIT 2058 ImplPtrData{ nullptr, IDC_SIZENS, 0 }, // POINTER_VSPLIT 2059 ImplPtrData{ nullptr, IDC_SIZEWE, 0 }, // POINTER_HSIZEBAR 2060 ImplPtrData{ nullptr, IDC_SIZENS, 0 }, // POINTER_VSIZEBAR 2061 ImplPtrData{ nullptr, IDC_HAND, 0 }, // POINTER_HAND 2062 ImplPtrData{ nullptr, IDC_HAND, 0 }, // POINTER_REFHAND 2063 ImplPtrData{ nullptr, IDC_PEN, 0 }, // POINTER_PEN 2064 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_MAGNIFY }, // POINTER_MAGNIFY 2065 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_FILL }, // POINTER_FILL 2066 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_ROTATE }, // POINTER_ROTATE 2067 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_HSHEAR }, // POINTER_HSHEAR 2068 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_VSHEAR }, // POINTER_VSHEAR 2069 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_MIRROR }, // POINTER_MIRROR 2070 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_CROOK }, // POINTER_CROOK 2071 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_CROP }, // POINTER_CROP 2072 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_MOVEPOINT }, // POINTER_MOVEPOINT 2073 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_MOVEBEZIERWEIGHT }, // POINTER_MOVEBEZIERWEIGHT 2074 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_MOVEDATA }, // POINTER_MOVEDATA 2075 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_COPYDATA }, // POINTER_COPYDATA 2076 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_LINKDATA }, // POINTER_LINKDATA 2077 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_MOVEDATALINK }, // POINTER_MOVEDATALINK 2078 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_COPYDATALINK }, // POINTER_COPYDATALINK 2079 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_MOVEFILE }, // POINTER_MOVEFILE 2080 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_COPYFILE }, // POINTER_COPYFILE 2081 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_LINKFILE }, // POINTER_LINKFILE 2082 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_MOVEFILELINK }, // POINTER_MOVEFILELINK 2083 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_COPYFILELINK }, // POINTER_COPYFILELINK 2084 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_MOVEFILES }, // POINTER_MOVEFILES 2085 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_COPYFILES }, // POINTER_COPYFILES 2086 ImplPtrData{ nullptr, IDC_NO, 0 }, // POINTER_NOTALLOWED 2087 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_DRAW_LINE }, // POINTER_DRAW_LINE 2088 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_DRAW_RECT }, // POINTER_DRAW_RECT 2089 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_DRAW_POLYGON }, // POINTER_DRAW_POLYGON 2090 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_DRAW_BEZIER }, // POINTER_DRAW_BEZIER 2091 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_DRAW_ARC }, // POINTER_DRAW_ARC 2092 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_DRAW_PIE }, // POINTER_DRAW_PIE 2093 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_DRAW_CIRCLECUT }, // POINTER_DRAW_CIRCLECUT 2094 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_DRAW_ELLIPSE }, // POINTER_DRAW_ELLIPSE 2095 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_DRAW_FREEHAND }, // POINTER_DRAW_FREEHAND 2096 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_DRAW_CONNECT }, // POINTER_DRAW_CONNECT 2097 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_DRAW_TEXT }, // POINTER_DRAW_TEXT 2098 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_DRAW_CAPTION }, // POINTER_DRAW_CAPTION 2099 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_CHART }, // POINTER_CHART 2100 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_DETECTIVE }, // POINTER_DETECTIVE 2101 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_PIVOT_COL }, // POINTER_PIVOT_COL 2102 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_PIVOT_ROW }, // POINTER_PIVOT_ROW 2103 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_PIVOT_FIELD }, // POINTER_PIVOT_FIELD 2104 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_CHAIN }, // POINTER_CHAIN 2105 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_CHAIN_NOTALLOWED }, // POINTER_CHAIN_NOTALLOWED 2106 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_AUTOSCROLL_N }, // POINTER_AUTOSCROLL_N 2107 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_AUTOSCROLL_S }, // POINTER_AUTOSCROLL_S 2108 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_AUTOSCROLL_W }, // POINTER_AUTOSCROLL_W 2109 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_AUTOSCROLL_E }, // POINTER_AUTOSCROLL_E 2110 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_AUTOSCROLL_NW }, // POINTER_AUTOSCROLL_NW 2111 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_AUTOSCROLL_NE }, // POINTER_AUTOSCROLL_NE 2112 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_AUTOSCROLL_SW }, // POINTER_AUTOSCROLL_SW 2113 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_AUTOSCROLL_SE }, // POINTER_AUTOSCROLL_SE 2114 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_AUTOSCROLL_NS }, // POINTER_AUTOSCROLL_NS 2115 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_AUTOSCROLL_WE }, // POINTER_AUTOSCROLL_WE 2116 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_AUTOSCROLL_NSWE }, // POINTER_AUTOSCROLL_NSWE 2117 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_TEXT_VERTICAL }, // POINTER_TEXT_VERTICAL 2118 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_PIVOT_DELETE }, // POINTER_PIVOT_DELETE 2119 2120 // #i32329# 2121 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_TAB_SELECT_S }, // POINTER_TAB_SELECT_S 2122 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_TAB_SELECT_E }, // POINTER_TAB_SELECT_E 2123 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_TAB_SELECT_SE }, // POINTER_TAB_SELECT_SE 2124 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_TAB_SELECT_W }, // POINTER_TAB_SELECT_W 2125 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_TAB_SELECT_SW }, // POINTER_TAB_SELECT_SW 2126 2127 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_HIDEWHITESPACE }, // POINTER_HIDEWHITESPACE 2128 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_SHOWWHITESPACE }, // POINTER_UNHIDEWHITESPACE 2129 2130 ImplPtrData{ nullptr, nullptr, SAL_RESID_POINTER_FATCROSS } // POINTER_FATCROSS 2131 }; 2132 2133 // Mousepointer loaded ? 2134 if ( !aImplPtrTab[ePointerStyle].mhCursor ) 2135 { 2136 if ( aImplPtrTab[ePointerStyle].mnOwnId ) 2137 aImplPtrTab[ePointerStyle].mhCursor = ImplLoadSalCursor( aImplPtrTab[ePointerStyle].mnOwnId ); 2138 else 2139 aImplPtrTab[ePointerStyle].mhCursor = LoadCursor( nullptr, aImplPtrTab[ePointerStyle].mnSysId ); 2140 } 2141 2142 // change the mouse pointer if different 2143 if ( mhCursor != aImplPtrTab[ePointerStyle].mhCursor ) 2144 { 2145 mhCursor = aImplPtrTab[ePointerStyle].mhCursor; 2146 SetCursor( mhCursor ); 2147 } 2148 } 2149 2150 void WinSalFrame::CaptureMouse( bool bCapture ) 2151 { 2152 // Send this Message to the window, because CaptureMouse() only work 2153 // in the thread of the window, which has create this window 2154 int nMsg; 2155 if ( bCapture ) 2156 nMsg = SAL_MSG_CAPTUREMOUSE; 2157 else 2158 nMsg = SAL_MSG_RELEASEMOUSE; 2159 SendMessageW( mhWnd, nMsg, 0, 0 ); 2160 } 2161 2162 void WinSalFrame::SetPointerPos( tools::Long nX, tools::Long nY ) 2163 { 2164 POINT aPt; 2165 aPt.x = static_cast<int>(nX); 2166 aPt.y = static_cast<int>(nY); 2167 ClientToScreen( mhWnd, &aPt ); 2168 SetCursorPos( aPt.x, aPt.y ); 2169 } 2170 2171 void WinSalFrame::Flush() 2172 { 2173 if(mpLocalGraphics) 2174 mpLocalGraphics->Flush(); 2175 if(mpThreadGraphics) 2176 mpThreadGraphics->Flush(); 2177 GdiFlush(); 2178 } 2179 2180 static void ImplSalFrameSetInputContext( HWND hWnd, const SalInputContext* pContext ) 2181 { 2182 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 2183 bool bIME(pContext->mnOptions & InputContextFlags::Text); 2184 if ( bIME ) 2185 { 2186 if ( !pFrame->mbIME ) 2187 { 2188 pFrame->mbIME = true; 2189 2190 if ( pFrame->mhDefIMEContext ) 2191 { 2192 ImmAssociateContext( pFrame->mhWnd, pFrame->mhDefIMEContext ); 2193 UINT nImeProps = ImmGetProperty( GetKeyboardLayout( 0 ), IGP_PROPERTY ); 2194 pFrame->mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0; 2195 pFrame->mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0; 2196 pFrame->mbHandleIME = !pFrame->mbSpezIME; 2197 } 2198 } 2199 2200 // When the application can't handle IME messages, then the 2201 // System should handle the IME handling 2202 if ( !(pContext->mnOptions & InputContextFlags::ExtText) ) 2203 pFrame->mbHandleIME = false; 2204 2205 // Set the Font for IME Handling 2206 if ( pContext->mpFont ) 2207 { 2208 HIMC hIMC = ImmGetContext( pFrame->mhWnd ); 2209 if ( hIMC ) 2210 { 2211 LOGFONTW aLogFont; 2212 ImplGetLogFontFromFontSelect(pContext->mpFont->GetFontSelectPattern(), 2213 nullptr, aLogFont); 2214 ImmSetCompositionFontW( hIMC, &aLogFont ); 2215 ImmReleaseContext( pFrame->mhWnd, hIMC ); 2216 } 2217 } 2218 } 2219 else 2220 { 2221 if ( pFrame->mbIME ) 2222 { 2223 pFrame->mbIME = false; 2224 pFrame->mbHandleIME = false; 2225 ImmAssociateContext( pFrame->mhWnd, nullptr ); 2226 } 2227 } 2228 } 2229 2230 void WinSalFrame::SetInputContext( SalInputContext* pContext ) 2231 { 2232 // Must be called in the main thread! 2233 SendMessageW( mhWnd, SAL_MSG_SETINPUTCONTEXT, 0, reinterpret_cast<LPARAM>(pContext) ); 2234 } 2235 2236 static void ImplSalFrameEndExtTextInput( HWND hWnd, EndExtTextInputFlags nFlags ) 2237 { 2238 HIMC hIMC = ImmGetContext( hWnd ); 2239 if ( hIMC ) 2240 { 2241 DWORD nIndex; 2242 if ( nFlags & EndExtTextInputFlags::Complete ) 2243 nIndex = CPS_COMPLETE; 2244 else 2245 nIndex = CPS_CANCEL; 2246 2247 ImmNotifyIME( hIMC, NI_COMPOSITIONSTR, nIndex, 0 ); 2248 ImmReleaseContext( hWnd, hIMC ); 2249 } 2250 } 2251 2252 void WinSalFrame::EndExtTextInput( EndExtTextInputFlags nFlags ) 2253 { 2254 // Must be called in the main thread! 2255 SendMessageW( mhWnd, SAL_MSG_ENDEXTTEXTINPUT, static_cast<WPARAM>(nFlags), 0 ); 2256 } 2257 2258 static void ImplGetKeyNameText( LONG lParam, sal_Unicode* pBuf, 2259 UINT& rCount, UINT nMaxSize, 2260 const char* pReplace ) 2261 { 2262 static_assert( sizeof( WCHAR ) == sizeof( sal_Unicode ), "must be the same size" ); 2263 2264 static const int nMaxKeyLen = 350; 2265 WCHAR aKeyBuf[ nMaxKeyLen ]; 2266 int nKeyLen = 0; 2267 if ( lParam ) 2268 { 2269 OUString aLang = Application::GetSettings().GetUILanguageTag().getLanguage(); 2270 OUString aRet; 2271 2272 aRet = ::vcl_sal::getKeysReplacementName( aLang, lParam ); 2273 if( aRet.isEmpty() ) 2274 { 2275 nKeyLen = GetKeyNameTextW( lParam, aKeyBuf, nMaxKeyLen ); 2276 SAL_WARN_IF( nKeyLen > nMaxKeyLen, "vcl", "Invalid key name length!" ); 2277 if( nKeyLen > nMaxKeyLen ) 2278 nKeyLen = 0; 2279 else if( nKeyLen > 0 ) 2280 { 2281 // Capitalize just the first letter of key names 2282 CharLowerBuffW( aKeyBuf, nKeyLen ); 2283 2284 bool bUpper = true; 2285 for( WCHAR *pW=aKeyBuf, *pE=pW+nKeyLen; pW < pE; ++pW ) 2286 { 2287 if( bUpper ) 2288 CharUpperBuffW( pW, 1 ); 2289 bUpper = (*pW=='+') || (*pW=='-') || (*pW==' ') || (*pW=='.'); 2290 } 2291 } 2292 } 2293 else 2294 { 2295 nKeyLen = aRet.getLength(); 2296 wcscpy( aKeyBuf, o3tl::toW( aRet.getStr() )); 2297 } 2298 } 2299 2300 if ( (nKeyLen > 0) || pReplace ) 2301 { 2302 if( (rCount > 0) && (rCount < nMaxSize) ) 2303 { 2304 pBuf[rCount] = '+'; 2305 rCount++; 2306 } 2307 2308 if( nKeyLen > 0 ) 2309 { 2310 WCHAR *pW = aKeyBuf, *pE = aKeyBuf + nKeyLen; 2311 while ((pW < pE) && *pW && (rCount < nMaxSize)) 2312 pBuf[rCount++] = *pW++; 2313 } 2314 else // fall back to provided default name 2315 { 2316 while( *pReplace && (rCount < nMaxSize) ) 2317 { 2318 pBuf[rCount] = *pReplace; 2319 rCount++; 2320 pReplace++; 2321 } 2322 } 2323 } 2324 else 2325 rCount = 0; 2326 } 2327 2328 OUString WinSalFrame::GetKeyName( sal_uInt16 nKeyCode ) 2329 { 2330 static const UINT nMaxKeyLen = 350; 2331 sal_Unicode aKeyBuf[ nMaxKeyLen ]; 2332 UINT nKeyBufLen = 0; 2333 UINT nSysCode = 0; 2334 2335 if ( nKeyCode & KEY_MOD1 ) 2336 { 2337 nSysCode = MapVirtualKeyW( VK_CONTROL, 0 ); 2338 nSysCode = (nSysCode << 16) | ((sal_uLong(1)) << 25); 2339 ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, "Ctrl" ); 2340 } 2341 2342 if ( nKeyCode & KEY_MOD2 ) 2343 { 2344 nSysCode = MapVirtualKeyW( VK_MENU, 0 ); 2345 nSysCode = (nSysCode << 16) | ((sal_uLong(1)) << 25); 2346 ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, "Alt" ); 2347 } 2348 2349 if ( nKeyCode & KEY_SHIFT ) 2350 { 2351 nSysCode = MapVirtualKeyW( VK_SHIFT, 0 ); 2352 nSysCode = (nSysCode << 16) | ((sal_uLong(1)) << 25); 2353 ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, "Shift" ); 2354 } 2355 2356 sal_uInt16 nCode = nKeyCode & 0x0FFF; 2357 sal_uLong nSysCode2 = 0; 2358 const char* pReplace = nullptr; 2359 sal_Unicode cSVCode = 0; 2360 char aFBuf[4]; 2361 nSysCode = 0; 2362 2363 if ( (nCode >= KEY_0) && (nCode <= KEY_9) ) 2364 cSVCode = '0' + (nCode - KEY_0); 2365 else if ( (nCode >= KEY_A) && (nCode <= KEY_Z) ) 2366 cSVCode = 'A' + (nCode - KEY_A); 2367 else if ( (nCode >= KEY_F1) && (nCode <= KEY_F26) ) 2368 { 2369 nSysCode = VK_F1 + (nCode - KEY_F1); 2370 aFBuf[0] = 'F'; 2371 if (nCode <= KEY_F9) 2372 { 2373 aFBuf[1] = sal::static_int_cast<char>('1' + (nCode - KEY_F1)); 2374 aFBuf[2] = 0; 2375 } 2376 else if (nCode <= KEY_F19) 2377 { 2378 aFBuf[1] = '1'; 2379 aFBuf[2] = sal::static_int_cast<char>('0' + (nCode - KEY_F10)); 2380 aFBuf[3] = 0; 2381 } 2382 else 2383 { 2384 aFBuf[1] = '2'; 2385 aFBuf[2] = sal::static_int_cast<char>('0' + (nCode - KEY_F20)); 2386 aFBuf[3] = 0; 2387 } 2388 pReplace = aFBuf; 2389 } 2390 else 2391 { 2392 switch ( nCode ) 2393 { 2394 case KEY_DOWN: 2395 nSysCode = VK_DOWN; 2396 nSysCode2 = ((sal_uLong(1)) << 24); 2397 pReplace = "Down"; 2398 break; 2399 case KEY_UP: 2400 nSysCode = VK_UP; 2401 nSysCode2 = ((sal_uLong(1)) << 24); 2402 pReplace = "Up"; 2403 break; 2404 case KEY_LEFT: 2405 nSysCode = VK_LEFT; 2406 nSysCode2 = ((sal_uLong(1)) << 24); 2407 pReplace = "Left"; 2408 break; 2409 case KEY_RIGHT: 2410 nSysCode = VK_RIGHT; 2411 nSysCode2 = ((sal_uLong(1)) << 24); 2412 pReplace = "Right"; 2413 break; 2414 case KEY_HOME: 2415 nSysCode = VK_HOME; 2416 nSysCode2 = ((sal_uLong(1)) << 24); 2417 pReplace = "Home"; 2418 break; 2419 case KEY_END: 2420 nSysCode = VK_END; 2421 nSysCode2 = ((sal_uLong(1)) << 24); 2422 pReplace = "End"; 2423 break; 2424 case KEY_PAGEUP: 2425 nSysCode = VK_PRIOR; 2426 nSysCode2 = ((sal_uLong(1)) << 24); 2427 pReplace = "Page Up"; 2428 break; 2429 case KEY_PAGEDOWN: 2430 nSysCode = VK_NEXT; 2431 nSysCode2 = ((sal_uLong(1)) << 24); 2432 pReplace = "Page Down"; 2433 break; 2434 case KEY_RETURN: 2435 nSysCode = VK_RETURN; 2436 pReplace = "Enter"; 2437 break; 2438 case KEY_ESCAPE: 2439 nSysCode = VK_ESCAPE; 2440 pReplace = "Escape"; 2441 break; 2442 case KEY_TAB: 2443 nSysCode = VK_TAB; 2444 pReplace = "Tab"; 2445 break; 2446 case KEY_BACKSPACE: 2447 nSysCode = VK_BACK; 2448 pReplace = "Backspace"; 2449 break; 2450 case KEY_SPACE: 2451 nSysCode = VK_SPACE; 2452 pReplace = "Space"; 2453 break; 2454 case KEY_INSERT: 2455 nSysCode = VK_INSERT; 2456 nSysCode2 = ((sal_uLong(1)) << 24); 2457 pReplace = "Insert"; 2458 break; 2459 case KEY_DELETE: 2460 nSysCode = VK_DELETE; 2461 nSysCode2 = ((sal_uLong(1)) << 24); 2462 pReplace = "Delete"; 2463 break; 2464 2465 case KEY_ADD: 2466 cSVCode = '+'; 2467 break; 2468 case KEY_SUBTRACT: 2469 cSVCode = '-'; 2470 break; 2471 case KEY_MULTIPLY: 2472 cSVCode = '*'; 2473 break; 2474 case KEY_DIVIDE: 2475 cSVCode = '/'; 2476 break; 2477 case KEY_POINT: 2478 cSVCode = '.'; 2479 break; 2480 case KEY_COMMA: 2481 cSVCode = ','; 2482 break; 2483 case KEY_LESS: 2484 cSVCode = '<'; 2485 break; 2486 case KEY_GREATER: 2487 cSVCode = '>'; 2488 break; 2489 case KEY_EQUAL: 2490 cSVCode = '='; 2491 break; 2492 case KEY_SEMICOLON: 2493 cSVCode = ';'; 2494 break; 2495 case KEY_QUOTERIGHT: 2496 cSVCode = '\''; 2497 break; 2498 case KEY_BRACKETLEFT: 2499 cSVCode = '['; 2500 break; 2501 case KEY_BRACKETRIGHT: 2502 cSVCode = ']'; 2503 break; 2504 case KEY_QUOTELEFT: 2505 cSVCode = '`'; 2506 break; 2507 case KEY_RIGHTCURLYBRACKET: 2508 cSVCode = '}'; 2509 break; 2510 } 2511 } 2512 2513 if ( nSysCode ) 2514 { 2515 nSysCode = MapVirtualKeyW( nSysCode, 0 ); 2516 if ( nSysCode ) 2517 nSysCode = (nSysCode << 16) | nSysCode2; 2518 ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, pReplace ); 2519 } 2520 else 2521 { 2522 if ( cSVCode ) 2523 { 2524 if ( nKeyBufLen > 0 ) 2525 aKeyBuf[ nKeyBufLen++ ] = '+'; 2526 if( nKeyBufLen < nMaxKeyLen ) 2527 aKeyBuf[ nKeyBufLen++ ] = cSVCode; 2528 } 2529 } 2530 2531 if( !nKeyBufLen ) 2532 return OUString(); 2533 2534 return OUString( aKeyBuf, sal::static_int_cast< sal_uInt16 >(nKeyBufLen) ); 2535 } 2536 2537 static Color ImplWinColorToSal( COLORREF nColor ) 2538 { 2539 return Color( GetRValue( nColor ), GetGValue( nColor ), GetBValue( nColor ) ); 2540 } 2541 2542 static void ImplSalUpdateStyleFontW( HDC hDC, const LOGFONTW& rLogFont, vcl::Font& rFont ) 2543 { 2544 ImplSalLogFontToFontW( hDC, rLogFont, rFont ); 2545 2546 // On Windows 9x, Windows NT we get sometimes very small sizes 2547 // (for example for the small Caption height). 2548 // So if it is MS Sans Serif, a none scalable font we use 2549 // 8 Point as the minimum control height, in all other cases 2550 // 6 Point is the smallest one 2551 if ( rFont.GetFontHeight() < 8 ) 2552 { 2553 if ( rtl_ustr_compareIgnoreAsciiCase( o3tl::toU(rLogFont.lfFaceName), o3tl::toU(L"MS Sans Serif") ) == 0 ) 2554 rFont.SetFontHeight( 8 ); 2555 else if ( rFont.GetFontHeight() < 6 ) 2556 rFont.SetFontHeight( 6 ); 2557 } 2558 } 2559 2560 static tools::Long ImplW2I( const wchar_t* pStr ) 2561 { 2562 tools::Long n = 0; 2563 int nSign = 1; 2564 2565 if ( *pStr == '-' ) 2566 { 2567 nSign = -1; 2568 pStr++; 2569 } 2570 2571 while( (*pStr >= 48) && (*pStr <= 57) ) 2572 { 2573 n *= 10; 2574 n += ((*pStr) - 48); 2575 pStr++; 2576 } 2577 2578 n *= nSign; 2579 2580 return n; 2581 } 2582 2583 void WinSalFrame::UpdateSettings( AllSettings& rSettings ) 2584 { 2585 MouseSettings aMouseSettings = rSettings.GetMouseSettings(); 2586 aMouseSettings.SetDoubleClickTime( GetDoubleClickTime() ); 2587 aMouseSettings.SetDoubleClickWidth( GetSystemMetrics( SM_CXDOUBLECLK ) ); 2588 aMouseSettings.SetDoubleClickHeight( GetSystemMetrics( SM_CYDOUBLECLK ) ); 2589 tools::Long nDragWidth = GetSystemMetrics( SM_CXDRAG ); 2590 tools::Long nDragHeight = GetSystemMetrics( SM_CYDRAG ); 2591 if ( nDragWidth ) 2592 aMouseSettings.SetStartDragWidth( nDragWidth ); 2593 if ( nDragHeight ) 2594 aMouseSettings.SetStartDragHeight( nDragHeight ); 2595 HKEY hRegKey; 2596 if ( RegOpenKeyW( HKEY_CURRENT_USER, 2597 L"Control Panel\\Desktop", 2598 &hRegKey ) == ERROR_SUCCESS ) 2599 { 2600 wchar_t aValueBuf[10]; 2601 DWORD nValueSize = sizeof( aValueBuf ); 2602 DWORD nType; 2603 if ( RegQueryValueExW( hRegKey, L"MenuShowDelay", nullptr, 2604 &nType, reinterpret_cast<LPBYTE>(aValueBuf), &nValueSize ) == ERROR_SUCCESS ) 2605 { 2606 if ( nType == REG_SZ ) 2607 aMouseSettings.SetMenuDelay( static_cast<sal_uLong>(ImplW2I( aValueBuf )) ); 2608 } 2609 2610 RegCloseKey( hRegKey ); 2611 } 2612 2613 StyleSettings aStyleSettings = rSettings.GetStyleSettings(); 2614 2615 // High contrast 2616 HIGHCONTRAST hc; 2617 hc.cbSize = sizeof( HIGHCONTRAST ); 2618 if( SystemParametersInfoW( SPI_GETHIGHCONTRAST, hc.cbSize, &hc, 0 ) 2619 && (hc.dwFlags & HCF_HIGHCONTRASTON) ) 2620 aStyleSettings.SetHighContrastMode( true ); 2621 else 2622 aStyleSettings.SetHighContrastMode( false ); 2623 2624 aStyleSettings.SetScrollBarSize( GetSystemMetrics( SM_CXVSCROLL ) ); 2625 aStyleSettings.SetSpinSize( GetSystemMetrics( SM_CXVSCROLL ) ); 2626 UINT blinkTime = GetCaretBlinkTime(); 2627 aStyleSettings.SetCursorBlinkTime( 2628 blinkTime == 0 || blinkTime == INFINITE // 0 indicates error 2629 ? STYLE_CURSOR_NOBLINKTIME : blinkTime ); 2630 aStyleSettings.SetFloatTitleHeight( GetSystemMetrics( SM_CYSMCAPTION ) ); 2631 aStyleSettings.SetTitleHeight( GetSystemMetrics( SM_CYCAPTION ) ); 2632 aStyleSettings.SetActiveBorderColor( ImplWinColorToSal( GetSysColor( COLOR_ACTIVEBORDER ) ) ); 2633 aStyleSettings.SetDeactiveBorderColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVEBORDER ) ) ); 2634 aStyleSettings.SetDeactiveColor( ImplWinColorToSal( GetSysColor( COLOR_GRADIENTINACTIVECAPTION ) ) ); 2635 2636 Color aControlTextColor; 2637 Color aMenuBarTextColor; 2638 Color aMenuBarRolloverTextColor; 2639 Color aHighlightTextColor = ImplWinColorToSal(GetSysColor(COLOR_HIGHLIGHTTEXT)); 2640 2641 const bool bUseDarkMode(UseDarkMode()); 2642 2643 OUString sThemeName(!bUseDarkMode ? u"colibre" : u"colibre_dark"); 2644 aStyleSettings.SetPreferredIconTheme(sThemeName, bUseDarkMode); 2645 2646 if (bUseDarkMode) 2647 { 2648 SetWindowTheme(mhWnd, L"Explorer", nullptr); 2649 2650 HTHEME hTheme = OpenThemeData(nullptr, L"ItemsView"); 2651 COLORREF color; 2652 GetThemeColor(hTheme, 0, 0, TMT_FILLCOLOR, &color); 2653 aStyleSettings.SetFaceColor( ImplWinColorToSal( color ) ); 2654 aStyleSettings.SetWindowColor( ImplWinColorToSal( color ) ); 2655 GetThemeColor(hTheme, 0, 0, TMT_TEXTCOLOR, &color); 2656 aStyleSettings.SetWindowTextColor( ImplWinColorToSal( color ) ); 2657 aStyleSettings.SetToolTextColor( ImplWinColorToSal( color ) ); 2658 GetThemeColor(hTheme, 0, 0, TMT_SHADOWCOLOR, &color); 2659 aStyleSettings.SetShadowColor( ImplWinColorToSal( color ) ); 2660 GetThemeColor(hTheme, 0, 0, TMT_DKSHADOW3D, &color); 2661 aStyleSettings.SetDarkShadowColor( ImplWinColorToSal( color ) ); 2662 CloseThemeData(hTheme); 2663 2664 hTheme = OpenThemeData(mhWnd, L"Button"); 2665 GetThemeColor(hTheme, BP_PUSHBUTTON, PBS_NORMAL, TMT_TEXTCOLOR, &color); 2666 aControlTextColor = ImplWinColorToSal(color); 2667 GetThemeColor(hTheme, BP_CHECKBOX, PBS_NORMAL, TMT_TEXTCOLOR, &color); 2668 aStyleSettings.SetRadioCheckTextColor( ImplWinColorToSal( color ) ); 2669 CloseThemeData(hTheme); 2670 2671 SetWindowTheme(mhWnd, nullptr, nullptr); 2672 2673 hTheme = OpenThemeData(mhWnd, L"Menu"); 2674 GetThemeColor(hTheme, MENU_POPUPITEM, MBI_NORMAL, TMT_TEXTCOLOR, &color); 2675 aStyleSettings.SetMenuTextColor( ImplWinColorToSal( color ) ); 2676 aMenuBarTextColor = ImplWinColorToSal( color ); 2677 aMenuBarRolloverTextColor = ImplWinColorToSal( color ); 2678 CloseThemeData(hTheme); 2679 2680 aStyleSettings.SetActiveTabColor( aStyleSettings.GetWindowColor() ); 2681 hTheme = OpenThemeData(mhWnd, L"Toolbar"); 2682 GetThemeColor(hTheme, 0, 0, TMT_FILLCOLOR, &color); 2683 aStyleSettings.SetInactiveTabColor( ImplWinColorToSal( color ) ); 2684 CloseThemeData(hTheme); 2685 2686 // tdf#148448 pick a warning color more likely to be readable as a 2687 // background in a dark theme 2688 aStyleSettings.SetWarningColor(Color(0xf5, 0x79, 0x00)); 2689 } 2690 else 2691 { 2692 aStyleSettings.SetFaceColor( ImplWinColorToSal( GetSysColor( COLOR_3DFACE ) ) ); 2693 aStyleSettings.SetWindowColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOW ) ) ); 2694 aStyleSettings.SetWindowTextColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOWTEXT ) ) ); 2695 aStyleSettings.SetToolTextColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOWTEXT ) ) ); 2696 aStyleSettings.SetShadowColor( ImplWinColorToSal( GetSysColor( COLOR_3DSHADOW ) ) ); 2697 aStyleSettings.SetDarkShadowColor( ImplWinColorToSal( GetSysColor( COLOR_3DDKSHADOW ) ) ); 2698 aControlTextColor = ImplWinColorToSal(GetSysColor(COLOR_BTNTEXT)); 2699 aStyleSettings.SetRadioCheckTextColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOWTEXT ) ) ); 2700 aStyleSettings.SetMenuTextColor( ImplWinColorToSal( GetSysColor( COLOR_MENUTEXT ) ) ); 2701 aMenuBarTextColor = ImplWinColorToSal( GetSysColor( COLOR_MENUTEXT ) ); 2702 aMenuBarRolloverTextColor = aHighlightTextColor; 2703 aStyleSettings.SetActiveTabColor( aStyleSettings.GetWindowColor() ); 2704 aStyleSettings.SetInactiveTabColor( aStyleSettings.GetFaceColor() ); 2705 } 2706 2707 if ( std::optional<Color> aColor = aStyleSettings.GetPersonaMenuBarTextColor() ) 2708 { 2709 aMenuBarTextColor = *aColor; 2710 aMenuBarRolloverTextColor = *aColor; 2711 } 2712 2713 aStyleSettings.SetMenuBarTextColor( aMenuBarTextColor ); 2714 aStyleSettings.SetMenuBarRolloverTextColor( aMenuBarRolloverTextColor ); 2715 2716 aStyleSettings.SetLightColor( ImplWinColorToSal( GetSysColor( COLOR_3DHILIGHT ) ) ); 2717 aStyleSettings.SetLightBorderColor( ImplWinColorToSal( GetSysColor( COLOR_3DLIGHT ) ) ); 2718 aStyleSettings.SetHelpColor( ImplWinColorToSal( GetSysColor( COLOR_INFOBK ) ) ); 2719 aStyleSettings.SetHelpTextColor( ImplWinColorToSal( GetSysColor( COLOR_INFOTEXT ) ) ); 2720 2721 aStyleSettings.SetWorkspaceColor(aStyleSettings.GetFaceColor()); 2722 aStyleSettings.SetDialogColor(aStyleSettings.GetFaceColor()); 2723 aStyleSettings.SetDialogTextColor(aControlTextColor); 2724 2725 Color aHighlightButtonTextColor = aStyleSettings.GetHighContrastMode() ? 2726 aHighlightTextColor : aControlTextColor; 2727 2728 if (aStyleSettings.GetHighContrastMode()) 2729 { 2730 Color aLinkColor(ImplWinColorToSal(GetSysColor(COLOR_HOTLIGHT))); 2731 aStyleSettings.SetLinkColor(aLinkColor); 2732 aStyleSettings.SetVisitedLinkColor(aLinkColor); 2733 } 2734 2735 aStyleSettings.SetDefaultButtonTextColor(aHighlightButtonTextColor); 2736 aStyleSettings.SetButtonTextColor(aControlTextColor); 2737 aStyleSettings.SetDefaultActionButtonTextColor(aHighlightButtonTextColor); 2738 aStyleSettings.SetActionButtonTextColor(aControlTextColor); 2739 aStyleSettings.SetFlatButtonTextColor(aControlTextColor); 2740 aStyleSettings.SetDefaultButtonRolloverTextColor(aHighlightButtonTextColor); 2741 aStyleSettings.SetButtonRolloverTextColor(aHighlightButtonTextColor); 2742 aStyleSettings.SetDefaultActionButtonRolloverTextColor(aHighlightButtonTextColor); 2743 aStyleSettings.SetActionButtonRolloverTextColor(aHighlightButtonTextColor); 2744 aStyleSettings.SetFlatButtonRolloverTextColor(aHighlightButtonTextColor); 2745 aStyleSettings.SetDefaultButtonPressedRolloverTextColor(aControlTextColor); 2746 aStyleSettings.SetButtonPressedRolloverTextColor(aControlTextColor); 2747 aStyleSettings.SetDefaultActionButtonPressedRolloverTextColor(aControlTextColor); 2748 aStyleSettings.SetActionButtonPressedRolloverTextColor(aControlTextColor); 2749 aStyleSettings.SetFlatButtonPressedRolloverTextColor(aControlTextColor); 2750 2751 aStyleSettings.SetTabTextColor(aControlTextColor); 2752 aStyleSettings.SetTabRolloverTextColor(aControlTextColor); 2753 aStyleSettings.SetTabHighlightTextColor(aControlTextColor); 2754 2755 aStyleSettings.SetGroupTextColor( aStyleSettings.GetRadioCheckTextColor() ); 2756 aStyleSettings.SetLabelTextColor( aStyleSettings.GetRadioCheckTextColor() ); 2757 aStyleSettings.SetFieldColor( aStyleSettings.GetWindowColor() ); 2758 aStyleSettings.SetListBoxWindowBackgroundColor( aStyleSettings.GetWindowColor() ); 2759 aStyleSettings.SetFieldTextColor( aStyleSettings.GetWindowTextColor() ); 2760 aStyleSettings.SetFieldRolloverTextColor( aStyleSettings.GetFieldTextColor() ); 2761 aStyleSettings.SetListBoxWindowTextColor( aStyleSettings.GetFieldTextColor() ); 2762 aStyleSettings.SetHighlightColor( ImplWinColorToSal( GetSysColor( COLOR_HIGHLIGHT ) ) ); 2763 aStyleSettings.SetHighlightTextColor(aHighlightTextColor); 2764 aStyleSettings.SetListBoxWindowHighlightColor( aStyleSettings.GetHighlightColor() ); 2765 aStyleSettings.SetListBoxWindowHighlightTextColor( aStyleSettings.GetHighlightTextColor() ); 2766 aStyleSettings.SetMenuHighlightColor( aStyleSettings.GetHighlightColor() ); 2767 aStyleSettings.SetMenuHighlightTextColor( aStyleSettings.GetHighlightTextColor() ); 2768 2769 ImplSVData* pSVData = ImplGetSVData(); 2770 pSVData->maNWFData.mnMenuFormatBorderX = 0; 2771 pSVData->maNWFData.mnMenuFormatBorderY = 0; 2772 pSVData->maNWFData.maMenuBarHighlightTextColor = COL_TRANSPARENT; 2773 GetSalData()->mbThemeMenuSupport = false; 2774 aStyleSettings.SetMenuColor( ImplWinColorToSal( GetSysColor( COLOR_MENU ) ) ); 2775 aStyleSettings.SetMenuBarColor( aStyleSettings.GetMenuColor() ); 2776 aStyleSettings.SetMenuBarRolloverColor( aStyleSettings.GetHighlightColor() ); 2777 aStyleSettings.SetMenuBorderColor( aStyleSettings.GetLightBorderColor() ); // overridden below for flat menus 2778 aStyleSettings.SetUseFlatBorders( false ); 2779 aStyleSettings.SetUseFlatMenus( false ); 2780 aStyleSettings.SetMenuBarHighlightTextColor(aStyleSettings.GetMenuHighlightTextColor()); 2781 aStyleSettings.SetActiveColor( ImplWinColorToSal( GetSysColor( COLOR_ACTIVECAPTION ) ) ); 2782 aStyleSettings.SetActiveTextColor( ImplWinColorToSal( GetSysColor( COLOR_CAPTIONTEXT ) ) ); 2783 aStyleSettings.SetDeactiveColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVECAPTION ) ) ); 2784 aStyleSettings.SetDeactiveTextColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVECAPTIONTEXT ) ) ); 2785 BOOL bFlatMenus = FALSE; 2786 SystemParametersInfoW( SPI_GETFLATMENU, 0, &bFlatMenus, 0); 2787 if( bFlatMenus ) 2788 { 2789 aStyleSettings.SetUseFlatMenus( true ); 2790 aStyleSettings.SetMenuBarColor( ImplWinColorToSal( GetSysColor( COLOR_MENUBAR ) ) ); 2791 aStyleSettings.SetMenuHighlightColor( ImplWinColorToSal( GetSysColor( COLOR_MENUHILIGHT ) ) ); 2792 aStyleSettings.SetMenuBarRolloverColor( ImplWinColorToSal( GetSysColor( COLOR_MENUHILIGHT ) ) ); 2793 aStyleSettings.SetMenuBorderColor( ImplWinColorToSal( GetSysColor( COLOR_3DSHADOW ) ) ); 2794 2795 // flat borders for our controls etc. as well in this mode (ie, no 3d borders) 2796 // this is not active in the classic style appearance 2797 aStyleSettings.SetUseFlatBorders( true ); 2798 } 2799 aStyleSettings.SetCheckedColorSpecialCase( ); 2800 2801 // caret width 2802 DWORD nCaretWidth = 2; 2803 if( SystemParametersInfoW( SPI_GETCARETWIDTH, 0, &nCaretWidth, 0 ) ) 2804 aStyleSettings.SetCursorSize( nCaretWidth ); 2805 2806 // Query Fonts 2807 vcl::Font aMenuFont = aStyleSettings.GetMenuFont(); 2808 vcl::Font aTitleFont = aStyleSettings.GetTitleFont(); 2809 vcl::Font aFloatTitleFont = aStyleSettings.GetFloatTitleFont(); 2810 vcl::Font aHelpFont = aStyleSettings.GetHelpFont(); 2811 vcl::Font aAppFont = aStyleSettings.GetAppFont(); 2812 vcl::Font aIconFont = aStyleSettings.GetIconFont(); 2813 HDC hDC = GetDC( nullptr ); 2814 NONCLIENTMETRICSW aNonClientMetrics; 2815 aNonClientMetrics.cbSize = sizeof( aNonClientMetrics ); 2816 if ( SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, sizeof( aNonClientMetrics ), &aNonClientMetrics, 0 ) ) 2817 { 2818 ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfMenuFont, aMenuFont ); 2819 ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfCaptionFont, aTitleFont ); 2820 ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfSmCaptionFont, aFloatTitleFont ); 2821 ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfStatusFont, aHelpFont ); 2822 ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfMessageFont, aAppFont ); 2823 2824 LOGFONTW aLogFont; 2825 if ( SystemParametersInfoW( SPI_GETICONTITLELOGFONT, 0, &aLogFont, 0 ) ) 2826 ImplSalUpdateStyleFontW( hDC, aLogFont, aIconFont ); 2827 } 2828 2829 ReleaseDC( nullptr, hDC ); 2830 2831 aStyleSettings.SetToolbarIconSize(ToolbarIconSize::Large); 2832 2833 aStyleSettings.BatchSetFonts( aAppFont, aAppFont ); 2834 2835 aStyleSettings.SetMenuFont( aMenuFont ); 2836 aStyleSettings.SetTitleFont( aTitleFont ); 2837 aStyleSettings.SetFloatTitleFont( aFloatTitleFont ); 2838 aStyleSettings.SetHelpFont( aHelpFont ); 2839 aStyleSettings.SetIconFont( aIconFont ); 2840 2841 if ( aAppFont.GetWeight() > WEIGHT_NORMAL ) 2842 aAppFont.SetWeight( WEIGHT_NORMAL ); 2843 aStyleSettings.SetToolFont( aAppFont ); 2844 aStyleSettings.SetTabFont( aAppFont ); 2845 2846 BOOL bDragFull; 2847 if ( SystemParametersInfoW( SPI_GETDRAGFULLWINDOWS, 0, &bDragFull, 0 ) ) 2848 { 2849 DragFullOptions nDragFullOptions = aStyleSettings.GetDragFullOptions(); 2850 if ( bDragFull ) 2851 nDragFullOptions |= DragFullOptions::WindowMove | DragFullOptions::WindowSize | DragFullOptions::Docking | DragFullOptions::Split; 2852 else 2853 nDragFullOptions &= ~DragFullOptions(DragFullOptions::WindowMove | DragFullOptions::WindowSize | DragFullOptions::Docking | DragFullOptions::Split); 2854 aStyleSettings.SetDragFullOptions( nDragFullOptions ); 2855 } 2856 2857 if ( RegOpenKeyW( HKEY_CURRENT_USER, 2858 L"Control Panel\\International\\Calendars\\TwoDigitYearMax", 2859 &hRegKey ) == ERROR_SUCCESS ) 2860 { 2861 wchar_t aValueBuf[10]; 2862 DWORD nValue; 2863 DWORD nValueSize = sizeof( aValueBuf ); 2864 DWORD nType; 2865 if ( RegQueryValueExW( hRegKey, L"1", nullptr, 2866 &nType, reinterpret_cast<LPBYTE>(aValueBuf), &nValueSize ) == ERROR_SUCCESS ) 2867 { 2868 if ( nType == REG_SZ ) 2869 { 2870 nValue = static_cast<sal_uLong>(ImplW2I( aValueBuf )); 2871 if ( (nValue > 1000) && (nValue < 10000) ) 2872 { 2873 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create()); 2874 officecfg::Office::Common::DateFormat::TwoDigitYear::set(static_cast<sal_Int32>(nValue-99), batch); 2875 batch->commit(); 2876 } 2877 } 2878 } 2879 2880 RegCloseKey( hRegKey ); 2881 } 2882 2883 rSettings.SetMouseSettings( aMouseSettings ); 2884 rSettings.SetStyleSettings( aStyleSettings ); 2885 2886 // now apply the values from theming, if available 2887 WinSalGraphics::updateSettingsNative( rSettings ); 2888 } 2889 2890 const SystemEnvData* WinSalFrame::GetSystemData() const 2891 { 2892 return &maSysData; 2893 } 2894 2895 void WinSalFrame::Beep() 2896 { 2897 // a simple beep 2898 MessageBeep( 0 ); 2899 } 2900 2901 SalFrame::SalPointerState WinSalFrame::GetPointerState() 2902 { 2903 SalPointerState aState; 2904 aState.mnState = 0; 2905 2906 if ( GetKeyState( VK_LBUTTON ) & 0x8000 ) 2907 aState.mnState |= MOUSE_LEFT; 2908 if ( GetKeyState( VK_MBUTTON ) & 0x8000 ) 2909 aState.mnState |= MOUSE_MIDDLE; 2910 if ( GetKeyState( VK_RBUTTON ) & 0x8000 ) 2911 aState.mnState |= MOUSE_RIGHT; 2912 if ( GetKeyState( VK_SHIFT ) & 0x8000 ) 2913 aState.mnState |= KEY_SHIFT; 2914 if ( GetKeyState( VK_CONTROL ) & 0x8000 ) 2915 aState.mnState |= KEY_MOD1; 2916 if ( GetKeyState( VK_MENU ) & 0x8000 ) 2917 aState.mnState |= KEY_MOD2; 2918 2919 POINT pt; 2920 GetCursorPos( &pt ); 2921 2922 aState.maPos = Point(pt.x - maGeometry.x(), pt.y - maGeometry.y()); 2923 return aState; 2924 } 2925 2926 KeyIndicatorState WinSalFrame::GetIndicatorState() 2927 { 2928 KeyIndicatorState aState = KeyIndicatorState::NONE; 2929 if (::GetKeyState(VK_CAPITAL)) 2930 aState |= KeyIndicatorState::CAPSLOCK; 2931 2932 if (::GetKeyState(VK_NUMLOCK)) 2933 aState |= KeyIndicatorState::NUMLOCK; 2934 2935 if (::GetKeyState(VK_SCROLL)) 2936 aState |= KeyIndicatorState::SCROLLLOCK; 2937 2938 return aState; 2939 } 2940 2941 void WinSalFrame::SimulateKeyPress( sal_uInt16 nKeyCode ) 2942 { 2943 BYTE nVKey = 0; 2944 switch (nKeyCode) 2945 { 2946 case KEY_CAPSLOCK: 2947 nVKey = VK_CAPITAL; 2948 break; 2949 } 2950 2951 if (nVKey > 0 && nVKey < 255) 2952 { 2953 ::keybd_event(nVKey, 0x45, KEYEVENTF_EXTENDEDKEY, 0); 2954 ::keybd_event(nVKey, 0x45, KEYEVENTF_EXTENDEDKEY|KEYEVENTF_KEYUP, 0); 2955 } 2956 } 2957 2958 void WinSalFrame::ResetClipRegion() 2959 { 2960 SetWindowRgn( mhWnd, nullptr, TRUE ); 2961 } 2962 2963 void WinSalFrame::BeginSetClipRegion( sal_uInt32 nRects ) 2964 { 2965 if( mpClipRgnData ) 2966 delete [] reinterpret_cast<BYTE*>(mpClipRgnData); 2967 sal_uLong nRectBufSize = sizeof(RECT)*nRects; 2968 mpClipRgnData = reinterpret_cast<RGNDATA*>(new BYTE[sizeof(RGNDATA)-1+nRectBufSize]); 2969 mpClipRgnData->rdh.dwSize = sizeof( RGNDATAHEADER ); 2970 mpClipRgnData->rdh.iType = RDH_RECTANGLES; 2971 mpClipRgnData->rdh.nCount = nRects; 2972 mpClipRgnData->rdh.nRgnSize = nRectBufSize; 2973 SetRectEmpty( &(mpClipRgnData->rdh.rcBound) ); 2974 mpNextClipRect = reinterpret_cast<RECT*>(&(mpClipRgnData->Buffer)); 2975 mbFirstClipRect = true; 2976 } 2977 2978 void WinSalFrame::UnionClipRegion( tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight ) 2979 { 2980 if( ! mpClipRgnData ) 2981 return; 2982 2983 RECT* pRect = mpNextClipRect; 2984 RECT* pBoundRect = &(mpClipRgnData->rdh.rcBound); 2985 tools::Long nRight = nX + nWidth; 2986 tools::Long nBottom = nY + nHeight; 2987 2988 if ( mbFirstClipRect ) 2989 { 2990 pBoundRect->left = nX; 2991 pBoundRect->top = nY; 2992 pBoundRect->right = nRight; 2993 pBoundRect->bottom = nBottom; 2994 mbFirstClipRect = false; 2995 } 2996 else 2997 { 2998 if ( nX < pBoundRect->left ) 2999 pBoundRect->left = static_cast<int>(nX); 3000 3001 if ( nY < pBoundRect->top ) 3002 pBoundRect->top = static_cast<int>(nY); 3003 3004 if ( nRight > pBoundRect->right ) 3005 pBoundRect->right = static_cast<int>(nRight); 3006 3007 if ( nBottom > pBoundRect->bottom ) 3008 pBoundRect->bottom = static_cast<int>(nBottom); 3009 } 3010 3011 pRect->left = static_cast<int>(nX); 3012 pRect->top = static_cast<int>(nY); 3013 pRect->right = static_cast<int>(nRight); 3014 pRect->bottom = static_cast<int>(nBottom); 3015 if( (mpNextClipRect - reinterpret_cast<RECT*>(&mpClipRgnData->Buffer)) < static_cast<int>(mpClipRgnData->rdh.nCount) ) 3016 mpNextClipRect++; 3017 } 3018 3019 void WinSalFrame::EndSetClipRegion() 3020 { 3021 if( ! mpClipRgnData ) 3022 return; 3023 3024 HRGN hRegion; 3025 3026 // create region from accumulated rectangles 3027 if ( mpClipRgnData->rdh.nCount == 1 ) 3028 { 3029 RECT* pRect = &(mpClipRgnData->rdh.rcBound); 3030 hRegion = CreateRectRgn( pRect->left, pRect->top, 3031 pRect->right, pRect->bottom ); 3032 } 3033 else 3034 { 3035 sal_uLong nSize = mpClipRgnData->rdh.nRgnSize+sizeof(RGNDATAHEADER); 3036 hRegion = ExtCreateRegion( nullptr, nSize, mpClipRgnData ); 3037 } 3038 delete [] reinterpret_cast<BYTE*>(mpClipRgnData); 3039 mpClipRgnData = nullptr; 3040 3041 SAL_WARN_IF( !hRegion, "vcl", "WinSalFrame::EndSetClipRegion() - Can't create ClipRegion" ); 3042 if( hRegion ) 3043 { 3044 RECT aWindowRect; 3045 GetWindowRect( mhWnd, &aWindowRect ); 3046 POINT aPt; 3047 aPt.x=0; 3048 aPt.y=0; 3049 ClientToScreen( mhWnd, &aPt ); 3050 OffsetRgn( hRegion, aPt.x - aWindowRect.left, aPt.y - aWindowRect.top ); 3051 3052 if( SetWindowRgn( mhWnd, hRegion, TRUE ) == 0 ) 3053 DeleteObject( hRegion ); 3054 } 3055 } 3056 3057 static bool ImplHandleMouseMsg( HWND hWnd, UINT nMsg, 3058 WPARAM wParam, LPARAM lParam ) 3059 { 3060 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 3061 if ( !pFrame ) 3062 return false; 3063 3064 if( nMsg == WM_LBUTTONDOWN || nMsg == WM_MBUTTONDOWN || nMsg == WM_RBUTTONDOWN ) 3065 { 3066 // #103168# post again if async focus has not arrived yet 3067 // hopefully we will not receive the corresponding button up before this 3068 // button down arrives again 3069 vcl::Window *pWin = pFrame->GetWindow(); 3070 if( pWin && pWin->ImplGetWindowImpl()->mpFrameData->mnFocusId ) 3071 { 3072 bool const ret = PostMessageW( hWnd, nMsg, wParam, lParam ); 3073 SAL_WARN_IF(!ret, "vcl", "ERROR: PostMessage() failed!"); 3074 return true; 3075 } 3076 } 3077 SalMouseEvent aMouseEvt; 3078 bool nRet; 3079 SalEvent nEvent = SalEvent::NONE; 3080 bool bCall = true; 3081 3082 aMouseEvt.mnX = static_cast<short>(LOWORD( lParam )); 3083 aMouseEvt.mnY = static_cast<short>(HIWORD( lParam )); 3084 aMouseEvt.mnCode = 0; 3085 aMouseEvt.mnTime = GetMessageTime(); 3086 3087 // Use GetKeyState(), as some Logitech mouse drivers do not check 3088 // KeyState when simulating double-click with center mouse button 3089 3090 if ( GetKeyState( VK_LBUTTON ) & 0x8000 ) 3091 aMouseEvt.mnCode |= MOUSE_LEFT; 3092 if ( GetKeyState( VK_MBUTTON ) & 0x8000 ) 3093 aMouseEvt.mnCode |= MOUSE_MIDDLE; 3094 if ( GetKeyState( VK_RBUTTON ) & 0x8000 ) 3095 aMouseEvt.mnCode |= MOUSE_RIGHT; 3096 if ( GetKeyState( VK_SHIFT ) & 0x8000 ) 3097 aMouseEvt.mnCode |= KEY_SHIFT; 3098 if ( GetKeyState( VK_CONTROL ) & 0x8000 ) 3099 aMouseEvt.mnCode |= KEY_MOD1; 3100 if ( GetKeyState( VK_MENU ) & 0x8000 ) 3101 aMouseEvt.mnCode |= KEY_MOD2; 3102 3103 switch ( nMsg ) 3104 { 3105 case WM_MOUSEMOVE: 3106 { 3107 // As the mouse events are not collected correctly when 3108 // pressing modifier keys (as interrupted by KeyEvents) 3109 // we do this here ourselves 3110 if ( aMouseEvt.mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2) ) 3111 { 3112 MSG aTempMsg; 3113 if ( PeekMessageW( &aTempMsg, hWnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE | PM_NOYIELD ) ) 3114 { 3115 if ( (aTempMsg.message == WM_MOUSEMOVE) && 3116 (aTempMsg.wParam == wParam) ) 3117 return true; 3118 } 3119 } 3120 3121 SalData* pSalData = GetSalData(); 3122 // Test for MouseLeave 3123 if ( pSalData->mhWantLeaveMsg && (pSalData->mhWantLeaveMsg != hWnd) ) 3124 SendMessageW( pSalData->mhWantLeaveMsg, SAL_MSG_MOUSELEAVE, 0, GetMessagePos() ); 3125 3126 pSalData->mhWantLeaveMsg = hWnd; 3127 // Start MouseLeave-Timer 3128 if ( !pSalData->mpMouseLeaveTimer ) 3129 { 3130 pSalData->mpMouseLeaveTimer = new AutoTimer( "ImplHandleMouseMsg SalData::mpMouseLeaveTimer" ); 3131 pSalData->mpMouseLeaveTimer->SetTimeout( SAL_MOUSELEAVE_TIMEOUT ); 3132 pSalData->mpMouseLeaveTimer->Start(); 3133 // We don't need to set a timeout handler, because we test 3134 // for mouseleave in the timeout callback 3135 } 3136 aMouseEvt.mnButton = 0; 3137 nEvent = SalEvent::MouseMove; 3138 } 3139 break; 3140 3141 case WM_NCMOUSEMOVE: 3142 case SAL_MSG_MOUSELEAVE: 3143 { 3144 SalData* pSalData = GetSalData(); 3145 if ( pSalData->mhWantLeaveMsg == hWnd ) 3146 { 3147 // Mouse-Coordinates are relative to the screen 3148 POINT aPt; 3149 aPt.x = static_cast<short>(LOWORD(lParam)); 3150 aPt.y = static_cast<short>(HIWORD(lParam)); 3151 ScreenToClient(hWnd, &aPt); 3152 if (const auto& pHelpWin = ImplGetSVHelpData().mpHelpWin) 3153 { 3154 const tools::Rectangle& rHelpRect = pHelpWin->GetHelpArea(); 3155 if (rHelpRect.Contains(Point(aPt.x, aPt.y))) 3156 { 3157 // We have entered a tooltip (help window). Don't call the handler here; it 3158 // would launch the sequence "Mouse leaves the Control->Control redraws-> 3159 // Help window gets destroyed->Mouse enters the Control->Control redraws", 3160 // which takes CPU and may flicker. Just destroy the help window and pretend 3161 // we are still over the original window. 3162 ImplDestroyHelpWindow(true); 3163 bCall = false; 3164 break; 3165 } 3166 } 3167 pSalData->mhWantLeaveMsg = nullptr; 3168 if ( pSalData->mpMouseLeaveTimer ) 3169 { 3170 delete pSalData->mpMouseLeaveTimer; 3171 pSalData->mpMouseLeaveTimer = nullptr; 3172 } 3173 aMouseEvt.mnX = aPt.x; 3174 aMouseEvt.mnY = aPt.y; 3175 aMouseEvt.mnButton = 0; 3176 nEvent = SalEvent::MouseLeave; 3177 } 3178 else 3179 bCall = false; 3180 } 3181 break; 3182 3183 case WM_LBUTTONDOWN: 3184 aMouseEvt.mnButton = MOUSE_LEFT; 3185 nEvent = SalEvent::MouseButtonDown; 3186 break; 3187 3188 case WM_MBUTTONDOWN: 3189 aMouseEvt.mnButton = MOUSE_MIDDLE; 3190 nEvent = SalEvent::MouseButtonDown; 3191 break; 3192 3193 case WM_RBUTTONDOWN: 3194 aMouseEvt.mnButton = MOUSE_RIGHT; 3195 nEvent = SalEvent::MouseButtonDown; 3196 break; 3197 3198 case WM_LBUTTONUP: 3199 aMouseEvt.mnButton = MOUSE_LEFT; 3200 nEvent = SalEvent::MouseButtonUp; 3201 break; 3202 3203 case WM_MBUTTONUP: 3204 aMouseEvt.mnButton = MOUSE_MIDDLE; 3205 nEvent = SalEvent::MouseButtonUp; 3206 break; 3207 3208 case WM_RBUTTONUP: 3209 aMouseEvt.mnButton = MOUSE_RIGHT; 3210 nEvent = SalEvent::MouseButtonUp; 3211 break; 3212 } 3213 3214 // check if this window was destroyed - this might happen if we are the help window 3215 // and sent a mouse leave message to the application which killed the help window, ie ourselves 3216 if( !IsWindow( hWnd ) ) 3217 return false; 3218 3219 if ( bCall ) 3220 { 3221 if ( nEvent == SalEvent::MouseButtonDown ) 3222 UpdateWindow( hWnd ); 3223 3224 if( AllSettings::GetLayoutRTL() ) 3225 aMouseEvt.mnX = pFrame->maGeometry.width() - 1 - aMouseEvt.mnX; 3226 3227 nRet = pFrame->CallCallback( nEvent, &aMouseEvt ); 3228 if ( nMsg == WM_MOUSEMOVE ) 3229 SetCursor( pFrame->mhCursor ); 3230 } 3231 else 3232 nRet = false; 3233 3234 return nRet; 3235 } 3236 3237 static bool ImplHandleMouseActivateMsg( HWND hWnd ) 3238 { 3239 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 3240 if ( !pFrame ) 3241 return false; 3242 3243 if ( pFrame->mbFloatWin ) 3244 return true; 3245 3246 return pFrame->CallCallback( SalEvent::MouseActivate, nullptr ); 3247 } 3248 3249 static bool ImplHandleWheelMsg( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ) 3250 { 3251 DBG_ASSERT( nMsg == WM_MOUSEWHEEL || 3252 nMsg == WM_MOUSEHWHEEL, 3253 "ImplHandleWheelMsg() called with no wheel mouse event" ); 3254 3255 ImplSalYieldMutexAcquireWithWait(); 3256 3257 bool nRet = false; 3258 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 3259 if ( pFrame ) 3260 { 3261 WORD nWinModCode = LOWORD( wParam ); 3262 POINT aWinPt; 3263 aWinPt.x = static_cast<short>(LOWORD( lParam )); 3264 aWinPt.y = static_cast<short>(HIWORD( lParam )); 3265 ScreenToClient( hWnd, &aWinPt ); 3266 3267 SalWheelMouseEvent aWheelEvt; 3268 aWheelEvt.mnTime = GetMessageTime(); 3269 aWheelEvt.mnX = aWinPt.x; 3270 aWheelEvt.mnY = aWinPt.y; 3271 aWheelEvt.mnCode = 0; 3272 aWheelEvt.mnDelta = static_cast<short>(HIWORD( wParam )); 3273 aWheelEvt.mnNotchDelta = aWheelEvt.mnDelta/WHEEL_DELTA; 3274 if( aWheelEvt.mnNotchDelta == 0 ) 3275 { 3276 if( aWheelEvt.mnDelta > 0 ) 3277 aWheelEvt.mnNotchDelta = 1; 3278 else if( aWheelEvt.mnDelta < 0 ) 3279 aWheelEvt.mnNotchDelta = -1; 3280 } 3281 3282 if( nMsg == WM_MOUSEWHEEL ) 3283 { 3284 if ( aSalShlData.mnWheelScrollLines == WHEEL_PAGESCROLL ) 3285 aWheelEvt.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL; 3286 else 3287 aWheelEvt.mnScrollLines = aSalShlData.mnWheelScrollLines; 3288 aWheelEvt.mbHorz = false; 3289 } 3290 else 3291 { 3292 aWheelEvt.mnScrollLines = aSalShlData.mnWheelScrollChars; 3293 aWheelEvt.mbHorz = true; 3294 3295 // fdo#36380 - seems horiz scrolling has swapped direction 3296 aWheelEvt.mnDelta *= -1; 3297 aWheelEvt.mnNotchDelta *= -1; 3298 } 3299 3300 if ( nWinModCode & MK_SHIFT ) 3301 aWheelEvt.mnCode |= KEY_SHIFT; 3302 if ( nWinModCode & MK_CONTROL ) 3303 aWheelEvt.mnCode |= KEY_MOD1; 3304 if ( GetKeyState( VK_MENU ) & 0x8000 ) 3305 aWheelEvt.mnCode |= KEY_MOD2; 3306 3307 if( AllSettings::GetLayoutRTL() ) 3308 aWheelEvt.mnX = pFrame->maGeometry.width() - 1 - aWheelEvt.mnX; 3309 3310 nRet = pFrame->CallCallback( SalEvent::WheelMouse, &aWheelEvt ); 3311 } 3312 3313 ImplSalYieldMutexRelease(); 3314 3315 return nRet; 3316 } 3317 3318 static sal_uInt16 ImplSalGetKeyCode( WPARAM wParam ) 3319 { 3320 sal_uInt16 nKeyCode; 3321 3322 // convert KeyCode 3323 if ( wParam < KEY_TAB_SIZE ) 3324 nKeyCode = aImplTranslateKeyTab[wParam]; 3325 else 3326 { 3327 SalData* pSalData = GetSalData(); 3328 std::map< UINT, sal_uInt16 >::const_iterator it = pSalData->maVKMap.find( static_cast<UINT>(wParam) ); 3329 if( it != pSalData->maVKMap.end() ) 3330 nKeyCode = it->second; 3331 else 3332 nKeyCode = 0; 3333 } 3334 3335 return nKeyCode; 3336 } 3337 3338 static void ImplUpdateInputLang( WinSalFrame* pFrame ) 3339 { 3340 UINT nLang = LOWORD( GetKeyboardLayout( 0 ) ); 3341 if ( nLang && nLang != pFrame->mnInputLang ) 3342 { 3343 // keep input lang up-to-date 3344 pFrame->mnInputLang = nLang; 3345 } 3346 3347 // We are on Windows NT so we use Unicode FrameProcs and get 3348 // Unicode charcodes directly from Windows no need to set up a 3349 // code page 3350 return; 3351 } 3352 3353 static sal_Unicode ImplGetCharCode( WinSalFrame* pFrame, WPARAM nCharCode ) 3354 { 3355 ImplUpdateInputLang( pFrame ); 3356 3357 // We are on Windows NT so we use Unicode FrameProcs and we 3358 // get Unicode charcodes directly from Windows 3359 return static_cast<sal_Unicode>(nCharCode); 3360 } 3361 3362 LanguageType WinSalFrame::GetInputLanguage() 3363 { 3364 if( !mnInputLang ) 3365 ImplUpdateInputLang( this ); 3366 3367 if( !mnInputLang ) 3368 return LANGUAGE_DONTKNOW; 3369 else 3370 return LanguageType(mnInputLang); 3371 } 3372 3373 bool WinSalFrame::MapUnicodeToKeyCode( sal_Unicode aUnicode, LanguageType aLangType, vcl::KeyCode& rKeyCode ) 3374 { 3375 bool bRet = false; 3376 sal_IntPtr nLangType = static_cast<sal_uInt16>(aLangType); 3377 // just use the passed language identifier, do not try to load additional keyboard support 3378 HKL hkl = reinterpret_cast<HKL>(nLangType); 3379 3380 if( hkl ) 3381 { 3382 SHORT scan = VkKeyScanExW( aUnicode, hkl ); 3383 if( LOWORD(scan) == 0xFFFF ) 3384 // keyboard not loaded or key cannot be mapped 3385 bRet = false; 3386 else 3387 { 3388 BYTE vkeycode = LOBYTE(scan); 3389 BYTE shiftstate = HIBYTE(scan); 3390 3391 // Last argument is set to false, because there's no decision made 3392 // yet which key should be assigned to MOD3 modifier on Windows. 3393 // Windows key - user's can be confused, because it should display 3394 // Windows menu (applies to both left/right key) 3395 // Menu key - this key is used to display context menu 3396 // AltGr key - probably it has no sense 3397 rKeyCode = vcl::KeyCode( ImplSalGetKeyCode( vkeycode ), 3398 (shiftstate & 0x01) != 0, // shift 3399 (shiftstate & 0x02) != 0, // ctrl 3400 (shiftstate & 0x04) != 0, // alt 3401 false ); 3402 bRet = true; 3403 } 3404 } 3405 3406 return bRet; 3407 } 3408 3409 static void UnsetAltIfAltGr(SalKeyEvent& rKeyEvt, sal_uInt16 nModCode) 3410 { 3411 if ((nModCode & (KEY_MOD1 | KEY_MOD2)) == (KEY_MOD1 | KEY_MOD2) && 3412 rKeyEvt.mnCharCode) 3413 { 3414 // this is actually AltGr and should not be handled as Alt 3415 rKeyEvt.mnCode &= ~(KEY_MOD1 | KEY_MOD2); 3416 } 3417 } 3418 3419 static bool ImplHandleKeyMsg( HWND hWnd, UINT nMsg, 3420 WPARAM wParam, LPARAM lParam, LRESULT& rResult ) 3421 { 3422 static bool bIgnoreCharMsg = false; 3423 static WPARAM nDeadChar = 0; 3424 static WPARAM nLastVKChar = 0; 3425 static sal_uInt16 nLastChar = 0; 3426 static ModKeyFlags nLastModKeyCode = ModKeyFlags::NONE; 3427 static bool bWaitForModKeyRelease = false; 3428 sal_uInt16 nRepeat = LOWORD( lParam )-1; 3429 sal_uInt16 nModCode = 0; 3430 3431 // this key might have been relayed by SysChild and thus 3432 // may not be processed twice 3433 GetSalData()->mnSalObjWantKeyEvt = 0; 3434 3435 if ( nMsg == WM_DEADCHAR ) 3436 { 3437 nDeadChar = wParam; 3438 return false; 3439 } 3440 3441 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 3442 if ( !pFrame ) 3443 return false; 3444 3445 // reset the background mode for each text input, 3446 // as some tools such as RichWin may have changed it 3447 if ( pFrame->mpLocalGraphics && 3448 pFrame->mpLocalGraphics->getHDC() ) 3449 SetBkMode( pFrame->mpLocalGraphics->getHDC(), TRANSPARENT ); 3450 3451 // determine modifiers 3452 if ( GetKeyState( VK_SHIFT ) & 0x8000 ) 3453 nModCode |= KEY_SHIFT; 3454 if ( GetKeyState( VK_CONTROL ) & 0x8000 ) 3455 nModCode |= KEY_MOD1; 3456 if (GetKeyState(VK_MENU) & 0x8000) 3457 nModCode |= KEY_MOD2; 3458 3459 if ( (nMsg == WM_CHAR) || (nMsg == WM_SYSCHAR) ) 3460 { 3461 nDeadChar = 0; 3462 3463 if ( bIgnoreCharMsg ) 3464 { 3465 bIgnoreCharMsg = false; 3466 // #101635# if zero is returned here for WM_SYSCHAR (ALT+<key>) Windows will beep 3467 // because this 'hotkey' was not processed -> better return 1 3468 // except for Alt-SPACE which should always open the sysmenu (#104616#) 3469 3470 // also return zero if a system menubar is available that might process this hotkey 3471 // this also applies to the OLE inplace embedding where we are a child window 3472 if( (GetWindowStyle( hWnd ) & WS_CHILD) || GetMenu( hWnd ) || (wParam == 0x20) ) 3473 return false; 3474 else 3475 return true; 3476 } 3477 3478 // ignore backspace as a single key, so that 3479 // we do not get problems for combinations w/ a DeadKey 3480 if ( wParam == 0x08 ) // BACKSPACE 3481 return false; 3482 3483 // only "free flying" WM_CHAR messages arrive here, that are 3484 // created by typing an ALT-NUMPAD combination 3485 SalKeyEvent aKeyEvt; 3486 3487 if ( (wParam >= '0') && (wParam <= '9') ) 3488 aKeyEvt.mnCode = sal::static_int_cast<sal_uInt16>(KEYGROUP_NUM + wParam - '0'); 3489 else if ( (wParam >= 'A') && (wParam <= 'Z') ) 3490 aKeyEvt.mnCode = sal::static_int_cast<sal_uInt16>(KEYGROUP_ALPHA + wParam - 'A'); 3491 else if ( (wParam >= 'a') && (wParam <= 'z') ) 3492 aKeyEvt.mnCode = sal::static_int_cast<sal_uInt16>(KEYGROUP_ALPHA + wParam - 'a'); 3493 else if ( wParam == 0x0D ) // RETURN 3494 aKeyEvt.mnCode = KEY_RETURN; 3495 else if ( wParam == 0x1B ) // ESCAPE 3496 aKeyEvt.mnCode = KEY_ESCAPE; 3497 else if ( wParam == 0x09 ) // TAB 3498 aKeyEvt.mnCode = KEY_TAB; 3499 else if ( wParam == 0x20 ) // SPACE 3500 aKeyEvt.mnCode = KEY_SPACE; 3501 else 3502 aKeyEvt.mnCode = 0; 3503 3504 aKeyEvt.mnCode |= nModCode; 3505 aKeyEvt.mnCharCode = ImplGetCharCode( pFrame, wParam ); 3506 aKeyEvt.mnRepeat = nRepeat; 3507 3508 UnsetAltIfAltGr(aKeyEvt, nModCode); 3509 3510 nLastChar = 0; 3511 nLastVKChar = 0; 3512 3513 bool nRet = pFrame->CallCallback( SalEvent::KeyInput, &aKeyEvt ); 3514 pFrame->CallCallback( SalEvent::KeyUp, &aKeyEvt ); 3515 return nRet; 3516 } 3517 // #i11583#, MCD, 2003-01-13, Support for WM_UNICHAR & Keyman 6.0; addition begins 3518 else if( nMsg == WM_UNICHAR ) 3519 { 3520 // If Windows is asking if we accept WM_UNICHAR, return TRUE 3521 if(wParam == UNICODE_NOCHAR) 3522 { 3523 rResult = TRUE; // ssa: this will actually return TRUE to windows 3524 return true; // ...but this will only avoid calling the defwindowproc 3525 } 3526 3527 SalKeyEvent aKeyEvt; 3528 aKeyEvt.mnCode = nModCode; // Or should it be 0? - as this is always a character returned 3529 aKeyEvt.mnRepeat = 0; 3530 3531 if( wParam >= Uni_SupplementaryPlanesStart ) 3532 { 3533 // character is supplementary char in UTF-32 format - must be converted to UTF-16 supplementary pair 3534 // sal_Unicode ch = (sal_Unicode) Uni_UTF32ToSurrogate1(wParam); 3535 nLastChar = 0; 3536 nLastVKChar = 0; 3537 pFrame->CallCallback( SalEvent::KeyInput, &aKeyEvt ); 3538 pFrame->CallCallback( SalEvent::KeyUp, &aKeyEvt ); 3539 wParam = rtl::getLowSurrogate( wParam ); 3540 } 3541 3542 aKeyEvt.mnCharCode = static_cast<sal_Unicode>(wParam); 3543 3544 nLastChar = 0; 3545 nLastVKChar = 0; 3546 bool nRet = pFrame->CallCallback( SalEvent::KeyInput, &aKeyEvt ); 3547 pFrame->CallCallback( SalEvent::KeyUp, &aKeyEvt ); 3548 3549 return nRet; 3550 } 3551 // MCD, 2003-01-13, Support for WM_UNICHAR & Keyman 6.0; addition ends 3552 else 3553 { 3554 // for shift, control and menu we issue a KeyModChange event 3555 if ( (wParam == VK_SHIFT) || (wParam == VK_CONTROL) || (wParam == VK_MENU) ) 3556 { 3557 SalKeyModEvent aModEvt; 3558 aModEvt.mbDown = false; // auto-accelerator feature not supported here. 3559 aModEvt.mnCode = nModCode; 3560 aModEvt.mnModKeyCode = ModKeyFlags::NONE; // no command events will be sent if this member is 0 3561 3562 ModKeyFlags tmpCode = ModKeyFlags::NONE; 3563 if( GetKeyState( VK_LSHIFT ) & 0x8000 ) 3564 tmpCode |= ModKeyFlags::LeftShift; 3565 if( GetKeyState( VK_RSHIFT ) & 0x8000 ) 3566 tmpCode |= ModKeyFlags::RightShift; 3567 if( GetKeyState( VK_LCONTROL ) & 0x8000 ) 3568 tmpCode |= ModKeyFlags::LeftMod1; 3569 if( GetKeyState( VK_RCONTROL ) & 0x8000 ) 3570 tmpCode |= ModKeyFlags::RightMod1; 3571 if( GetKeyState( VK_LMENU ) & 0x8000 ) 3572 tmpCode |= ModKeyFlags::LeftMod2; 3573 if( GetKeyState( VK_RMENU ) & 0x8000 ) 3574 tmpCode |= ModKeyFlags::RightMod2; 3575 3576 if( tmpCode < nLastModKeyCode ) 3577 { 3578 aModEvt.mnModKeyCode = nLastModKeyCode; 3579 nLastModKeyCode = ModKeyFlags::NONE; 3580 bWaitForModKeyRelease = true; 3581 } 3582 else 3583 { 3584 if( !bWaitForModKeyRelease ) 3585 nLastModKeyCode = tmpCode; 3586 } 3587 3588 if( tmpCode == ModKeyFlags::NONE ) 3589 bWaitForModKeyRelease = false; 3590 3591 return pFrame->CallCallback( SalEvent::KeyModChange, &aModEvt ); 3592 } 3593 else 3594 { 3595 SalKeyEvent aKeyEvt; 3596 SalEvent nEvent; 3597 MSG aCharMsg; 3598 bool bCharPeek = false; 3599 UINT nCharMsg = WM_CHAR; 3600 bool bKeyUp = (nMsg == WM_KEYUP) || (nMsg == WM_SYSKEYUP); 3601 3602 nLastModKeyCode = ModKeyFlags::NONE; // make sure no modkey messages are sent if they belong to a hotkey (see above) 3603 aKeyEvt.mnCharCode = 0; 3604 aKeyEvt.mnCode = ImplSalGetKeyCode( wParam ); 3605 if ( !bKeyUp ) 3606 { 3607 // check for charcode 3608 // Get the related WM_CHAR message using PeekMessage, if available. 3609 // The WM_CHAR message is always at the beginning of the 3610 // message queue. Also it is made certain that there is always only 3611 // one WM_CHAR message in the queue. 3612 bCharPeek = PeekMessageW( &aCharMsg, hWnd, 3613 WM_CHAR, WM_CHAR, PM_NOREMOVE | PM_NOYIELD ); 3614 if ( bCharPeek && (nDeadChar == aCharMsg.wParam) ) 3615 { 3616 bCharPeek = false; 3617 nDeadChar = 0; 3618 3619 if ( wParam == VK_BACK ) 3620 { 3621 PeekMessageW( &aCharMsg, hWnd, 3622 nCharMsg, nCharMsg, PM_REMOVE | PM_NOYIELD ); 3623 return false; 3624 } 3625 } 3626 else 3627 { 3628 if ( !bCharPeek ) 3629 { 3630 bCharPeek = PeekMessageW( &aCharMsg, hWnd, 3631 WM_SYSCHAR, WM_SYSCHAR, PM_NOREMOVE | PM_NOYIELD ); 3632 nCharMsg = WM_SYSCHAR; 3633 } 3634 } 3635 if ( bCharPeek ) 3636 aKeyEvt.mnCharCode = ImplGetCharCode( pFrame, aCharMsg.wParam ); 3637 else 3638 aKeyEvt.mnCharCode = 0; 3639 3640 nLastChar = aKeyEvt.mnCharCode; 3641 nLastVKChar = wParam; 3642 } 3643 else 3644 { 3645 if ( wParam == nLastVKChar ) 3646 { 3647 aKeyEvt.mnCharCode = nLastChar; 3648 nLastChar = 0; 3649 nLastVKChar = 0; 3650 } 3651 } 3652 3653 if ( aKeyEvt.mnCode || aKeyEvt.mnCharCode ) 3654 { 3655 if ( bKeyUp ) 3656 nEvent = SalEvent::KeyUp; 3657 else 3658 nEvent = SalEvent::KeyInput; 3659 3660 aKeyEvt.mnCode |= nModCode; 3661 aKeyEvt.mnRepeat = nRepeat; 3662 3663 UnsetAltIfAltGr(aKeyEvt, nModCode); 3664 3665 bIgnoreCharMsg = bCharPeek; 3666 bool nRet = pFrame->CallCallback( nEvent, &aKeyEvt ); 3667 // independent part only reacts on keyup but Windows does not send 3668 // keyup for VK_HANJA 3669 if( aKeyEvt.mnCode == KEY_HANGUL_HANJA ) 3670 nRet = pFrame->CallCallback( SalEvent::KeyUp, &aKeyEvt ); 3671 3672 bIgnoreCharMsg = false; 3673 3674 // char-message, then remove or ignore 3675 if ( bCharPeek ) 3676 { 3677 nDeadChar = 0; 3678 if ( nRet ) 3679 { 3680 PeekMessageW( &aCharMsg, hWnd, 3681 nCharMsg, nCharMsg, PM_REMOVE | PM_NOYIELD ); 3682 } 3683 else 3684 bIgnoreCharMsg = true; 3685 } 3686 3687 return nRet; 3688 } 3689 else 3690 return false; 3691 } 3692 } 3693 } 3694 3695 bool ImplHandleSalObjKeyMsg( HWND hWnd, UINT nMsg, 3696 WPARAM wParam, LPARAM lParam ) 3697 { 3698 if ( (nMsg == WM_KEYDOWN) || (nMsg == WM_KEYUP) ) 3699 { 3700 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 3701 if ( !pFrame ) 3702 return false; 3703 3704 sal_uInt16 nRepeat = LOWORD( lParam )-1; 3705 sal_uInt16 nModCode = 0; 3706 3707 // determine modifiers 3708 if ( GetKeyState( VK_SHIFT ) & 0x8000 ) 3709 nModCode |= KEY_SHIFT; 3710 if ( GetKeyState( VK_CONTROL ) & 0x8000 ) 3711 nModCode |= KEY_MOD1; 3712 if ( GetKeyState( VK_MENU ) & 0x8000 ) 3713 nModCode |= KEY_MOD2; 3714 3715 if ( (wParam != VK_SHIFT) && (wParam != VK_CONTROL) && (wParam != VK_MENU) ) 3716 { 3717 SalKeyEvent aKeyEvt; 3718 SalEvent nEvent; 3719 3720 // convert KeyCode 3721 aKeyEvt.mnCode = ImplSalGetKeyCode( wParam ); 3722 aKeyEvt.mnCharCode = 0; 3723 3724 if ( aKeyEvt.mnCode ) 3725 { 3726 if (nMsg == WM_KEYUP) 3727 nEvent = SalEvent::KeyUp; 3728 else 3729 nEvent = SalEvent::KeyInput; 3730 3731 aKeyEvt.mnCode |= nModCode; 3732 aKeyEvt.mnRepeat = nRepeat; 3733 bool nRet = pFrame->CallCallback( nEvent, &aKeyEvt ); 3734 return nRet; 3735 } 3736 else 3737 return false; 3738 } 3739 } 3740 3741 return false; 3742 } 3743 3744 bool ImplHandleSalObjSysCharMsg( HWND hWnd, WPARAM wParam, LPARAM lParam ) 3745 { 3746 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 3747 if ( !pFrame ) 3748 return false; 3749 3750 sal_uInt16 nRepeat = LOWORD( lParam )-1; 3751 sal_uInt16 nModCode = 0; 3752 sal_uInt16 cKeyCode = static_cast<sal_uInt16>(wParam); 3753 3754 // determine modifiers 3755 if ( GetKeyState( VK_SHIFT ) & 0x8000 ) 3756 nModCode |= KEY_SHIFT; 3757 if ( GetKeyState( VK_CONTROL ) & 0x8000 ) 3758 nModCode |= KEY_MOD1; 3759 nModCode |= KEY_MOD2; 3760 3761 // assemble KeyEvent 3762 SalKeyEvent aKeyEvt; 3763 if ( (cKeyCode >= 48) && (cKeyCode <= 57) ) 3764 aKeyEvt.mnCode = KEY_0+(cKeyCode-48); 3765 else if ( (cKeyCode >= 65) && (cKeyCode <= 90) ) 3766 aKeyEvt.mnCode = KEY_A+(cKeyCode-65); 3767 else if ( (cKeyCode >= 97) && (cKeyCode <= 122) ) 3768 aKeyEvt.mnCode = KEY_A+(cKeyCode-97); 3769 else 3770 aKeyEvt.mnCode = 0; 3771 aKeyEvt.mnCode |= nModCode; 3772 aKeyEvt.mnCharCode = ImplGetCharCode( pFrame, cKeyCode ); 3773 aKeyEvt.mnRepeat = nRepeat; 3774 bool nRet = pFrame->CallCallback( SalEvent::KeyInput, &aKeyEvt ); 3775 pFrame->CallCallback( SalEvent::KeyUp, &aKeyEvt ); 3776 return nRet; 3777 } 3778 3779 namespace { 3780 3781 enum class DeferPolicy 3782 { 3783 Blocked, 3784 Allowed 3785 }; 3786 3787 } 3788 3789 // Remember to release the solar mutex on success! 3790 static WinSalFrame* ProcessOrDeferMessage( HWND hWnd, INT nMsg, WPARAM pWParam = 0, 3791 DeferPolicy eCanDefer = DeferPolicy::Allowed ) 3792 { 3793 bool bFailedCondition = false, bGotMutex = false; 3794 WinSalFrame* pFrame = nullptr; 3795 3796 if ( DeferPolicy::Blocked == eCanDefer ) 3797 assert( (DeferPolicy::Blocked == eCanDefer) && (nMsg == 0) && (pWParam == 0) ); 3798 else 3799 assert( (DeferPolicy::Allowed == eCanDefer) && (nMsg != 0) ); 3800 3801 if ( DeferPolicy::Blocked == eCanDefer ) 3802 { 3803 ImplSalYieldMutexAcquireWithWait(); 3804 bGotMutex = true; 3805 } 3806 else if ( !(bGotMutex = ImplSalYieldMutexTryToAcquire()) ) 3807 bFailedCondition = true; 3808 3809 if ( !bFailedCondition ) 3810 { 3811 pFrame = GetWindowPtr( hWnd ); 3812 bFailedCondition = pFrame == nullptr; 3813 } 3814 3815 if ( bFailedCondition ) 3816 { 3817 if ( bGotMutex ) 3818 ImplSalYieldMutexRelease(); 3819 if ( DeferPolicy::Allowed == eCanDefer ) 3820 { 3821 bool const ret = PostMessageW(hWnd, nMsg, pWParam, 0); 3822 SAL_WARN_IF(!ret, "vcl", "ERROR: PostMessage() failed!"); 3823 } 3824 } 3825 3826 return pFrame; 3827 } 3828 3829 namespace { 3830 3831 enum class PostedState 3832 { 3833 IsPosted, 3834 IsInitial 3835 }; 3836 3837 } 3838 3839 static bool ImplHandlePostPaintMsg( HWND hWnd, RECT* pRect, 3840 PostedState eProcessed = PostedState::IsPosted ) 3841 { 3842 RECT* pMsgRect; 3843 if ( PostedState::IsInitial == eProcessed ) 3844 { 3845 pMsgRect = new RECT; 3846 CopyRect( pMsgRect, pRect ); 3847 } 3848 else 3849 pMsgRect = pRect; 3850 3851 WinSalFrame* pFrame = ProcessOrDeferMessage( hWnd, SAL_MSG_POSTPAINT, 3852 reinterpret_cast<WPARAM>(pMsgRect) ); 3853 if ( pFrame ) 3854 { 3855 SalPaintEvent aPEvt( pRect->left, pRect->top, pRect->right-pRect->left, pRect->bottom-pRect->top ); 3856 pFrame->CallCallback( SalEvent::Paint, &aPEvt ); 3857 ImplSalYieldMutexRelease(); 3858 if ( PostedState::IsPosted == eProcessed ) 3859 delete pRect; 3860 } 3861 3862 return (pFrame != nullptr); 3863 } 3864 3865 static bool ImplHandlePaintMsg( HWND hWnd ) 3866 { 3867 bool bPaintSuccessful = false; 3868 3869 // even without the Yield mutex, we can still change the clip region, 3870 // because other threads don't use the Yield mutex 3871 // --> see AcquireGraphics() 3872 3873 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 3874 if ( pFrame ) 3875 { 3876 // clip region must be set, as we don't get a proper 3877 // bounding rectangle otherwise 3878 WinSalGraphics *pGraphics = pFrame->mpLocalGraphics; 3879 bool bHasClipRegion = pGraphics && 3880 pGraphics->getHDC() && pGraphics->getRegion(); 3881 if ( bHasClipRegion ) 3882 SelectClipRgn( pGraphics->getHDC(), nullptr ); 3883 3884 // according to Windows documentation one shall check first if 3885 // there really is a paint-region 3886 RECT aUpdateRect; 3887 PAINTSTRUCT aPs; 3888 bool bHasPaintRegion = GetUpdateRect( hWnd, nullptr, FALSE ); 3889 if ( bHasPaintRegion ) 3890 { 3891 // call BeginPaint/EndPaint to query the paint rect and use 3892 // this information in the (deferred) paint 3893 BeginPaint( hWnd, &aPs ); 3894 CopyRect( &aUpdateRect, &aPs.rcPaint ); 3895 } 3896 3897 // reset clip region 3898 if ( bHasClipRegion ) 3899 SelectClipRgn( pGraphics->getHDC(), pGraphics->getRegion() ); 3900 3901 // try painting 3902 if ( bHasPaintRegion ) 3903 { 3904 bPaintSuccessful = ImplHandlePostPaintMsg( 3905 hWnd, &aUpdateRect, PostedState::IsInitial ); 3906 EndPaint( hWnd, &aPs ); 3907 } 3908 else // if there is nothing to paint, the paint is successful 3909 bPaintSuccessful = true; 3910 } 3911 3912 return bPaintSuccessful; 3913 } 3914 3915 static void SetMaximizedFrameGeometry( HWND hWnd, WinSalFrame* pFrame, RECT* pParentRect ) 3916 { 3917 // calculate and set frame geometry of a maximized window - useful if the window is still hidden 3918 3919 // dualmonitor support: 3920 // Get screensize of the monitor with the mouse pointer 3921 3922 RECT aRectMouse; 3923 if( ! pParentRect ) 3924 { 3925 POINT pt; 3926 GetCursorPos( &pt ); 3927 aRectMouse.left = pt.x; 3928 aRectMouse.top = pt.y; 3929 aRectMouse.right = pt.x+2; 3930 aRectMouse.bottom = pt.y+2; 3931 pParentRect = &aRectMouse; 3932 } 3933 3934 RECT aRect; 3935 ImplSalGetWorkArea( hWnd, &aRect, pParentRect ); 3936 3937 // a maximized window has no other borders than the caption 3938 pFrame->maGeometry.setDecorations(0, pFrame->mbCaption ? GetSystemMetrics(SM_CYCAPTION) : 0, 0, 0); 3939 3940 aRect.top += pFrame->maGeometry.topDecoration(); 3941 pFrame->maGeometry.setPos({ aRect.left, aRect.top }); 3942 SetGeometrySize(pFrame->maGeometry, { aRect.right - aRect.left, aRect.bottom - aRect.top }); 3943 } 3944 3945 static void UpdateFrameGeometry(WinSalFrame* pFrame) 3946 { 3947 if( !pFrame ) 3948 return; 3949 const HWND hWnd = pFrame->mhWnd; 3950 3951 RECT aRect; 3952 GetWindowRect( hWnd, &aRect ); 3953 pFrame->maGeometry.setPosSize({ 0, 0 }, { 0, 0 }); 3954 pFrame->maGeometry.setDecorations(0, 0, 0, 0); 3955 pFrame->maGeometry.setScreen(0); 3956 3957 if ( IsIconic( hWnd ) ) 3958 return; 3959 3960 POINT aPt; 3961 aPt.x=0; 3962 aPt.y=0; 3963 ClientToScreen(hWnd, &aPt); 3964 int cx = aPt.x - aRect.left; 3965 3966 pFrame->maGeometry.setDecorations(cx, aPt.y - aRect.top, cx, 0); 3967 pFrame->maGeometry.setPos({ aPt.x, aPt.y }); 3968 3969 RECT aInnerRect; 3970 GetClientRect( hWnd, &aInnerRect ); 3971 if( aInnerRect.right ) 3972 { 3973 // improve right decoration 3974 aPt.x=aInnerRect.right; 3975 aPt.y=aInnerRect.top; 3976 ClientToScreen(hWnd, &aPt); 3977 pFrame->maGeometry.setRightDecoration(aRect.right - aPt.x); 3978 } 3979 if( aInnerRect.bottom ) // may be zero if window was not shown yet 3980 pFrame->maGeometry.setBottomDecoration(aRect.bottom - aPt.y - aInnerRect.bottom); 3981 else 3982 // bottom border is typically the same as left/right 3983 pFrame->maGeometry.setBottomDecoration(pFrame->maGeometry.leftDecoration()); 3984 3985 int nWidth = aRect.right - aRect.left 3986 - pFrame->maGeometry.rightDecoration() - pFrame->maGeometry.leftDecoration(); 3987 int nHeight = aRect.bottom - aRect.top 3988 - pFrame->maGeometry.bottomDecoration() - pFrame->maGeometry.topDecoration(); 3989 SetGeometrySize(pFrame->maGeometry, { nWidth, nHeight }); 3990 pFrame->updateScreenNumber(); 3991 } 3992 3993 static void ImplCallClosePopupsHdl( HWND hWnd ) 3994 { 3995 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 3996 if ( pFrame ) 3997 { 3998 pFrame->CallCallback( SalEvent::ClosePopups, nullptr ); 3999 } 4000 } 4001 4002 static void ImplCallMoveHdl(HWND hWnd) 4003 { 4004 WinSalFrame* pFrame = ProcessOrDeferMessage(hWnd, SAL_MSG_POSTMOVE); 4005 if (!pFrame) 4006 return; 4007 4008 pFrame->CallCallback(SalEvent::Move, nullptr); 4009 4010 ImplSalYieldMutexRelease(); 4011 } 4012 4013 static void ImplHandleMoveMsg(HWND hWnd, LPARAM lParam) 4014 { 4015 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 4016 if (!pFrame) 4017 return; 4018 4019 UpdateFrameGeometry(pFrame); 4020 4021 #ifdef NDEBUG 4022 (void) lParam; 4023 #endif 4024 assert(IsIconic(hWnd) || (pFrame->maGeometry.x() == static_cast<sal_Int16>(LOWORD(lParam)))); 4025 assert(IsIconic(hWnd) || (pFrame->maGeometry.y() == static_cast<sal_Int16>(HIWORD(lParam)))); 4026 4027 if (GetWindowStyle(hWnd) & WS_VISIBLE) 4028 pFrame->mbDefPos = false; 4029 4030 // protect against recursion 4031 if (!pFrame->mbInMoveMsg) 4032 { 4033 // adjust window again for FullScreenMode 4034 pFrame->mbInMoveMsg = true; 4035 if (pFrame->isFullScreen()) 4036 ImplSalFrameFullScreenPos(pFrame); 4037 pFrame->mbInMoveMsg = false; 4038 } 4039 4040 pFrame->UpdateFrameState(); 4041 4042 ImplCallMoveHdl(hWnd); 4043 } 4044 4045 static void ImplCallSizeHdl( HWND hWnd ) 4046 { 4047 WinSalFrame* pFrame = ProcessOrDeferMessage( hWnd, SAL_MSG_POSTCALLSIZE ); 4048 if (!pFrame) 4049 return; 4050 4051 pFrame->CallCallback(SalEvent::Resize, nullptr); 4052 // to avoid double Paints by VCL and SAL 4053 if (IsWindowVisible(hWnd) && !pFrame->mbInShow) 4054 UpdateWindow(hWnd); 4055 4056 ImplSalYieldMutexRelease(); 4057 } 4058 4059 static void ImplHandleSizeMsg(HWND hWnd, WPARAM wParam, LPARAM lParam) 4060 { 4061 if ((wParam == SIZE_MAXSHOW) || (wParam == SIZE_MAXHIDE)) 4062 return; 4063 4064 WinSalFrame* pFrame = GetWindowPtr(hWnd); 4065 if (!pFrame) 4066 return; 4067 4068 UpdateFrameGeometry(pFrame); 4069 4070 #ifdef NDEBUG 4071 (void) lParam; 4072 #endif 4073 assert(pFrame->maGeometry.width() == static_cast<sal_Int16>(LOWORD(lParam))); 4074 assert(pFrame->maGeometry.height() == static_cast<sal_Int16>(HIWORD(lParam))); 4075 4076 pFrame->UpdateFrameState(); 4077 4078 ImplCallSizeHdl(hWnd); 4079 4080 WinSalTimer* pTimer = static_cast<WinSalTimer*>(ImplGetSVData()->maSchedCtx.mpSalTimer); 4081 if (pTimer) 4082 pTimer->SetForceRealTimer(true); 4083 } 4084 4085 static void ImplHandleFocusMsg( HWND hWnd ) 4086 { 4087 WinSalFrame* pFrame = ProcessOrDeferMessage( hWnd, SAL_MSG_POSTFOCUS ); 4088 if (!pFrame) 4089 return; 4090 const ::comphelper::ScopeGuard aScopeGuard([](){ ImplSalYieldMutexRelease(); }); 4091 4092 if (WinSalFrame::mbInReparent) 4093 return; 4094 4095 const bool bGotFocus = ::GetFocus() == hWnd; 4096 if (bGotFocus) 4097 { 4098 if (IsWindowVisible(hWnd) && !pFrame->mbInShow) 4099 UpdateWindow(hWnd); 4100 4101 // do we support IME? 4102 if (pFrame->mbIME && pFrame->mhDefIMEContext) 4103 { 4104 UINT nImeProps = ImmGetProperty(GetKeyboardLayout(0), IGP_PROPERTY); 4105 pFrame->mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0; 4106 pFrame->mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0; 4107 pFrame->mbHandleIME = !pFrame->mbSpezIME; 4108 } 4109 } 4110 4111 pFrame->CallCallback(bGotFocus ? SalEvent::GetFocus : SalEvent::LoseFocus, nullptr); 4112 } 4113 4114 static void ImplHandleCloseMsg( HWND hWnd ) 4115 { 4116 WinSalFrame* pFrame = ProcessOrDeferMessage( hWnd, WM_CLOSE ); 4117 if ( pFrame ) 4118 { 4119 pFrame->CallCallback( SalEvent::Close, nullptr ); 4120 ImplSalYieldMutexRelease(); 4121 } 4122 } 4123 4124 static bool ImplHandleShutDownMsg( HWND hWnd ) 4125 { 4126 bool nRet = false; 4127 WinSalFrame* pFrame = ProcessOrDeferMessage( hWnd, 0, 0, DeferPolicy::Blocked ); 4128 if ( pFrame ) 4129 { 4130 nRet = pFrame->CallCallback( SalEvent::Shutdown, nullptr ); 4131 ImplSalYieldMutexRelease(); 4132 } 4133 return nRet; 4134 } 4135 4136 static void ImplHandleSettingsChangeMsg( HWND hWnd, UINT nMsg, 4137 WPARAM wParam, LPARAM lParam ) 4138 { 4139 SalEvent nSalEvent = SalEvent::SettingsChanged; 4140 4141 if ( nMsg == WM_DEVMODECHANGE ) 4142 nSalEvent = SalEvent::PrinterChanged; 4143 else if ( nMsg == WM_DISPLAYCHANGE ) 4144 nSalEvent = SalEvent::DisplayChanged; 4145 else if ( nMsg == WM_FONTCHANGE ) 4146 nSalEvent = SalEvent::FontChanged; 4147 else if ( nMsg == WM_WININICHANGE ) 4148 { 4149 if ( lParam ) 4150 { 4151 if ( ImplSalWICompareAscii( reinterpret_cast<const wchar_t*>(lParam), "devices" ) == 0 ) 4152 nSalEvent = SalEvent::PrinterChanged; 4153 } 4154 } 4155 4156 if ( nMsg == WM_SETTINGCHANGE ) 4157 { 4158 if ( wParam == SPI_SETWHEELSCROLLLINES ) 4159 aSalShlData.mnWheelScrollLines = ImplSalGetWheelScrollLines(); 4160 else if( wParam == SPI_SETWHEELSCROLLCHARS ) 4161 aSalShlData.mnWheelScrollChars = ImplSalGetWheelScrollChars(); 4162 UpdateDarkMode(hWnd); 4163 GetSalData()->mbThemeChanged = true; 4164 } 4165 4166 if ( WM_SYSCOLORCHANGE == nMsg && GetSalData()->mhDitherPal ) 4167 ImplUpdateSysColorEntries(); 4168 4169 WinSalFrame* pFrame = ProcessOrDeferMessage( hWnd, 0, 0, DeferPolicy::Blocked ); 4170 if (!pFrame) 4171 return; 4172 4173 if (((nMsg == WM_DISPLAYCHANGE) || (nMsg == WM_WININICHANGE)) && pFrame->isFullScreen()) 4174 ImplSalFrameFullScreenPos(pFrame); 4175 4176 pFrame->CallCallback(nSalEvent, nullptr); 4177 4178 ImplSalYieldMutexRelease(); 4179 } 4180 4181 static void ImplHandleUserEvent( HWND hWnd, LPARAM lParam ) 4182 { 4183 WinSalFrame* pFrame = ProcessOrDeferMessage( hWnd, 0, 0, DeferPolicy::Blocked ); 4184 if ( pFrame ) 4185 { 4186 pFrame->CallCallback( SalEvent::UserEvent, reinterpret_cast<void*>(lParam) ); 4187 ImplSalYieldMutexRelease(); 4188 } 4189 } 4190 4191 static void ImplHandleForcePalette( HWND hWnd ) 4192 { 4193 SalData* pSalData = GetSalData(); 4194 HPALETTE hPal = pSalData->mhDitherPal; 4195 if (!hPal) 4196 return; 4197 4198 WinSalFrame* pFrame = ProcessOrDeferMessage(hWnd, SAL_MSG_FORCEPALETTE); 4199 if (!pFrame) 4200 return; 4201 const ::comphelper::ScopeGuard aScopeGuard([](){ ImplSalYieldMutexRelease(); }); 4202 4203 WinSalGraphics* pGraphics = pFrame->mpLocalGraphics; 4204 if (!pGraphics || !pGraphics->getHDC() || !pGraphics->getDefPal() 4205 || (pGraphics->setPalette(hPal, FALSE) == GDI_ERROR)) 4206 return; 4207 4208 InvalidateRect(hWnd, nullptr, FALSE); 4209 UpdateWindow(hWnd); 4210 pFrame->CallCallback(SalEvent::DisplayChanged, nullptr); 4211 } 4212 4213 static LRESULT ImplHandlePalette( bool bFrame, HWND hWnd, UINT nMsg, 4214 WPARAM wParam, LPARAM lParam, bool& rDef ) 4215 { 4216 SalData* pSalData = GetSalData(); 4217 HPALETTE hPal = pSalData->mhDitherPal; 4218 if ( !hPal ) 4219 return 0; 4220 4221 rDef = false; 4222 if ( pSalData->mbInPalChange ) 4223 return 0; 4224 4225 if ( (nMsg == WM_PALETTECHANGED) || (nMsg == SAL_MSG_POSTPALCHANGED) ) 4226 { 4227 if ( reinterpret_cast<HWND>(wParam) == hWnd ) 4228 return 0; 4229 } 4230 4231 bool bReleaseMutex = false; 4232 if ( (nMsg == WM_QUERYNEWPALETTE) || (nMsg == WM_PALETTECHANGED) ) 4233 { 4234 // as Windows can send these messages also, we have to use 4235 // the Solar semaphore 4236 if ( ImplSalYieldMutexTryToAcquire() ) 4237 bReleaseMutex = true; 4238 else if ( nMsg == WM_QUERYNEWPALETTE ) 4239 { 4240 bool const ret = PostMessageW(hWnd, SAL_MSG_POSTQUERYNEWPAL, wParam, lParam); 4241 SAL_WARN_IF(!ret, "vcl", "ERROR: PostMessage() failed!"); 4242 } 4243 else /* ( nMsg == WM_PALETTECHANGED ) */ 4244 { 4245 bool const ret = PostMessageW(hWnd, SAL_MSG_POSTPALCHANGED, wParam, lParam); 4246 SAL_WARN_IF(!ret, "vcl", "ERROR: PostMessage() failed!"); 4247 } 4248 } 4249 4250 WinSalVirtualDevice*pTempVD; 4251 WinSalFrame* pTempFrame; 4252 WinSalGraphics* pGraphics; 4253 HDC hDC; 4254 HPALETTE hOldPal = nullptr; 4255 UINT nCols = GDI_ERROR; 4256 bool bUpdate; 4257 4258 pSalData->mbInPalChange = true; 4259 4260 // reset all palettes in VirDevs and Frames 4261 pTempVD = pSalData->mpFirstVD; 4262 while ( pTempVD ) 4263 { 4264 pGraphics = pTempVD->getGraphics(); 4265 pGraphics->setPalette(nullptr); 4266 pTempVD = pTempVD->getNext(); 4267 } 4268 pTempFrame = pSalData->mpFirstFrame; 4269 while ( pTempFrame ) 4270 { 4271 pGraphics = pTempFrame->mpLocalGraphics; 4272 pGraphics->setPalette(nullptr); 4273 pTempFrame = pTempFrame->mpNextFrame; 4274 } 4275 4276 // re-initialize palette 4277 WinSalFrame* pFrame = nullptr; 4278 if ( bFrame ) 4279 pFrame = GetWindowPtr( hWnd ); 4280 4281 UnrealizeObject(hPal); 4282 const bool bStdDC = pFrame && pFrame->mpLocalGraphics && pFrame->mpLocalGraphics->getHDC(); 4283 if (!bStdDC) 4284 { 4285 hDC = GetDC(hWnd); 4286 hOldPal = SelectPalette(hDC, hPal, TRUE); 4287 if (hOldPal) 4288 nCols = RealizePalette(hDC); 4289 } 4290 else 4291 { 4292 hDC = pFrame->mpLocalGraphics->getHDC(); 4293 nCols = pFrame->mpLocalGraphics->setPalette(hPal); 4294 } 4295 4296 bUpdate = nCols != 0 && nCols != GDI_ERROR; 4297 4298 if ( !bStdDC ) 4299 { 4300 if (hOldPal) 4301 SelectPalette(hDC, hOldPal, TRUE); 4302 ReleaseDC( hWnd, hDC ); 4303 } 4304 4305 // reset all palettes in VirDevs and Frames 4306 pTempVD = pSalData->mpFirstVD; 4307 while ( pTempVD ) 4308 { 4309 pGraphics = pTempVD->getGraphics(); 4310 if ( pGraphics->getDefPal() ) 4311 pGraphics->setPalette(hPal); 4312 pTempVD = pTempVD->getNext(); 4313 } 4314 4315 pTempFrame = pSalData->mpFirstFrame; 4316 while ( pTempFrame ) 4317 { 4318 if ( pTempFrame != pFrame ) 4319 { 4320 pGraphics = pTempFrame->mpLocalGraphics; 4321 if (pGraphics && pGraphics->getDefPal()) 4322 { 4323 UINT nRes = pGraphics->setPalette(hPal); 4324 if (nRes != 0 && nRes != GDI_ERROR) 4325 bUpdate = true; 4326 } 4327 } 4328 pTempFrame = pTempFrame->mpNextFrame; 4329 } 4330 4331 // if colors changed, update the window 4332 if ( bUpdate ) 4333 { 4334 pTempFrame = pSalData->mpFirstFrame; 4335 while ( pTempFrame ) 4336 { 4337 pGraphics = pTempFrame->mpLocalGraphics; 4338 if (pGraphics && pGraphics->getDefPal()) 4339 { 4340 InvalidateRect( pTempFrame->mhWnd, nullptr, FALSE ); 4341 UpdateWindow( pTempFrame->mhWnd ); 4342 pTempFrame->CallCallback( SalEvent::DisplayChanged, nullptr ); 4343 } 4344 pTempFrame = pTempFrame->mpNextFrame; 4345 } 4346 } 4347 4348 pSalData->mbInPalChange = false; 4349 4350 if ( bReleaseMutex ) 4351 ImplSalYieldMutexRelease(); 4352 4353 if ( nMsg == WM_PALETTECHANGED ) 4354 return 0; 4355 else 4356 return nCols; 4357 } 4358 4359 static bool ImplHandleMinMax( HWND hWnd, LPARAM lParam ) 4360 { 4361 bool bRet = false; 4362 4363 if ( ImplSalYieldMutexTryToAcquire() ) 4364 { 4365 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 4366 if ( pFrame ) 4367 { 4368 MINMAXINFO* pMinMax = reinterpret_cast<MINMAXINFO*>(lParam); 4369 4370 if (pFrame->isFullScreen()) 4371 { 4372 int nX; 4373 int nY; 4374 int nDX; 4375 int nDY; 4376 ImplSalCalcFullScreenSize( pFrame, nX, nY, nDX, nDY ); 4377 4378 if ( pMinMax->ptMaxPosition.x > nX ) 4379 pMinMax->ptMaxPosition.x = nX; 4380 if ( pMinMax->ptMaxPosition.y > nY ) 4381 pMinMax->ptMaxPosition.y = nY; 4382 4383 if ( pMinMax->ptMaxSize.x < nDX ) 4384 pMinMax->ptMaxSize.x = nDX; 4385 if ( pMinMax->ptMaxSize.y < nDY ) 4386 pMinMax->ptMaxSize.y = nDY; 4387 if ( pMinMax->ptMaxTrackSize.x < nDX ) 4388 pMinMax->ptMaxTrackSize.x = nDX; 4389 if ( pMinMax->ptMaxTrackSize.y < nDY ) 4390 pMinMax->ptMaxTrackSize.y = nDY; 4391 4392 pMinMax->ptMinTrackSize.x = nDX; 4393 pMinMax->ptMinTrackSize.y = nDY; 4394 4395 bRet = true; 4396 } 4397 4398 if ( pFrame->mnMinWidth || pFrame->mnMinHeight ) 4399 { 4400 int nWidth = pFrame->mnMinWidth; 4401 int nHeight = pFrame->mnMinHeight; 4402 4403 ImplSalAddBorder( pFrame, nWidth, nHeight ); 4404 4405 if ( pMinMax->ptMinTrackSize.x < nWidth ) 4406 pMinMax->ptMinTrackSize.x = nWidth; 4407 if ( pMinMax->ptMinTrackSize.y < nHeight ) 4408 pMinMax->ptMinTrackSize.y = nHeight; 4409 } 4410 4411 if ( pFrame->mnMaxWidth || pFrame->mnMaxHeight ) 4412 { 4413 int nWidth = pFrame->mnMaxWidth; 4414 int nHeight = pFrame->mnMaxHeight; 4415 4416 ImplSalAddBorder( pFrame, nWidth, nHeight ); 4417 4418 if( nWidth > 0 && nHeight > 0 ) // protect against int overflow due to INT_MAX initialisation 4419 { 4420 if ( pMinMax->ptMaxTrackSize.x > nWidth ) 4421 pMinMax->ptMaxTrackSize.x = nWidth; 4422 if ( pMinMax->ptMaxTrackSize.y > nHeight ) 4423 pMinMax->ptMaxTrackSize.y = nHeight; 4424 } 4425 } 4426 } 4427 4428 ImplSalYieldMutexRelease(); 4429 } 4430 4431 return bRet; 4432 } 4433 4434 // retrieves the SalMenuItem pointer from a hMenu 4435 // the pointer is stored in every item, so if no position 4436 // is specified we just use the first item (ie, pos=0) 4437 // if bByPosition is false then nPos denotes a menu id instead of a position 4438 static WinSalMenuItem* ImplGetSalMenuItem( HMENU hMenu, UINT nPos, bool bByPosition=true ) 4439 { 4440 MENUITEMINFOW mi = {}; 4441 mi.cbSize = sizeof( mi ); 4442 mi.fMask = MIIM_DATA; 4443 if( !GetMenuItemInfoW( hMenu, nPos, bByPosition, &mi) ) 4444 SAL_WARN("vcl", "GetMenuItemInfoW failed: " << WindowsErrorString(GetLastError())); 4445 4446 return reinterpret_cast<WinSalMenuItem *>(mi.dwItemData); 4447 } 4448 4449 // returns the index of the currently selected item if any or -1 4450 static int ImplGetSelectedIndex( HMENU hMenu ) 4451 { 4452 MENUITEMINFOW mi = {}; 4453 mi.cbSize = sizeof( mi ); 4454 mi.fMask = MIIM_STATE; 4455 int n = GetMenuItemCount( hMenu ); 4456 if( n != -1 ) 4457 { 4458 for(int i=0; i<n; i++ ) 4459 { 4460 if( !GetMenuItemInfoW( hMenu, i, TRUE, &mi) ) 4461 SAL_WARN( "vcl", "GetMenuItemInfoW failed: " << WindowsErrorString( GetLastError() ) ); 4462 else 4463 { 4464 if( mi.fState & MFS_HILITE ) 4465 return i; 4466 } 4467 } 4468 } 4469 return -1; 4470 } 4471 4472 static LRESULT ImplMenuChar( HWND, WPARAM wParam, LPARAM lParam ) 4473 { 4474 LRESULT nRet = MNC_IGNORE; 4475 HMENU hMenu = reinterpret_cast<HMENU>(lParam); 4476 OUString aMnemonic( "&" + OUStringChar(static_cast<sal_Unicode>(LOWORD(wParam))) ); 4477 aMnemonic = aMnemonic.toAsciiLowerCase(); // we only have ascii mnemonics 4478 4479 // search the mnemonic in the current menu 4480 int nItemCount = GetMenuItemCount( hMenu ); 4481 int nFound = 0; 4482 int idxFound = -1; 4483 int idxSelected = ImplGetSelectedIndex( hMenu ); 4484 int idx = idxSelected != -1 ? idxSelected+1 : 0; // if duplicate mnemonics cycle through menu 4485 for( int i=0; i< nItemCount; i++, idx++ ) 4486 { 4487 WinSalMenuItem* pSalMenuItem = ImplGetSalMenuItem( hMenu, idx % nItemCount ); 4488 if( !pSalMenuItem ) 4489 continue; 4490 OUString aStr = pSalMenuItem->mText; 4491 aStr = aStr.toAsciiLowerCase(); 4492 if( aStr.indexOf( aMnemonic ) != -1 ) 4493 { 4494 if( idxFound == -1 ) 4495 idxFound = idx % nItemCount; 4496 if( nFound++ ) 4497 break; // duplicate found 4498 } 4499 } 4500 if( nFound == 1 ) 4501 nRet = MAKELRESULT( idxFound, MNC_EXECUTE ); 4502 else 4503 // duplicate mnemonics, just select the next occurrence 4504 nRet = MAKELRESULT( idxFound, MNC_SELECT ); 4505 4506 return nRet; 4507 } 4508 4509 static LRESULT ImplMeasureItem( HWND hWnd, WPARAM wParam, LPARAM lParam ) 4510 { 4511 LRESULT nRet = 0; 4512 if( !wParam ) 4513 { 4514 // request was sent by a menu 4515 nRet = 1; 4516 MEASUREITEMSTRUCT *pMI = reinterpret_cast<LPMEASUREITEMSTRUCT>(lParam); 4517 if( pMI->CtlType != ODT_MENU ) 4518 return 0; 4519 4520 WinSalMenuItem *pSalMenuItem = reinterpret_cast<WinSalMenuItem *>(pMI->itemData); 4521 if( !pSalMenuItem ) 4522 return 0; 4523 4524 HDC hdc = GetDC( hWnd ); 4525 SIZE strSize; 4526 4527 NONCLIENTMETRICSW ncm = {}; 4528 ncm.cbSize = sizeof( ncm ); 4529 SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0 ); 4530 4531 // Assume every menu item can be default and printed bold 4532 //ncm.lfMenuFont.lfWeight = FW_BOLD; 4533 4534 HFONT hfntOld = static_cast<HFONT>(SelectObject(hdc, CreateFontIndirectW( &ncm.lfMenuFont ))); 4535 4536 // menu text and accelerator 4537 OUString aStr(pSalMenuItem->mText); 4538 if( pSalMenuItem->mAccelText.getLength() ) 4539 { 4540 aStr += " " + pSalMenuItem->mAccelText; 4541 } 4542 GetTextExtentPoint32W( hdc, o3tl::toW(aStr.getStr()), 4543 aStr.getLength(), &strSize ); 4544 4545 // image 4546 Size bmpSize( 16, 16 ); 4547 //if( pSalMenuItem->maBitmap ) 4548 // bmpSize = pSalMenuItem->maBitmap.GetSizePixel(); 4549 4550 // checkmark 4551 Size checkSize( GetSystemMetrics( SM_CXMENUCHECK ), GetSystemMetrics( SM_CYMENUCHECK ) ); 4552 4553 pMI->itemWidth = checkSize.Width() + 3 + bmpSize.Width() + 3 + strSize.cx; 4554 pMI->itemHeight = std::max( std::max( checkSize.Height(), bmpSize.Height() ), tools::Long(strSize.cy) ); 4555 pMI->itemHeight += 4; 4556 4557 DeleteObject( SelectObject(hdc, hfntOld) ); 4558 ReleaseDC( hWnd, hdc ); 4559 } 4560 4561 return nRet; 4562 } 4563 4564 static LRESULT ImplDrawItem(HWND, WPARAM wParam, LPARAM lParam ) 4565 { 4566 LRESULT nRet = 0; 4567 if( !wParam ) 4568 { 4569 // request was sent by a menu 4570 nRet = 1; 4571 DRAWITEMSTRUCT *pDI = reinterpret_cast<LPDRAWITEMSTRUCT>(lParam); 4572 if( pDI->CtlType != ODT_MENU ) 4573 return 0; 4574 4575 WinSalMenuItem *pSalMenuItem = reinterpret_cast<WinSalMenuItem *>(pDI->itemData); 4576 if( !pSalMenuItem ) 4577 return 0; 4578 4579 COLORREF clrPrevText, clrPrevBkgnd; 4580 HFONT hfntOld; 4581 HBRUSH hbrOld; 4582 bool fChecked = (pDI->itemState & ODS_CHECKED); 4583 bool fSelected = (pDI->itemState & ODS_SELECTED); 4584 bool fDisabled = (pDI->itemState & (ODS_DISABLED | ODS_GRAYED)); 4585 4586 // Set the appropriate foreground and background colors. 4587 RECT aRect = pDI->rcItem; 4588 4589 if ( fDisabled ) 4590 clrPrevText = SetTextColor( pDI->hDC, GetSysColor( COLOR_GRAYTEXT ) ); 4591 else 4592 clrPrevText = SetTextColor( pDI->hDC, GetSysColor( fSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT ) ); 4593 4594 DWORD colBackground = GetSysColor( fSelected ? COLOR_HIGHLIGHT : COLOR_MENU ); 4595 clrPrevBkgnd = SetBkColor( pDI->hDC, colBackground ); 4596 4597 hbrOld = static_cast<HBRUSH>(SelectObject( pDI->hDC, CreateSolidBrush( GetBkColor( pDI->hDC ) ) )); 4598 4599 // Fill background 4600 if(!PatBlt( pDI->hDC, aRect.left, aRect.top, aRect.right-aRect.left, aRect.bottom-aRect.top, PATCOPY )) 4601 SAL_WARN("vcl", "PatBlt failed: " << WindowsErrorString(GetLastError())); 4602 4603 int lineHeight = aRect.bottom-aRect.top; 4604 4605 int x = aRect.left; 4606 int y = aRect.top; 4607 4608 int checkWidth = GetSystemMetrics( SM_CXMENUCHECK ); 4609 int checkHeight = GetSystemMetrics( SM_CYMENUCHECK ); 4610 if( fChecked ) 4611 { 4612 RECT r; 4613 r.left = 0; 4614 r.top = 0; 4615 r.right = checkWidth; 4616 r.bottom = checkWidth; 4617 HDC memDC = CreateCompatibleDC( pDI->hDC ); 4618 HBITMAP memBmp = CreateCompatibleBitmap( pDI->hDC, checkWidth, checkHeight ); 4619 HBITMAP hOldBmp = static_cast<HBITMAP>(SelectObject( memDC, memBmp )); 4620 DrawFrameControl( memDC, &r, DFC_MENU, DFCS_MENUCHECK ); 4621 BitBlt( pDI->hDC, x, y+(lineHeight-checkHeight)/2, checkWidth, checkHeight, memDC, 0, 0, SRCAND ); 4622 DeleteObject( SelectObject( memDC, hOldBmp ) ); 4623 DeleteDC( memDC ); 4624 } 4625 x += checkWidth+3; 4626 4627 //Size bmpSize = aBitmap.GetSizePixel(); 4628 Size bmpSize(16, 16); 4629 if( !pSalMenuItem->maBitmap.IsEmpty() ) 4630 { 4631 Bitmap aBitmap( pSalMenuItem->maBitmap ); 4632 4633 // set transparent pixels to background color 4634 if( fDisabled ) 4635 colBackground = RGB(255,255,255); 4636 aBitmap.Replace( COL_LIGHTMAGENTA, 4637 Color( GetRValue(colBackground),GetGValue(colBackground),GetBValue(colBackground) )); 4638 4639 WinSalBitmap* pSalBmp = static_cast<WinSalBitmap*>(aBitmap.ImplGetSalBitmap().get()); 4640 HGLOBAL hDrawDIB = pSalBmp->ImplGethDIB(); 4641 4642 if( hDrawDIB ) 4643 { 4644 PBITMAPINFO pBI = static_cast<PBITMAPINFO>(GlobalLock( hDrawDIB )); 4645 PBYTE pBits = reinterpret_cast<PBYTE>(pBI) + pBI->bmiHeader.biSize + 4646 WinSalBitmap::ImplGetDIBColorCount( hDrawDIB ) * sizeof( RGBQUAD ); 4647 4648 HBITMAP hBmp = CreateDIBitmap( pDI->hDC, &pBI->bmiHeader, CBM_INIT, pBits, pBI, DIB_RGB_COLORS ); 4649 GlobalUnlock( hDrawDIB ); 4650 4651 HBRUSH hbrIcon = CreateSolidBrush( GetSysColor( COLOR_GRAYTEXT ) ); 4652 DrawStateW( pDI->hDC, hbrIcon, nullptr, reinterpret_cast<LPARAM>(hBmp), WPARAM(0), 4653 x, y+(lineHeight-bmpSize.Height())/2, bmpSize.Width(), bmpSize.Height(), 4654 DST_BITMAP | (fDisabled ? (fSelected ? DSS_MONO : DSS_DISABLED) : DSS_NORMAL) ); 4655 4656 DeleteObject( hbrIcon ); 4657 DeleteObject( hBmp ); 4658 } 4659 4660 } 4661 x += bmpSize.Width() + 3; 4662 aRect.left = x; 4663 4664 NONCLIENTMETRICSW ncm = {}; 4665 ncm.cbSize = sizeof( ncm ); 4666 SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0 ); 4667 4668 // Print default menu entry with bold font 4669 //if ( pDI->itemState & ODS_DEFAULT ) 4670 // ncm.lfMenuFont.lfWeight = FW_BOLD; 4671 4672 hfntOld = static_cast<HFONT>(SelectObject(pDI->hDC, CreateFontIndirectW( &ncm.lfMenuFont ))); 4673 4674 SIZE strSize; 4675 OUString aStr( pSalMenuItem->mText ); 4676 GetTextExtentPoint32W( pDI->hDC, o3tl::toW(aStr.getStr()), 4677 aStr.getLength(), &strSize ); 4678 4679 if(!DrawStateW( pDI->hDC, nullptr, nullptr, 4680 reinterpret_cast<LPARAM>(aStr.getStr()), 4681 WPARAM(0), aRect.left, aRect.top + (lineHeight - strSize.cy)/2, 0, 0, 4682 DST_PREFIXTEXT | (fDisabled && !fSelected ? DSS_DISABLED : DSS_NORMAL) ) ) 4683 SAL_WARN("vcl", "DrawStateW failed: " << WindowsErrorString(GetLastError())); 4684 4685 if( pSalMenuItem->mAccelText.getLength() ) 4686 { 4687 SIZE strSizeA; 4688 aStr = pSalMenuItem->mAccelText; 4689 GetTextExtentPoint32W( pDI->hDC, o3tl::toW(aStr.getStr()), 4690 aStr.getLength(), &strSizeA ); 4691 TEXTMETRICW tm; 4692 GetTextMetricsW( pDI->hDC, &tm ); 4693 4694 // position the accelerator string to the right but leave space for the 4695 // (potential) submenu arrow (tm.tmMaxCharWidth) 4696 if(!DrawStateW( pDI->hDC, nullptr, nullptr, 4697 reinterpret_cast<LPARAM>(aStr.getStr()), 4698 WPARAM(0), aRect.right-strSizeA.cx-tm.tmMaxCharWidth, aRect.top + (lineHeight - strSizeA.cy)/2, 0, 0, 4699 DST_TEXT | (fDisabled && !fSelected ? DSS_DISABLED : DSS_NORMAL) ) ) 4700 SAL_WARN("vcl", "DrawStateW failed: " << WindowsErrorString(GetLastError())); 4701 } 4702 4703 // Restore the original font and colors. 4704 DeleteObject( SelectObject( pDI->hDC, hbrOld ) ); 4705 DeleteObject( SelectObject( pDI->hDC, hfntOld) ); 4706 SetTextColor(pDI->hDC, clrPrevText); 4707 SetBkColor(pDI->hDC, clrPrevBkgnd); 4708 } 4709 return nRet; 4710 } 4711 4712 static bool ImplHandleMenuActivate( HWND hWnd, WPARAM wParam, LPARAM ) 4713 { 4714 // Menu activation 4715 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 4716 if ( !pFrame ) 4717 return false; 4718 4719 HMENU hMenu = reinterpret_cast<HMENU>(wParam); 4720 // WORD nPos = LOWORD (lParam); 4721 // bool bWindowMenu = (bool) HIWORD(lParam); 4722 4723 // Send activate and deactivate together, so we have not keep track of opened menus 4724 // this will be enough to have the menus updated correctly 4725 SalMenuEvent aMenuEvt; 4726 WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( hMenu, 0 ); 4727 if( pSalMenuItem ) 4728 aMenuEvt.mpMenu = pSalMenuItem->mpMenu; 4729 else 4730 aMenuEvt.mpMenu = nullptr; 4731 4732 bool nRet = pFrame->CallCallback( SalEvent::MenuActivate, &aMenuEvt ); 4733 if( nRet ) 4734 nRet = pFrame->CallCallback( SalEvent::MenuDeactivate, &aMenuEvt ); 4735 if( nRet ) 4736 pFrame->mLastActivatedhMenu = hMenu; 4737 4738 return nRet; 4739 } 4740 4741 static bool ImplHandleMenuSelect( HWND hWnd, WPARAM wParam, LPARAM lParam ) 4742 { 4743 // Menu selection 4744 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 4745 if ( !pFrame ) 4746 return false; 4747 4748 WORD nId = LOWORD(wParam); // menu item or submenu index 4749 WORD nFlags = HIWORD(wParam); 4750 HMENU hMenu = reinterpret_cast<HMENU>(lParam); 4751 4752 // check if we have to process the message 4753 if( !GetSalData()->IsKnownMenuHandle( hMenu ) ) 4754 return false; 4755 4756 bool bByPosition = false; 4757 if( nFlags & MF_POPUP ) 4758 bByPosition = true; 4759 4760 bool nRet = false; 4761 if ( hMenu && !pFrame->mLastActivatedhMenu ) 4762 { 4763 // we never activated a menu (ie, no WM_INITMENUPOPUP has occurred yet) 4764 // which means this must be the menubar -> send activation/deactivation 4765 SalMenuEvent aMenuEvt; 4766 WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( hMenu, nId, bByPosition ); 4767 if( pSalMenuItem ) 4768 aMenuEvt.mpMenu = pSalMenuItem->mpMenu; 4769 else 4770 aMenuEvt.mpMenu = nullptr; 4771 4772 nRet = pFrame->CallCallback( SalEvent::MenuActivate, &aMenuEvt ); 4773 if( nRet ) 4774 nRet = pFrame->CallCallback( SalEvent::MenuDeactivate, &aMenuEvt ); 4775 if( nRet ) 4776 pFrame->mLastActivatedhMenu = hMenu; 4777 } 4778 4779 if( !hMenu && nFlags == 0xFFFF ) 4780 { 4781 // all menus are closed, reset activation logic 4782 pFrame->mLastActivatedhMenu = nullptr; 4783 } 4784 4785 if( hMenu ) 4786 { 4787 // hMenu must be saved, as it is not passed in WM_COMMAND which always occurs after a selection 4788 // if a menu is closed due to a command selection then hMenu is NULL, but WM_COMMAND comes later 4789 // so we must not overwrite it in this case 4790 pFrame->mSelectedhMenu = hMenu; 4791 4792 // send highlight event 4793 if( nFlags & MF_POPUP ) 4794 { 4795 // submenu selected 4796 // wParam now carries an index instead of an id -> retrieve id 4797 MENUITEMINFOW mi = {}; 4798 mi.cbSize = sizeof( mi ); 4799 mi.fMask = MIIM_ID; 4800 if( GetMenuItemInfoW( hMenu, LOWORD(wParam), TRUE, &mi) ) 4801 nId = sal::static_int_cast<WORD>(mi.wID); 4802 } 4803 4804 SalMenuEvent aMenuEvt; 4805 aMenuEvt.mnId = nId; 4806 WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( hMenu, nId, false ); 4807 if( pSalMenuItem ) 4808 aMenuEvt.mpMenu = pSalMenuItem->mpMenu; 4809 else 4810 aMenuEvt.mpMenu = nullptr; 4811 4812 nRet = pFrame->CallCallback( SalEvent::MenuHighlight, &aMenuEvt ); 4813 } 4814 4815 return nRet; 4816 } 4817 4818 static bool ImplHandleCommand( HWND hWnd, WPARAM wParam, LPARAM ) 4819 { 4820 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 4821 if ( !pFrame ) 4822 return false; 4823 4824 bool nRet = false; 4825 if( !HIWORD(wParam) ) 4826 { 4827 // Menu command 4828 WORD nId = LOWORD(wParam); 4829 if( nId ) // zero for separators 4830 { 4831 SalMenuEvent aMenuEvt; 4832 aMenuEvt.mnId = nId; 4833 WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( pFrame->mSelectedhMenu, nId, false ); 4834 if( pSalMenuItem ) 4835 aMenuEvt.mpMenu = pSalMenuItem->mpMenu; 4836 else 4837 aMenuEvt.mpMenu = nullptr; 4838 4839 nRet = pFrame->CallCallback( SalEvent::MenuCommand, &aMenuEvt ); 4840 } 4841 } 4842 return nRet; 4843 } 4844 4845 static bool ImplHandleSysCommand( HWND hWnd, WPARAM wParam, LPARAM lParam ) 4846 { 4847 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 4848 if ( !pFrame ) 4849 return false; 4850 4851 WPARAM nCommand = wParam & 0xFFF0; 4852 4853 if (pFrame->isFullScreen()) 4854 { 4855 bool bMaximize = IsZoomed( pFrame->mhWnd ); 4856 bool bMinimize = IsIconic( pFrame->mhWnd ); 4857 if ( (nCommand == SC_SIZE) || 4858 (!bMinimize && (nCommand == SC_MOVE)) || 4859 (!bMaximize && (nCommand == SC_MAXIMIZE)) || 4860 (bMaximize && (nCommand == SC_RESTORE)) ) 4861 { 4862 return true; 4863 } 4864 } 4865 4866 if ( nCommand == SC_MOVE ) 4867 { 4868 WinSalTimer* pTimer = static_cast<WinSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer ); 4869 if ( pTimer ) 4870 pTimer->SetForceRealTimer( true ); 4871 } 4872 4873 if ( nCommand == SC_KEYMENU ) 4874 { 4875 // do not process SC_KEYMENU if we have a native menu 4876 // Windows should handle this 4877 if( GetMenu( hWnd ) ) 4878 return false; 4879 4880 // Process here KeyMenu events only for Alt to activate the MenuBar, 4881 // or if a SysChild window is in focus, as Alt-key-combinations are 4882 // only processed via this event 4883 if ( !LOWORD( lParam ) ) 4884 { 4885 // Only trigger if no other key is pressed. 4886 // Contrary to Docu the CharCode is delivered with the x-coordinate 4887 // that is pressed in addition. 4888 // Also 32 for space, 99 for c, 100 for d, ... 4889 // As this is not documented, we check the state of the space-bar 4890 if ( GetKeyState( VK_SPACE ) & 0x8000 ) 4891 return false; 4892 4893 // to avoid activating the MenuBar for Alt+MouseKey 4894 if ( (GetKeyState( VK_LBUTTON ) & 0x8000) || 4895 (GetKeyState( VK_RBUTTON ) & 0x8000) || 4896 (GetKeyState( VK_MBUTTON ) & 0x8000) || 4897 (GetKeyState( VK_SHIFT ) & 0x8000) ) 4898 return true; 4899 4900 SalKeyEvent aKeyEvt; 4901 aKeyEvt.mnCode = KEY_MENU; 4902 aKeyEvt.mnCharCode = 0; 4903 aKeyEvt.mnRepeat = 0; 4904 bool nRet = pFrame->CallCallback( SalEvent::KeyInput, &aKeyEvt ); 4905 pFrame->CallCallback( SalEvent::KeyUp, &aKeyEvt ); 4906 return nRet; 4907 } 4908 else 4909 { 4910 // check if a SysChild is in focus 4911 HWND hFocusWnd = ::GetFocus(); 4912 if ( hFocusWnd && ImplFindSalObject( hFocusWnd ) ) 4913 { 4914 char cKeyCode = static_cast<char>(static_cast<unsigned char>(LOWORD( lParam ))); 4915 // LowerCase 4916 if ( (cKeyCode >= 65) && (cKeyCode <= 90) ) 4917 cKeyCode += 32; 4918 // We only accept 0-9 and A-Z; all other keys have to be 4919 // processed by the SalObj hook 4920 if ( ((cKeyCode >= 48) && (cKeyCode <= 57)) || 4921 ((cKeyCode >= 97) && (cKeyCode <= 122)) ) 4922 { 4923 sal_uInt16 nModCode = 0; 4924 if ( GetKeyState( VK_SHIFT ) & 0x8000 ) 4925 nModCode |= KEY_SHIFT; 4926 if ( GetKeyState( VK_CONTROL ) & 0x8000 ) 4927 nModCode |= KEY_MOD1; 4928 nModCode |= KEY_MOD2; 4929 4930 SalKeyEvent aKeyEvt; 4931 if ( (cKeyCode >= 48) && (cKeyCode <= 57) ) 4932 aKeyEvt.mnCode = KEY_0+(cKeyCode-48); 4933 else 4934 aKeyEvt.mnCode = KEY_A+(cKeyCode-97); 4935 aKeyEvt.mnCode |= nModCode; 4936 aKeyEvt.mnCharCode = cKeyCode; 4937 aKeyEvt.mnRepeat = 0; 4938 bool nRet = pFrame->CallCallback( SalEvent::KeyInput, &aKeyEvt ); 4939 pFrame->CallCallback( SalEvent::KeyUp, &aKeyEvt ); 4940 return nRet; 4941 } 4942 } 4943 } 4944 } 4945 4946 return false; 4947 } 4948 4949 static void ImplHandleInputLangChange( HWND hWnd, WPARAM, LPARAM lParam ) 4950 { 4951 ImplSalYieldMutexAcquireWithWait(); 4952 4953 // check if we support IME 4954 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 4955 4956 if ( !pFrame ) 4957 return; 4958 4959 if ( pFrame->mbIME && pFrame->mhDefIMEContext ) 4960 { 4961 HKL hKL = reinterpret_cast<HKL>(lParam); 4962 UINT nImeProps = ImmGetProperty( hKL, IGP_PROPERTY ); 4963 4964 pFrame->mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0; 4965 pFrame->mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0; 4966 pFrame->mbHandleIME = !pFrame->mbSpezIME; 4967 } 4968 4969 // trigger input language and codepage update 4970 UINT nLang = pFrame->mnInputLang; 4971 ImplUpdateInputLang( pFrame ); 4972 4973 // notify change 4974 if( nLang != pFrame->mnInputLang ) 4975 pFrame->CallCallback( SalEvent::InputLanguageChange, nullptr ); 4976 4977 // reinit spec. keys 4978 GetSalData()->initKeyCodeMap(); 4979 4980 ImplSalYieldMutexRelease(); 4981 } 4982 4983 static void ImplUpdateIMECursorPos( WinSalFrame* pFrame, HIMC hIMC ) 4984 { 4985 COMPOSITIONFORM aForm = {}; 4986 4987 // get cursor position and from it calculate default position 4988 // for the composition window 4989 SalExtTextInputPosEvent aPosEvt; 4990 pFrame->CallCallback( SalEvent::ExtTextInputPos, &aPosEvt ); 4991 if ( (aPosEvt.mnX == -1) && (aPosEvt.mnY == -1) ) 4992 aForm.dwStyle |= CFS_DEFAULT; 4993 else 4994 { 4995 aForm.dwStyle |= CFS_POINT; 4996 aForm.ptCurrentPos.x = aPosEvt.mnX; 4997 aForm.ptCurrentPos.y = aPosEvt.mnY; 4998 } 4999 ImmSetCompositionWindow( hIMC, &aForm ); 5000 5001 // Because not all IME's use this values, we create 5002 // a Windows caret to force the Position from the IME 5003 if ( GetFocus() == pFrame->mhWnd ) 5004 { 5005 CreateCaret( pFrame->mhWnd, nullptr, 5006 aPosEvt.mnWidth, aPosEvt.mnHeight ); 5007 SetCaretPos( aPosEvt.mnX, aPosEvt.mnY ); 5008 } 5009 } 5010 5011 static bool ImplHandleIMEStartComposition( HWND hWnd ) 5012 { 5013 bool bDef = true; 5014 5015 ImplSalYieldMutexAcquireWithWait(); 5016 5017 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 5018 if ( pFrame ) 5019 { 5020 HIMC hIMC = ImmGetContext( hWnd ); 5021 if ( hIMC ) 5022 { 5023 ImplUpdateIMECursorPos( pFrame, hIMC ); 5024 ImmReleaseContext( hWnd, hIMC ); 5025 } 5026 5027 if ( pFrame->mbHandleIME ) 5028 { 5029 if ( pFrame->mbAtCursorIME ) 5030 bDef = false; 5031 } 5032 } 5033 5034 ImplSalYieldMutexRelease(); 5035 5036 return bDef; 5037 } 5038 5039 static bool ImplHandleIMECompositionInput( WinSalFrame* pFrame, 5040 HIMC hIMC, LPARAM lParam ) 5041 { 5042 bool bDef = true; 5043 5044 // Init Event 5045 SalExtTextInputEvent aEvt; 5046 aEvt.mpTextAttr = nullptr; 5047 aEvt.mnCursorPos = 0; 5048 aEvt.mnCursorFlags = 0; 5049 5050 // If we get a result string, then we handle this input 5051 if ( lParam & GCS_RESULTSTR ) 5052 { 5053 bDef = false; 5054 5055 LONG nTextLen = ImmGetCompositionStringW( hIMC, GCS_RESULTSTR, nullptr, 0 ) / sizeof( WCHAR ); 5056 if ( nTextLen >= 0 ) 5057 { 5058 auto pTextBuf = std::make_unique<WCHAR[]>(nTextLen); 5059 ImmGetCompositionStringW( hIMC, GCS_RESULTSTR, pTextBuf.get(), nTextLen*sizeof( WCHAR ) ); 5060 aEvt.maText = OUString( o3tl::toU(pTextBuf.get()), static_cast<sal_Int32>(nTextLen) ); 5061 } 5062 5063 aEvt.mnCursorPos = aEvt.maText.getLength(); 5064 pFrame->CallCallback( SalEvent::ExtTextInput, &aEvt ); 5065 pFrame->CallCallback( SalEvent::EndExtTextInput, nullptr ); 5066 ImplUpdateIMECursorPos( pFrame, hIMC ); 5067 } 5068 5069 // If the IME doesn't support OnSpot input, then there is nothing to do 5070 if ( !pFrame->mbAtCursorIME ) 5071 return !bDef; 5072 5073 // If we get new Composition data, then we handle this new input 5074 if ( (lParam & (GCS_COMPSTR | GCS_COMPATTR)) || 5075 ((lParam & GCS_CURSORPOS) && !(lParam & GCS_RESULTSTR)) ) 5076 { 5077 bDef = false; 5078 5079 std::unique_ptr<ExtTextInputAttr[]> pSalAttrAry; 5080 LONG nTextLen = ImmGetCompositionStringW( hIMC, GCS_COMPSTR, nullptr, 0 ) / sizeof( WCHAR ); 5081 if ( nTextLen > 0 ) 5082 { 5083 { 5084 auto pTextBuf = std::make_unique<WCHAR[]>(nTextLen); 5085 ImmGetCompositionStringW( hIMC, GCS_COMPSTR, pTextBuf.get(), nTextLen*sizeof( WCHAR ) ); 5086 aEvt.maText = OUString( o3tl::toU(pTextBuf.get()), static_cast<sal_Int32>(nTextLen) ); 5087 } 5088 5089 std::unique_ptr<BYTE[]> pAttrBuf; 5090 LONG nAttrLen = ImmGetCompositionStringW( hIMC, GCS_COMPATTR, nullptr, 0 ); 5091 if ( nAttrLen > 0 ) 5092 { 5093 pAttrBuf.reset(new BYTE[nAttrLen]); 5094 ImmGetCompositionStringW( hIMC, GCS_COMPATTR, pAttrBuf.get(), nAttrLen ); 5095 } 5096 5097 if ( pAttrBuf ) 5098 { 5099 sal_Int32 nTextLen2 = aEvt.maText.getLength(); 5100 pSalAttrAry.reset(new ExtTextInputAttr[nTextLen2]); 5101 memset( pSalAttrAry.get(), 0, nTextLen2*sizeof( sal_uInt16 ) ); 5102 for( sal_Int32 i = 0; (i < nTextLen2) && (i < nAttrLen); i++ ) 5103 { 5104 BYTE nWinAttr = pAttrBuf.get()[i]; 5105 ExtTextInputAttr nSalAttr; 5106 if ( nWinAttr == ATTR_TARGET_CONVERTED ) 5107 { 5108 nSalAttr = ExtTextInputAttr::BoldUnderline; 5109 aEvt.mnCursorFlags |= EXTTEXTINPUT_CURSOR_INVISIBLE; 5110 } 5111 else if ( nWinAttr == ATTR_CONVERTED ) 5112 nSalAttr = ExtTextInputAttr::DashDotUnderline; 5113 else if ( nWinAttr == ATTR_TARGET_NOTCONVERTED ) 5114 nSalAttr = ExtTextInputAttr::Highlight; 5115 else if ( nWinAttr == ATTR_INPUT_ERROR ) 5116 nSalAttr = ExtTextInputAttr::RedText | ExtTextInputAttr::DottedUnderline; 5117 else /* ( nWinAttr == ATTR_INPUT ) */ 5118 nSalAttr = ExtTextInputAttr::DottedUnderline; 5119 pSalAttrAry[i] = nSalAttr; 5120 } 5121 5122 aEvt.mpTextAttr = pSalAttrAry.get(); 5123 } 5124 } 5125 5126 // Only when we get new composition data, we must send this event 5127 if ( (nTextLen > 0) || !(lParam & GCS_RESULTSTR) ) 5128 { 5129 // End the mode, if the last character is deleted 5130 if ( !nTextLen ) 5131 { 5132 pFrame->CallCallback( SalEvent::ExtTextInput, &aEvt ); 5133 pFrame->CallCallback( SalEvent::EndExtTextInput, nullptr ); 5134 } 5135 else 5136 { 5137 // Because Cursor-Position and DeltaStart never updated 5138 // from the korean input engine, we must handle this here 5139 if ( lParam & CS_INSERTCHAR ) 5140 { 5141 aEvt.mnCursorPos = nTextLen; 5142 if ( aEvt.mnCursorPos && (lParam & CS_NOMOVECARET) ) 5143 aEvt.mnCursorPos--; 5144 } 5145 else 5146 aEvt.mnCursorPos = LOWORD( ImmGetCompositionStringW( hIMC, GCS_CURSORPOS, nullptr, 0 ) ); 5147 5148 if ( pFrame->mbCandidateMode ) 5149 aEvt.mnCursorFlags |= EXTTEXTINPUT_CURSOR_INVISIBLE; 5150 if ( lParam & CS_NOMOVECARET ) 5151 aEvt.mnCursorFlags |= EXTTEXTINPUT_CURSOR_OVERWRITE; 5152 5153 pFrame->CallCallback( SalEvent::ExtTextInput, &aEvt ); 5154 } 5155 ImplUpdateIMECursorPos( pFrame, hIMC ); 5156 } 5157 } 5158 5159 return !bDef; 5160 } 5161 5162 static bool ImplHandleIMEComposition( HWND hWnd, LPARAM lParam ) 5163 { 5164 bool bDef = true; 5165 ImplSalYieldMutexAcquireWithWait(); 5166 5167 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 5168 if ( pFrame && (!lParam || (lParam & GCS_RESULTSTR)) ) 5169 { 5170 // reset the background mode for each text input, 5171 // as some tools such as RichWin may have changed it 5172 if ( pFrame->mpLocalGraphics && 5173 pFrame->mpLocalGraphics->getHDC() ) 5174 SetBkMode( pFrame->mpLocalGraphics->getHDC(), TRANSPARENT ); 5175 } 5176 5177 if ( pFrame && pFrame->mbHandleIME ) 5178 { 5179 if ( !lParam ) 5180 { 5181 SalExtTextInputEvent aEvt; 5182 aEvt.mpTextAttr = nullptr; 5183 aEvt.mnCursorPos = 0; 5184 aEvt.mnCursorFlags = 0; 5185 pFrame->CallCallback( SalEvent::ExtTextInput, &aEvt ); 5186 pFrame->CallCallback( SalEvent::EndExtTextInput, nullptr ); 5187 } 5188 else if ( lParam & (GCS_RESULTSTR | GCS_COMPSTR | GCS_COMPATTR | GCS_CURSORPOS) ) 5189 { 5190 HIMC hIMC = ImmGetContext( hWnd ); 5191 if ( hIMC ) 5192 { 5193 if ( ImplHandleIMECompositionInput( pFrame, hIMC, lParam ) ) 5194 bDef = false; 5195 5196 ImmReleaseContext( hWnd, hIMC ); 5197 } 5198 } 5199 } 5200 5201 ImplSalYieldMutexRelease(); 5202 return bDef; 5203 } 5204 5205 static bool ImplHandleIMEEndComposition( HWND hWnd ) 5206 { 5207 bool bDef = true; 5208 5209 ImplSalYieldMutexAcquireWithWait(); 5210 5211 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 5212 if ( pFrame && pFrame->mbHandleIME ) 5213 { 5214 if ( pFrame->mbAtCursorIME ) 5215 { 5216 pFrame->mbCandidateMode = false; 5217 bDef = false; 5218 } 5219 } 5220 5221 ImplSalYieldMutexRelease(); 5222 5223 return bDef; 5224 } 5225 5226 static bool ImplHandleAppCommand( HWND hWnd, LPARAM lParam, LRESULT & nRet ) 5227 { 5228 MediaCommand nCommand; 5229 switch( GET_APPCOMMAND_LPARAM(lParam) ) 5230 { 5231 case APPCOMMAND_MEDIA_CHANNEL_DOWN: nCommand = MediaCommand::ChannelDown; break; 5232 case APPCOMMAND_MEDIA_CHANNEL_UP: nCommand = MediaCommand::ChannelUp; break; 5233 case APPCOMMAND_MEDIA_NEXTTRACK: nCommand = MediaCommand::NextTrack; break; 5234 case APPCOMMAND_MEDIA_PAUSE: nCommand = MediaCommand::Pause; break; 5235 case APPCOMMAND_MEDIA_PLAY: nCommand = MediaCommand::Play; break; 5236 case APPCOMMAND_MEDIA_PLAY_PAUSE: nCommand = MediaCommand::PlayPause; break; 5237 case APPCOMMAND_MEDIA_PREVIOUSTRACK: nCommand = MediaCommand::PreviousTrack; break; 5238 case APPCOMMAND_MEDIA_RECORD: nCommand = MediaCommand::Record; break; 5239 case APPCOMMAND_MEDIA_REWIND: nCommand = MediaCommand::Rewind; break; 5240 case APPCOMMAND_MEDIA_STOP: nCommand = MediaCommand::Stop; break; 5241 case APPCOMMAND_MIC_ON_OFF_TOGGLE: nCommand = MediaCommand::MicOnOffToggle; break; 5242 case APPCOMMAND_MICROPHONE_VOLUME_DOWN: nCommand = MediaCommand::MicrophoneVolumeDown; break; 5243 case APPCOMMAND_MICROPHONE_VOLUME_MUTE: nCommand = MediaCommand::MicrophoneVolumeMute; break; 5244 case APPCOMMAND_MICROPHONE_VOLUME_UP: nCommand = MediaCommand::MicrophoneVolumeUp; break; 5245 case APPCOMMAND_VOLUME_DOWN: nCommand = MediaCommand::VolumeDown; break; 5246 case APPCOMMAND_VOLUME_MUTE: nCommand = MediaCommand::VolumeMute; break; 5247 case APPCOMMAND_VOLUME_UP: nCommand = MediaCommand::VolumeUp; break; 5248 default: 5249 return false; 5250 } 5251 5252 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 5253 vcl::Window *pWindow = pFrame ? pFrame->GetWindow() : nullptr; 5254 5255 if( pWindow ) 5256 { 5257 const Point aPoint; 5258 CommandMediaData aMediaData(nCommand); 5259 CommandEvent aCEvt( aPoint, CommandEventId::Media, false, &aMediaData ); 5260 NotifyEvent aNCmdEvt( NotifyEventType::COMMAND, pWindow, &aCEvt ); 5261 5262 if ( !ImplCallPreNotify( aNCmdEvt ) ) 5263 { 5264 pWindow->Command( aCEvt ); 5265 nRet = 1; 5266 return !aMediaData.GetPassThroughToOS(); 5267 } 5268 } 5269 5270 return false; 5271 } 5272 5273 static void ImplHandleIMENotify( HWND hWnd, WPARAM wParam ) 5274 { 5275 if ( wParam == WPARAM(IMN_OPENCANDIDATE) ) 5276 { 5277 ImplSalYieldMutexAcquireWithWait(); 5278 5279 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 5280 if ( pFrame && pFrame->mbHandleIME && 5281 pFrame->mbAtCursorIME ) 5282 { 5283 // we want to hide the cursor 5284 pFrame->mbCandidateMode = true; 5285 ImplHandleIMEComposition( hWnd, GCS_CURSORPOS ); 5286 5287 HWND hWnd2 = pFrame->mhWnd; 5288 HIMC hIMC = ImmGetContext( hWnd2 ); 5289 if ( hIMC ) 5290 { 5291 LONG nBufLen = ImmGetCompositionStringW( hIMC, GCS_COMPSTR, nullptr, 0 ); 5292 if ( nBufLen >= 1 ) 5293 { 5294 SalExtTextInputPosEvent aPosEvt; 5295 pFrame->CallCallback( SalEvent::ExtTextInputPos, &aPosEvt ); 5296 5297 // Vertical !!! 5298 CANDIDATEFORM aForm; 5299 aForm.dwIndex = 0; 5300 aForm.dwStyle = CFS_EXCLUDE; 5301 aForm.ptCurrentPos.x = aPosEvt.mnX; 5302 aForm.ptCurrentPos.y = aPosEvt.mnY+1; 5303 aForm.rcArea.left = aPosEvt.mnX; 5304 aForm.rcArea.top = aPosEvt.mnY; 5305 aForm.rcArea.right = aForm.rcArea.left+aPosEvt.mnExtWidth+1; 5306 aForm.rcArea.bottom = aForm.rcArea.top+aPosEvt.mnHeight+1; 5307 ImmSetCandidateWindow( hIMC, &aForm ); 5308 } 5309 5310 ImmReleaseContext( hWnd2, hIMC ); 5311 } 5312 } 5313 5314 ImplSalYieldMutexRelease(); 5315 } 5316 else if ( wParam == WPARAM(IMN_CLOSECANDIDATE) ) 5317 { 5318 ImplSalYieldMutexAcquireWithWait(); 5319 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 5320 if ( pFrame ) 5321 pFrame->mbCandidateMode = false; 5322 ImplSalYieldMutexRelease(); 5323 } 5324 } 5325 5326 static bool 5327 ImplHandleGetObject(HWND hWnd, LPARAM lParam, WPARAM wParam, LRESULT & nRet) 5328 { 5329 if (!Application::GetSettings().GetMiscSettings().GetEnableATToolSupport()) 5330 { 5331 // IA2 should be enabled automatically 5332 AllSettings aSettings = Application::GetSettings(); 5333 MiscSettings aMisc = aSettings.GetMiscSettings(); 5334 aMisc.SetEnableATToolSupport(true); 5335 // The above is enough, since aMisc changes the same shared ImplMiscData as used in global 5336 // settings, so no need to call aSettings.SetMiscSettings and Application::SetSettings 5337 5338 if (!Application::GetSettings().GetMiscSettings().GetEnableATToolSupport()) 5339 return false; // locked down somehow ? 5340 } 5341 5342 ImplSVData* pSVData = ImplGetSVData(); 5343 5344 // Make sure to launch Accessibility only the following criteria are satisfied 5345 // to avoid RFT interrupts regular accessibility processing 5346 if ( !pSVData->mxAccessBridge.is() ) 5347 { 5348 if( !InitAccessBridge() ) 5349 return false; 5350 } 5351 5352 uno::Reference< accessibility::XMSAAService > xMSAA( pSVData->mxAccessBridge, uno::UNO_QUERY ); 5353 if ( xMSAA.is() ) 5354 { 5355 sal_Int32 lParam32 = static_cast<sal_Int32>(lParam); 5356 sal_uInt32 wParam32 = static_cast<sal_uInt32>(wParam); 5357 5358 // mhOnSetTitleWnd not set to reasonable value anywhere... 5359 if ( lParam32 == OBJID_CLIENT ) 5360 { 5361 nRet = xMSAA->getAccObjectPtr( 5362 reinterpret_cast<sal_Int64>(hWnd), lParam32, wParam32); 5363 if (nRet != 0) 5364 return true; 5365 } 5366 } 5367 return false; 5368 } 5369 5370 static LRESULT ImplHandleIMEReconvertString( HWND hWnd, LPARAM lParam ) 5371 { 5372 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 5373 LPRECONVERTSTRING pReconvertString = reinterpret_cast<LPRECONVERTSTRING>(lParam); 5374 LRESULT nRet = 0; 5375 SalSurroundingTextRequestEvent aEvt; 5376 aEvt.maText.clear(); 5377 aEvt.mnStart = aEvt.mnEnd = 0; 5378 5379 UINT nImeProps = ImmGetProperty( GetKeyboardLayout( 0 ), IGP_SETCOMPSTR ); 5380 if( (nImeProps & SCS_CAP_SETRECONVERTSTRING) == 0 ) 5381 { 5382 // This IME does not support reconversion. 5383 return 0; 5384 } 5385 5386 if( !pReconvertString ) 5387 { 5388 // The first call for reconversion. 5389 pFrame->CallCallback( SalEvent::StartReconversion, nullptr ); 5390 5391 // Retrieve the surrounding text from the focused control. 5392 pFrame->CallCallback( SalEvent::SurroundingTextRequest, &aEvt ); 5393 5394 if( aEvt.maText.isEmpty()) 5395 { 5396 return 0; 5397 } 5398 5399 nRet = sizeof(RECONVERTSTRING) + (aEvt.maText.getLength() + 1) * sizeof(WCHAR); 5400 } 5401 else 5402 { 5403 // The second call for reconversion. 5404 5405 // Retrieve the surrounding text from the focused control. 5406 pFrame->CallCallback( SalEvent::SurroundingTextRequest, &aEvt ); 5407 nRet = sizeof(RECONVERTSTRING) + (aEvt.maText.getLength() + 1) * sizeof(WCHAR); 5408 5409 pReconvertString->dwStrOffset = sizeof(RECONVERTSTRING); 5410 pReconvertString->dwStrLen = aEvt.maText.getLength(); 5411 pReconvertString->dwCompStrOffset = aEvt.mnStart * sizeof(WCHAR); 5412 pReconvertString->dwCompStrLen = aEvt.mnEnd - aEvt.mnStart; 5413 pReconvertString->dwTargetStrOffset = pReconvertString->dwCompStrOffset; 5414 pReconvertString->dwTargetStrLen = pReconvertString->dwCompStrLen; 5415 5416 memcpy( pReconvertString + 1, aEvt.maText.getStr(), (aEvt.maText.getLength() + 1) * sizeof(WCHAR) ); 5417 } 5418 5419 // just return the required size of buffer to reconvert. 5420 return nRet; 5421 } 5422 5423 static LRESULT ImplHandleIMEConfirmReconvertString( HWND hWnd, LPARAM lParam ) 5424 { 5425 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 5426 LPRECONVERTSTRING pReconvertString = reinterpret_cast<LPRECONVERTSTRING>(lParam); 5427 SalSurroundingTextRequestEvent aEvt; 5428 aEvt.maText.clear(); 5429 aEvt.mnStart = aEvt.mnEnd = 0; 5430 5431 pFrame->CallCallback( SalEvent::SurroundingTextRequest, &aEvt ); 5432 5433 sal_uLong nTmpStart = pReconvertString->dwCompStrOffset / sizeof(WCHAR); 5434 sal_uLong nTmpEnd = nTmpStart + pReconvertString->dwCompStrLen; 5435 5436 if( nTmpStart != aEvt.mnStart || nTmpEnd != aEvt.mnEnd ) 5437 { 5438 SalSurroundingTextSelectionChangeEvent aSelEvt { nTmpStart, nTmpEnd }; 5439 pFrame->CallCallback( SalEvent::SurroundingTextSelectionChange, &aSelEvt ); 5440 } 5441 5442 return TRUE; 5443 } 5444 5445 static LRESULT ImplHandleIMEQueryCharPosition( HWND hWnd, LPARAM lParam ) { 5446 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 5447 PIMECHARPOSITION pQueryCharPosition = reinterpret_cast<PIMECHARPOSITION>(lParam); 5448 if ( pQueryCharPosition->dwSize < sizeof(IMECHARPOSITION) ) 5449 return FALSE; 5450 5451 SalQueryCharPositionEvent aEvt; 5452 aEvt.mbValid = false; 5453 aEvt.mnCharPos = pQueryCharPosition->dwCharPos; 5454 5455 pFrame->CallCallback( SalEvent::QueryCharPosition, &aEvt ); 5456 5457 if ( !aEvt.mbValid ) 5458 return FALSE; 5459 5460 if ( aEvt.mbVertical ) 5461 { 5462 // For vertical writing, the base line is left edge of the rectangle 5463 // and the target position is top-right corner. 5464 pQueryCharPosition->pt.x = aEvt.mnCursorBoundX + aEvt.mnCursorBoundWidth; 5465 pQueryCharPosition->pt.y = aEvt.mnCursorBoundY; 5466 pQueryCharPosition->cLineHeight = aEvt.mnCursorBoundWidth; 5467 } 5468 else 5469 { 5470 // For horizontal writing, the base line is the bottom edge of the rectangle. 5471 // and the target position is top-left corner. 5472 pQueryCharPosition->pt.x = aEvt.mnCursorBoundX; 5473 pQueryCharPosition->pt.y = aEvt.mnCursorBoundY; 5474 pQueryCharPosition->cLineHeight = aEvt.mnCursorBoundHeight; 5475 } 5476 5477 // Currently not supported but many IMEs usually ignore them. 5478 pQueryCharPosition->rcDocument.left = 0; 5479 pQueryCharPosition->rcDocument.top = 0; 5480 pQueryCharPosition->rcDocument.right = 0; 5481 pQueryCharPosition->rcDocument.bottom = 0; 5482 5483 return TRUE; 5484 } 5485 5486 void SalTestMouseLeave() 5487 { 5488 SalData* pSalData = GetSalData(); 5489 5490 if ( pSalData->mhWantLeaveMsg && !::GetCapture() ) 5491 { 5492 POINT aPt; 5493 GetCursorPos( &aPt ); 5494 5495 // a one item cache, because this function is sometimes hot - if the cursor has not moved, then 5496 // no need to call WindowFromPoint 5497 static POINT cachedPoint; 5498 if (cachedPoint.x == aPt.x && cachedPoint.y == aPt.y) 5499 return; 5500 cachedPoint = aPt; 5501 5502 if ( pSalData->mhWantLeaveMsg != WindowFromPoint( aPt ) ) 5503 SendMessageW( pSalData->mhWantLeaveMsg, SAL_MSG_MOUSELEAVE, 0, MAKELPARAM( aPt.x, aPt.y ) ); 5504 } 5505 } 5506 5507 static bool ImplSalWheelMousePos( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam , 5508 LRESULT& rResult ) 5509 { 5510 POINT aPt; 5511 POINT aScreenPt; 5512 aScreenPt.x = static_cast<short>(LOWORD( lParam )); 5513 aScreenPt.y = static_cast<short>(HIWORD( lParam )); 5514 // find child window that is at this position 5515 HWND hChildWnd; 5516 HWND hWheelWnd = hWnd; 5517 do 5518 { 5519 hChildWnd = hWheelWnd; 5520 aPt = aScreenPt; 5521 ScreenToClient( hChildWnd, &aPt ); 5522 hWheelWnd = ChildWindowFromPointEx( hChildWnd, aPt, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT ); 5523 } 5524 while ( hWheelWnd && (hWheelWnd != hChildWnd) ); 5525 if ( hWheelWnd && (hWheelWnd != hWnd) && 5526 (hWheelWnd != ::GetFocus()) && IsWindowEnabled( hWheelWnd ) ) 5527 { 5528 rResult = SendMessageW( hWheelWnd, nMsg, wParam, lParam ); 5529 return false; 5530 } 5531 5532 return true; 5533 } 5534 5535 static LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, bool& rDef ) 5536 { 5537 LRESULT nRet = 0; 5538 static bool bInWheelMsg = false; 5539 static bool bInQueryEnd = false; 5540 5541 SAL_INFO("vcl.gdi.wndproc", "SalFrameWndProc(nMsg=" << nMsg << ", wParam=" << wParam << ", lParam=" << lParam << ")"); 5542 5543 // By WM_CREATE we connect the frame with the window handle 5544 if ( nMsg == WM_CREATE ) 5545 { 5546 // Save Window-Instance in Windowhandle 5547 // Can also be used for the A-Version, because the struct 5548 // to access lpCreateParams is the same structure 5549 CREATESTRUCTW* pStruct = reinterpret_cast<CREATESTRUCTW*>(lParam); 5550 WinSalFrame* pFrame = static_cast<WinSalFrame*>(pStruct->lpCreateParams); 5551 if ( pFrame != nullptr ) 5552 { 5553 SetWindowPtr( hWnd, pFrame ); 5554 5555 UpdateDarkMode(hWnd); 5556 5557 // Set HWND already here, as data might be used already 5558 // when messages are being sent by CreateWindow() 5559 pFrame->mhWnd = hWnd; 5560 pFrame->maSysData.hWnd = hWnd; 5561 } 5562 return 0; 5563 } 5564 5565 ImplSVData* pSVData = ImplGetSVData(); 5566 // #i72707# TODO: the mbDeInit check will not be needed 5567 // once all windows that are not properly closed on exit got fixed 5568 if( pSVData->mbDeInit ) 5569 return 0; 5570 5571 if ( WM_USER_SYSTEM_WINDOW_ACTIVATED == nMsg ) 5572 { 5573 ImplHideSplash(); 5574 return 0; 5575 } 5576 5577 switch( nMsg ) 5578 { 5579 case WM_MOUSEMOVE: 5580 case WM_LBUTTONDOWN: 5581 case WM_MBUTTONDOWN: 5582 case WM_RBUTTONDOWN: 5583 case WM_LBUTTONUP: 5584 case WM_MBUTTONUP: 5585 case WM_RBUTTONUP: 5586 case WM_NCMOUSEMOVE: 5587 case SAL_MSG_MOUSELEAVE: 5588 ImplSalYieldMutexAcquireWithWait(); 5589 rDef = !ImplHandleMouseMsg( hWnd, nMsg, wParam, lParam ); 5590 ImplSalYieldMutexRelease(); 5591 break; 5592 5593 case WM_NCLBUTTONDOWN: 5594 case WM_NCMBUTTONDOWN: 5595 case WM_NCRBUTTONDOWN: 5596 ImplSalYieldMutexAcquireWithWait(); 5597 ImplCallClosePopupsHdl( hWnd ); // close popups... 5598 ImplSalYieldMutexRelease(); 5599 break; 5600 5601 case WM_MOUSEACTIVATE: 5602 if ( LOWORD( lParam ) == HTCLIENT ) 5603 { 5604 ImplSalYieldMutexAcquireWithWait(); 5605 nRet = LRESULT(ImplHandleMouseActivateMsg( hWnd )); 5606 ImplSalYieldMutexRelease(); 5607 if ( nRet ) 5608 { 5609 nRet = MA_NOACTIVATE; 5610 rDef = false; 5611 } 5612 } 5613 break; 5614 5615 case WM_KEYDOWN: 5616 case WM_KEYUP: 5617 case WM_DEADCHAR: 5618 case WM_CHAR: 5619 case WM_UNICHAR: // MCD, 2003-01-13, Support for WM_UNICHAR & Keyman 6.0 5620 case WM_SYSKEYDOWN: 5621 case WM_SYSKEYUP: 5622 case WM_SYSCHAR: 5623 ImplSalYieldMutexAcquireWithWait(); 5624 rDef = !ImplHandleKeyMsg( hWnd, nMsg, wParam, lParam, nRet ); 5625 ImplSalYieldMutexRelease(); 5626 break; 5627 5628 case WM_MOUSEWHEEL: 5629 case WM_MOUSEHWHEEL: 5630 // protect against recursion, in case the message is returned 5631 // by IE or the external window 5632 if ( !bInWheelMsg ) 5633 { 5634 bInWheelMsg = true; 5635 rDef = !ImplHandleWheelMsg( hWnd, nMsg, wParam, lParam ); 5636 // If we did not process the message, re-check if here is a 5637 // connected (?) window that we have to notify. 5638 if ( rDef ) 5639 rDef = ImplSalWheelMousePos( hWnd, nMsg, wParam, lParam, nRet ); 5640 bInWheelMsg = false; 5641 } 5642 break; 5643 5644 case WM_COMMAND: 5645 ImplSalYieldMutexAcquireWithWait(); 5646 rDef = !ImplHandleCommand( hWnd, wParam, lParam ); 5647 ImplSalYieldMutexRelease(); 5648 break; 5649 5650 case WM_INITMENUPOPUP: 5651 ImplSalYieldMutexAcquireWithWait(); 5652 rDef = !ImplHandleMenuActivate( hWnd, wParam, lParam ); 5653 ImplSalYieldMutexRelease(); 5654 break; 5655 5656 case WM_MENUSELECT: 5657 ImplSalYieldMutexAcquireWithWait(); 5658 rDef = !ImplHandleMenuSelect( hWnd, wParam, lParam ); 5659 ImplSalYieldMutexRelease(); 5660 break; 5661 5662 case WM_SYSCOMMAND: 5663 ImplSalYieldMutexAcquireWithWait(); 5664 nRet = LRESULT(ImplHandleSysCommand( hWnd, wParam, lParam )); 5665 ImplSalYieldMutexRelease(); 5666 if ( nRet ) 5667 rDef = false; 5668 break; 5669 5670 case WM_MENUCHAR: 5671 nRet = ImplMenuChar( hWnd, wParam, lParam ); 5672 if( nRet ) 5673 rDef = false; 5674 break; 5675 5676 case WM_MEASUREITEM: 5677 nRet = ImplMeasureItem(hWnd, wParam, lParam); 5678 if( nRet ) 5679 rDef = false; 5680 break; 5681 5682 case WM_DRAWITEM: 5683 nRet = ImplDrawItem(hWnd, wParam, lParam); 5684 if( nRet ) 5685 rDef = false; 5686 break; 5687 5688 case WM_MOVE: 5689 ImplHandleMoveMsg(hWnd, lParam); 5690 rDef = false; 5691 break; 5692 case SAL_MSG_POSTMOVE: 5693 ImplCallMoveHdl(hWnd); 5694 rDef = false; 5695 break; 5696 case WM_SIZE: 5697 ImplHandleSizeMsg(hWnd, wParam, lParam); 5698 rDef = false; 5699 break; 5700 case SAL_MSG_POSTCALLSIZE: 5701 ImplCallSizeHdl( hWnd ); 5702 rDef = false; 5703 break; 5704 5705 case WM_GETMINMAXINFO: 5706 if ( ImplHandleMinMax( hWnd, lParam ) ) 5707 rDef = false; 5708 break; 5709 5710 case WM_ERASEBKGND: 5711 nRet = 1; 5712 rDef = false; 5713 break; 5714 case WM_PAINT: 5715 ImplHandlePaintMsg( hWnd ); 5716 rDef = false; 5717 break; 5718 case SAL_MSG_POSTPAINT: 5719 ImplHandlePostPaintMsg( hWnd, reinterpret_cast<RECT*>(wParam) ); 5720 rDef = false; 5721 break; 5722 5723 case SAL_MSG_FORCEPALETTE: 5724 ImplHandleForcePalette( hWnd ); 5725 rDef = false; 5726 break; 5727 5728 case WM_QUERYNEWPALETTE: 5729 case SAL_MSG_POSTQUERYNEWPAL: 5730 nRet = ImplHandlePalette( true, hWnd, nMsg, wParam, lParam, rDef ); 5731 break; 5732 5733 case WM_ACTIVATE: 5734 // Getting activated, we also want to set our palette. 5735 // We do this in Activate, so that other external child windows 5736 // can overwrite our palette. Thus our palette is set only once 5737 // and not recursively, as at all other places it is set only as 5738 // the background palette. 5739 if ( LOWORD( wParam ) != WA_INACTIVE ) 5740 SendMessageW( hWnd, SAL_MSG_FORCEPALETTE, 0, 0 ); 5741 break; 5742 5743 case WM_ENABLE: 5744 // #95133# a system dialog is opened/closed, using our app window as parent 5745 { 5746 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 5747 vcl::Window *pWin = nullptr; 5748 if( pFrame ) 5749 pWin = pFrame->GetWindow(); 5750 5751 if( !wParam ) 5752 { 5753 pSVData->maAppData.mnModalMode++; 5754 5755 ImplHideSplash(); 5756 if( pWin ) 5757 { 5758 pWin->EnableInput( false, nullptr ); 5759 pWin->IncModalCount(); // #106303# support frame based modal count 5760 } 5761 } 5762 else 5763 { 5764 ImplGetSVData()->maAppData.mnModalMode--; 5765 if( pWin ) 5766 { 5767 pWin->EnableInput( true, nullptr ); 5768 pWin->DecModalCount(); // #106303# support frame based modal count 5769 } 5770 } 5771 } 5772 break; 5773 5774 case WM_KILLFOCUS: 5775 DestroyCaret(); 5776 [[fallthrough]]; 5777 case WM_SETFOCUS: 5778 case SAL_MSG_POSTFOCUS: 5779 ImplHandleFocusMsg( hWnd ); 5780 rDef = false; 5781 break; 5782 5783 case WM_CLOSE: 5784 ImplHandleCloseMsg( hWnd ); 5785 rDef = false; 5786 break; 5787 5788 case WM_QUERYENDSESSION: 5789 if( !bInQueryEnd ) 5790 { 5791 // handle queryendsession only once 5792 bInQueryEnd = true; 5793 nRet = LRESULT(!ImplHandleShutDownMsg( hWnd )); 5794 rDef = false; 5795 5796 // Issue #16314#: ImplHandleShutDownMsg causes a PostMessage in case of allowing shutdown. 5797 // This posted message was never processed and cause Windows XP to hang after log off 5798 // if there are multiple sessions and the current session wasn't the first one started. 5799 // So if shutdown is allowed we assume that a post message was done and retrieve all 5800 // messages in the message queue and dispatch them before we return control to the system. 5801 5802 if ( nRet ) 5803 { 5804 SolarMutexGuard aGuard; 5805 while ( Application::Reschedule( true ) ); 5806 } 5807 } 5808 else 5809 { 5810 ImplSalYieldMutexAcquireWithWait(); 5811 ImplSalYieldMutexRelease(); 5812 rDef = true; 5813 } 5814 break; 5815 5816 case WM_ENDSESSION: 5817 if( !wParam ) 5818 bInQueryEnd = false; // no shutdown: allow query again 5819 nRet = FALSE; 5820 rDef = false; 5821 break; 5822 5823 case WM_DISPLAYCHANGE: 5824 case WM_SETTINGCHANGE: 5825 case WM_DEVMODECHANGE: 5826 case WM_FONTCHANGE: 5827 case WM_SYSCOLORCHANGE: 5828 case WM_TIMECHANGE: 5829 ImplHandleSettingsChangeMsg( hWnd, nMsg, wParam, lParam ); 5830 break; 5831 5832 case WM_THEMECHANGED: 5833 GetSalData()->mbThemeChanged = true; 5834 break; 5835 5836 case SAL_MSG_USEREVENT: 5837 ImplHandleUserEvent( hWnd, lParam ); 5838 rDef = false; 5839 break; 5840 5841 case SAL_MSG_CAPTUREMOUSE: 5842 SetCapture( hWnd ); 5843 rDef = false; 5844 break; 5845 case SAL_MSG_RELEASEMOUSE: 5846 if ( ::GetCapture() == hWnd ) 5847 ReleaseCapture(); 5848 rDef = false; 5849 break; 5850 case SAL_MSG_TOTOP: 5851 ImplSalToTop( hWnd, static_cast<SalFrameToTop>(wParam) ); 5852 rDef = false; 5853 break; 5854 case SAL_MSG_SHOW: 5855 ImplSalShow( hWnd, static_cast<bool>(wParam), static_cast<bool>(lParam) ); 5856 rDef = false; 5857 break; 5858 case SAL_MSG_SETINPUTCONTEXT: 5859 ImplSalFrameSetInputContext( hWnd, reinterpret_cast<const SalInputContext*>(lParam) ); 5860 rDef = false; 5861 break; 5862 case SAL_MSG_ENDEXTTEXTINPUT: 5863 ImplSalFrameEndExtTextInput( hWnd, static_cast<EndExtTextInputFlags>(wParam) ); 5864 rDef = false; 5865 break; 5866 5867 case WM_INPUTLANGCHANGE: 5868 ImplHandleInputLangChange( hWnd, wParam, lParam ); 5869 break; 5870 5871 case WM_IME_CHAR: 5872 // #103487#, some IMEs (eg, those that do not work onspot) 5873 // may send WM_IME_CHAR instead of WM_IME_COMPOSITION 5874 // we just handle it like a WM_CHAR message - seems to work fine 5875 ImplSalYieldMutexAcquireWithWait(); 5876 rDef = !ImplHandleKeyMsg( hWnd, WM_CHAR, wParam, lParam, nRet ); 5877 ImplSalYieldMutexRelease(); 5878 break; 5879 5880 case WM_IME_STARTCOMPOSITION: 5881 rDef = ImplHandleIMEStartComposition( hWnd ); 5882 break; 5883 5884 case WM_IME_COMPOSITION: 5885 rDef = ImplHandleIMEComposition( hWnd, lParam ); 5886 break; 5887 5888 case WM_IME_ENDCOMPOSITION: 5889 rDef = ImplHandleIMEEndComposition( hWnd ); 5890 break; 5891 5892 case WM_IME_NOTIFY: 5893 ImplHandleIMENotify( hWnd, wParam ); 5894 break; 5895 5896 case WM_GETOBJECT: 5897 ImplSalYieldMutexAcquireWithWait(); 5898 if ( ImplHandleGetObject( hWnd, lParam, wParam, nRet ) ) 5899 { 5900 rDef = false; 5901 } 5902 ImplSalYieldMutexRelease(); 5903 break; 5904 5905 case WM_APPCOMMAND: 5906 if( ImplHandleAppCommand( hWnd, lParam, nRet ) ) 5907 { 5908 rDef = false; 5909 } 5910 break; 5911 case WM_IME_REQUEST: 5912 if ( static_cast<sal_uIntPtr>(wParam) == IMR_RECONVERTSTRING ) 5913 { 5914 nRet = ImplHandleIMEReconvertString( hWnd, lParam ); 5915 rDef = false; 5916 } 5917 else if( static_cast<sal_uIntPtr>(wParam) == IMR_CONFIRMRECONVERTSTRING ) 5918 { 5919 nRet = ImplHandleIMEConfirmReconvertString( hWnd, lParam ); 5920 rDef = false; 5921 } 5922 else if ( static_cast<sal_uIntPtr>(wParam) == IMR_QUERYCHARPOSITION ) 5923 { 5924 if ( ImplSalYieldMutexTryToAcquire() ) 5925 { 5926 nRet = ImplHandleIMEQueryCharPosition( hWnd, lParam ); 5927 ImplSalYieldMutexRelease(); 5928 } 5929 else 5930 nRet = FALSE; 5931 rDef = false; 5932 } 5933 break; 5934 } 5935 5936 return nRet; 5937 } 5938 5939 LRESULT CALLBACK SalFrameWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ) 5940 { 5941 bool bDef = true; 5942 LRESULT nRet = 0; 5943 __try 5944 { 5945 nRet = SalFrameWndProc( hWnd, nMsg, wParam, lParam, bDef ); 5946 } 5947 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation())) 5948 { 5949 } 5950 5951 if ( bDef ) 5952 nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam ); 5953 return nRet; 5954 } 5955 5956 bool ImplHandleGlobalMsg( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, LRESULT& rlResult ) 5957 { 5958 // handle all messages concerning all frames so they get processed only once 5959 // Must work for Unicode and none Unicode 5960 bool bResult = false; 5961 if ( (nMsg == WM_PALETTECHANGED) || (nMsg == SAL_MSG_POSTPALCHANGED) ) 5962 { 5963 bResult = true; 5964 rlResult = ImplHandlePalette( false, hWnd, nMsg, wParam, lParam, bResult ); 5965 } 5966 else if( nMsg == WM_DISPLAYCHANGE ) 5967 { 5968 WinSalSystem* pSys = static_cast<WinSalSystem*>(ImplGetSalSystem()); 5969 if( pSys ) 5970 pSys->clearMonitors(); 5971 bResult = (pSys != nullptr); 5972 } 5973 return bResult; 5974 } 5975 5976 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 5977
