1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_vcl.hxx" 26 27 #include <string.h> 28 #include <tools/svwin.h> 29 #ifdef WNT 30 #include <process.h> 31 #endif 32 #ifdef __MINGW32__ 33 #include <excpt.h> 34 #endif 35 36 #include <osl/file.hxx> 37 38 #include <vos/mutex.hxx> 39 40 #include <tools/solarmutex.hxx> 41 #include <tools/debug.hxx> 42 43 #include <vcl/timer.hxx> 44 #include <vcl/apptypes.hxx> 45 46 #include <win/wincomp.hxx> 47 #include <win/salids.hrc> 48 #include <win/saldata.hxx> 49 #include <win/salinst.h> 50 #include <win/salframe.h> 51 #include <win/salobj.h> 52 #include <win/saltimer.h> 53 #include <win/salbmp.h> 54 55 #include <salimestatus.hxx> 56 #include <salsys.hxx> 57 58 #ifndef min 59 #define min(a,b) (((a) < (b)) ? (a) : (b)) 60 #endif 61 #ifndef max 62 #define max(a,b) (((a) > (b)) ? (a) : (b)) 63 #endif 64 65 #if defined _MSC_VER 66 #pragma warning(push, 1) 67 #pragma warning( disable: 4917 ) 68 #endif 69 70 #include <GdiPlus.h> 71 #include <GdiPlusEnums.h> 72 #include <GdiPlusColor.h> 73 #include <Shlobj.h> 74 75 #if defined _MSC_VER 76 #pragma warning(pop) 77 #endif 78 79 // ======================================================================= 80 81 void SalAbort( const XubString& rErrorText ) 82 { 83 ImplFreeSalGDI(); 84 85 if ( !rErrorText.Len() ) 86 { 87 // #112255# make sure crash reporter is triggered 88 RaiseException( 0, EXCEPTION_NONCONTINUABLE, 0, NULL ); 89 FatalAppExit( 0, "Application Error" ); 90 } 91 else 92 { 93 // #112255# make sure crash reporter is triggered 94 RaiseException( 0, EXCEPTION_NONCONTINUABLE, 0, NULL ); 95 ByteString aErrorText( ImplSalGetWinAnsiString( rErrorText ) ); 96 FatalAppExit( 0, aErrorText.GetBuffer() ); 97 } 98 } 99 100 // ======================================================================= 101 102 LRESULT CALLBACK SalComWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ); 103 LRESULT CALLBACK SalComWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ); 104 105 // ======================================================================= 106 107 class SalYieldMutex : public vos::OMutex 108 { 109 public: // for ImplSalYield() 110 WinSalInstance* mpInstData; 111 sal_uLong mnCount; 112 DWORD mnThreadId; 113 114 public: 115 SalYieldMutex( WinSalInstance* pInstData ); 116 117 virtual void SAL_CALL acquire(); 118 virtual void SAL_CALL release(); 119 virtual sal_Bool SAL_CALL tryToAcquire(); 120 121 sal_uLong GetAcquireCount( sal_uLong nThreadId ); 122 }; 123 124 // ----------------------------------------------------------------------- 125 126 SalYieldMutex::SalYieldMutex( WinSalInstance* pInstData ) 127 { 128 mpInstData = pInstData; 129 mnCount = 0; 130 mnThreadId = 0; 131 } 132 133 // ----------------------------------------------------------------------- 134 135 void SAL_CALL SalYieldMutex::acquire() 136 { 137 OMutex::acquire(); 138 mnCount++; 139 mnThreadId = GetCurrentThreadId(); 140 } 141 142 // ----------------------------------------------------------------------- 143 144 void SAL_CALL SalYieldMutex::release() 145 { 146 DWORD nThreadId = GetCurrentThreadId(); 147 if ( mnThreadId != nThreadId ) 148 OMutex::release(); 149 else 150 { 151 SalData* pSalData = GetSalData(); 152 if ( pSalData->mnAppThreadId != nThreadId ) 153 { 154 if ( mnCount == 1 ) 155 { 156 // If we don't call these message, the Output from the 157 // Java clients doesn't come in the right order 158 GdiFlush(); 159 160 mpInstData->mpSalWaitMutex->acquire(); 161 if ( mpInstData->mnYieldWaitCount ) 162 ImplPostMessage( mpInstData->mhComWnd, SAL_MSG_RELEASEWAITYIELD, 0, 0 ); 163 mnThreadId = 0; 164 mnCount--; 165 OMutex::release(); 166 mpInstData->mpSalWaitMutex->release(); 167 } 168 else 169 { 170 mnCount--; 171 OMutex::release(); 172 } 173 } 174 else 175 { 176 if ( mnCount == 1 ) 177 mnThreadId = 0; 178 mnCount--; 179 OMutex::release(); 180 } 181 } 182 } 183 184 // ----------------------------------------------------------------------- 185 186 sal_Bool SAL_CALL SalYieldMutex::tryToAcquire() 187 { 188 if( OMutex::tryToAcquire() ) 189 { 190 mnCount++; 191 mnThreadId = GetCurrentThreadId(); 192 return sal_True; 193 } 194 else 195 return sal_False; 196 } 197 198 // ----------------------------------------------------------------------- 199 200 sal_uLong SalYieldMutex::GetAcquireCount( sal_uLong nThreadId ) 201 { 202 if ( nThreadId == mnThreadId ) 203 return mnCount; 204 else 205 return 0; 206 } 207 208 // ----------------------------------------------------------------------- 209 210 void ImplSalYieldMutexAcquireWithWait() 211 { 212 WinSalInstance* pInst = GetSalData()->mpFirstInstance; 213 if ( !pInst ) 214 return; 215 216 // If we are the main thread, then we must wait with wait, because 217 // in if we don't reschedule, then we create deadlocks if a Windows 218 // Function is called from another thread. If we arn't the main thread, 219 // than we call qcquire directly. 220 DWORD nThreadId = GetCurrentThreadId(); 221 SalData* pSalData = GetSalData(); 222 if ( pSalData->mnAppThreadId == nThreadId ) 223 { 224 // Wenn wir den Mutex nicht bekommen, muessen wir solange 225 // warten, bis wir Ihn bekommen 226 sal_Bool bAcquire = FALSE; 227 do 228 { 229 if ( pInst->mpSalYieldMutex->tryToAcquire() ) 230 bAcquire = TRUE; 231 else 232 { 233 pInst->mpSalWaitMutex->acquire(); 234 if ( pInst->mpSalYieldMutex->tryToAcquire() ) 235 { 236 bAcquire = TRUE; 237 pInst->mpSalWaitMutex->release(); 238 } 239 else 240 { 241 pInst->mnYieldWaitCount++; 242 pInst->mpSalWaitMutex->release(); 243 MSG aTmpMsg; 244 ImplGetMessage( &aTmpMsg, pInst->mhComWnd, SAL_MSG_RELEASEWAITYIELD, SAL_MSG_RELEASEWAITYIELD ); 245 pInst->mnYieldWaitCount--; 246 if ( pInst->mnYieldWaitCount ) 247 ImplPostMessage( pInst->mhComWnd, SAL_MSG_RELEASEWAITYIELD, 0, 0 ); 248 } 249 } 250 } 251 while ( !bAcquire ); 252 } 253 else 254 pInst->mpSalYieldMutex->acquire(); 255 } 256 257 // ----------------------------------------------------------------------- 258 259 sal_Bool ImplSalYieldMutexTryToAcquire() 260 { 261 WinSalInstance* pInst = GetSalData()->mpFirstInstance; 262 if ( pInst ) 263 return pInst->mpSalYieldMutex->tryToAcquire(); 264 else 265 return FALSE; 266 } 267 268 // ----------------------------------------------------------------------- 269 270 void ImplSalYieldMutexAcquire() 271 { 272 WinSalInstance* pInst = GetSalData()->mpFirstInstance; 273 if ( pInst ) 274 pInst->mpSalYieldMutex->acquire(); 275 } 276 277 // ----------------------------------------------------------------------- 278 279 void ImplSalYieldMutexRelease() 280 { 281 WinSalInstance* pInst = GetSalData()->mpFirstInstance; 282 if ( pInst ) 283 { 284 GdiFlush(); 285 pInst->mpSalYieldMutex->release(); 286 } 287 } 288 289 // ----------------------------------------------------------------------- 290 291 sal_uLong ImplSalReleaseYieldMutex() 292 { 293 WinSalInstance* pInst = GetSalData()->mpFirstInstance; 294 if ( !pInst ) 295 return 0; 296 297 SalYieldMutex* pYieldMutex = pInst->mpSalYieldMutex; 298 sal_uLong nCount = pYieldMutex->GetAcquireCount( GetCurrentThreadId() ); 299 sal_uLong n = nCount; 300 while ( n ) 301 { 302 pYieldMutex->release(); 303 n--; 304 } 305 306 return nCount; 307 } 308 309 // ----------------------------------------------------------------------- 310 311 void ImplSalAcquireYieldMutex( sal_uLong nCount ) 312 { 313 WinSalInstance* pInst = GetSalData()->mpFirstInstance; 314 if ( !pInst ) 315 return; 316 317 SalYieldMutex* pYieldMutex = pInst->mpSalYieldMutex; 318 while ( nCount ) 319 { 320 pYieldMutex->acquire(); 321 nCount--; 322 } 323 } 324 325 // ----------------------------------------------------------------------- 326 327 bool WinSalInstance::CheckYieldMutex() 328 { 329 bool bRet = true; 330 SalData* pSalData = GetSalData(); 331 DWORD nCurThreadId = GetCurrentThreadId(); 332 if ( pSalData->mnAppThreadId != nCurThreadId ) 333 { 334 if ( pSalData->mpFirstInstance ) 335 { 336 SalYieldMutex* pYieldMutex = pSalData->mpFirstInstance->mpSalYieldMutex; 337 if ( pYieldMutex->mnThreadId != nCurThreadId ) 338 { 339 bRet = false; 340 } 341 } 342 } 343 else 344 { 345 if ( pSalData->mpFirstInstance ) 346 { 347 SalYieldMutex* pYieldMutex = pSalData->mpFirstInstance->mpSalYieldMutex; 348 if ( pYieldMutex->mnThreadId != nCurThreadId ) 349 { 350 bRet = false; 351 } 352 } 353 } 354 return bRet; 355 } 356 357 // ======================================================================= 358 359 void SalData::initKeyCodeMap() 360 { 361 UINT nKey = 0xffffffff; 362 #define initKey( a, b )\ 363 nKey = LOWORD( VkKeyScan( a ) );\ 364 if( nKey < 0xffff )\ 365 maVKMap[ nKey ] = b; 366 367 initKey( '+', KEY_ADD ); 368 initKey( '-', KEY_SUBTRACT ); 369 initKey( '*', KEY_MULTIPLY ); 370 initKey( '/', KEY_DIVIDE ); 371 initKey( '.', KEY_POINT ); 372 initKey( ',', KEY_COMMA ); 373 initKey( '<', KEY_LESS ); 374 initKey( '>', KEY_GREATER ); 375 initKey( '=', KEY_EQUAL ); 376 initKey( '~', KEY_TILDE ); 377 initKey( '`', KEY_QUOTELEFT ); 378 } 379 380 // ======================================================================= 381 // ------- 382 // SalData 383 // ------- 384 385 SalData::SalData() 386 { 387 mhInst = 0; // default instance handle 388 mhPrevInst = 0; // previous instance handle 389 mnCmdShow = 0; // default frame show style 390 mhDitherPal = 0; // dither palette 391 mhDitherDIB = 0; // dither memory handle 392 mpDitherDIB = 0; // dither memory 393 mpDitherDIBData = 0; // beginning of DIB data 394 mpDitherDiff = 0; // Dither mapping table 395 mpDitherLow = 0; // Dither mapping table 396 mpDitherHigh = 0; // Dither mapping table 397 mnTimerMS = 0; // Current Time (in MS) of the Timer 398 mnTimerOrgMS = 0; // Current Original Time (in MS) 399 mnNextTimerTime = 0; 400 mnLastEventTime = 0; 401 mnTimerId = 0; // windows timer id 402 mbInTimerProc = FALSE; // timer event is currently being dispatched 403 mhSalObjMsgHook = 0; // hook to get interesting msg for SalObject 404 mhWantLeaveMsg = 0; // window handle, that want a MOUSELEAVE message 405 mpMouseLeaveTimer = 0; // Timer for MouseLeave Test 406 mpFirstInstance = 0; // pointer of first instance 407 mpFirstFrame = 0; // pointer of first frame 408 mpFirstObject = 0; // pointer of first object window 409 mpFirstVD = 0; // first VirDev 410 mpFirstPrinter = 0; // first printing printer 411 mpHDCCache = 0; // Cache for three DC's 412 mh50Bmp = 0; // 50% Bitmap 413 mh50Brush = 0; // 50% Brush 414 int i; 415 for(i=0; i<MAX_STOCKPEN; i++) 416 { 417 maStockPenColorAry[i] = 0; 418 mhStockPenAry[i] = 0; 419 } 420 for(i=0; i<MAX_STOCKBRUSH; i++) 421 { 422 maStockBrushColorAry[i] = 0; 423 mhStockBrushAry[i] = 0; 424 } 425 mnStockPenCount = 0; // count of static pens 426 mnStockBrushCount = 0; // count of static brushes 427 mnSalObjWantKeyEvt = 0; // KeyEvent, welcher vom SalObj-Hook verarbeitet werden soll 428 mnCacheDCInUse = 0; // count of CacheDC in use 429 mbObjClassInit = FALSE; // is SALOBJECTCLASS initialised 430 mbInPalChange = FALSE; // is in WM_QUERYNEWPALETTE 431 mnAppThreadId = 0; // Id from Applikation-Thread 432 mbScrSvrEnabled = FALSE; // ScreenSaver enabled 433 mnSageStatus = 0; // status of Sage-DLL (DISABLE_AGENT == nicht vorhanden) 434 mpSageEnableProc = 0; // funktion to deactivate the system agent 435 mpFirstIcon = 0; // icon cache, points to first icon, NULL if none 436 mpTempFontItem = 0; 437 mbThemeChanged = FALSE; // true if visual theme was changed: throw away theme handles 438 mbThemeMenuSupport = FALSE; 439 440 // init with NULL 441 gdiplusToken = 0; 442 maDwmLib = 0; 443 mpDwmIsCompositionEnabled = 0; 444 445 initKeyCodeMap(); 446 447 SetSalData( this ); 448 initNWF(); 449 } 450 451 SalData::~SalData() 452 { 453 deInitNWF(); 454 SetSalData( NULL ); 455 } 456 457 void InitSalData() 458 { 459 SalData* pSalData = new SalData; 460 CoInitialize(0); 461 462 // init GDIPlus 463 static Gdiplus::GdiplusStartupInput gdiplusStartupInput; 464 Gdiplus::GdiplusStartup(&pSalData->gdiplusToken, &gdiplusStartupInput, NULL); 465 } 466 467 468 void DeInitSalData() 469 { 470 CoUninitialize(); 471 SalData* pSalData = GetSalData(); 472 473 // deinit GDIPlus 474 if(pSalData) 475 { 476 Gdiplus::GdiplusShutdown(pSalData->gdiplusToken); 477 } 478 479 delete pSalData; 480 } 481 482 // ----------------------------------------------------------------------- 483 484 void InitSalMain() 485 { 486 // remember data, copied from WinMain 487 SalData* pData = GetAppSalData(); 488 if ( pData ) // Im AppServer NULL 489 { 490 STARTUPINFO aSI; 491 aSI.cb = sizeof( aSI ); 492 GetStartupInfo( &aSI ); 493 pData->mhInst = GetModuleHandle( NULL ); 494 pData->mhPrevInst = NULL; 495 pData->mnCmdShow = aSI.wShowWindow; 496 } 497 } 498 499 void DeInitSalMain() 500 { 501 } 502 503 // ----------------------------------------------------------------------- 504 505 SalInstance* CreateSalInstance() 506 { 507 SalData* pSalData = GetSalData(); 508 509 // determine the windows version 510 aSalShlData.mbWXP = 0; 511 aSalShlData.mbWPrinter = 0; 512 WORD nVer = (WORD)GetVersion(); 513 aSalShlData.mnVersion = (((WORD)LOBYTE(nVer)) * 100) + HIBYTE(nVer); 514 if ( aSalShlData.mnVersion >= 400 ) 515 aSalShlData.mbW40 = 1; 516 rtl_zeroMemory( &aSalShlData.maVersionInfo, sizeof(aSalShlData.maVersionInfo) ); 517 aSalShlData.maVersionInfo.dwOSVersionInfoSize = sizeof( aSalShlData.maVersionInfo ); 518 if ( GetVersionEx( &aSalShlData.maVersionInfo ) ) 519 { 520 if ( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) 521 { 522 // Windows XP ? 523 if ( aSalShlData.maVersionInfo.dwMajorVersion > 5 || 524 ( aSalShlData.maVersionInfo.dwMajorVersion == 5 && aSalShlData.maVersionInfo.dwMinorVersion >= 1 ) ) 525 aSalShlData.mbWXP = 1; 526 if( aSalShlData.maVersionInfo.dwMajorVersion >= 5 ) 527 aSalShlData.mbWPrinter = 1; 528 } 529 } 530 531 pSalData->mnAppThreadId = GetCurrentThreadId(); 532 533 // register frame class 534 if ( !pSalData->mhPrevInst ) 535 { 536 WNDCLASSEXW aWndClassEx; 537 aWndClassEx.cbSize = sizeof( aWndClassEx ); 538 aWndClassEx.style = CS_OWNDC; 539 aWndClassEx.lpfnWndProc = SalFrameWndProcW; 540 aWndClassEx.cbClsExtra = 0; 541 aWndClassEx.cbWndExtra = SAL_FRAME_WNDEXTRA; 542 aWndClassEx.hInstance = pSalData->mhInst; 543 aWndClassEx.hCursor = 0; 544 aWndClassEx.hbrBackground = 0; 545 aWndClassEx.lpszMenuName = 0; 546 aWndClassEx.lpszClassName = SAL_FRAME_CLASSNAMEW; 547 ImplLoadSalIcon( SAL_RESID_ICON_DEFAULT, aWndClassEx.hIcon, aWndClassEx.hIconSm ); 548 if ( !RegisterClassExW( &aWndClassEx ) ) 549 return NULL; 550 551 aWndClassEx.hIcon = 0; 552 aWndClassEx.hIconSm = 0; 553 aWndClassEx.style |= CS_SAVEBITS; 554 aWndClassEx.lpszClassName = SAL_SUBFRAME_CLASSNAMEW; 555 if ( !RegisterClassExW( &aWndClassEx ) ) 556 return NULL; 557 558 // shadow effect for popups on XP 559 if( aSalShlData.mbWXP ) 560 aWndClassEx.style |= CS_DROPSHADOW; 561 aWndClassEx.lpszClassName = SAL_TMPSUBFRAME_CLASSNAMEW; 562 if ( !RegisterClassExW( &aWndClassEx ) ) 563 return NULL; 564 565 aWndClassEx.style = 0; 566 aWndClassEx.lpfnWndProc = SalComWndProcW; 567 aWndClassEx.cbWndExtra = 0; 568 aWndClassEx.lpszClassName = SAL_COM_CLASSNAMEW; 569 if ( !RegisterClassExW( &aWndClassEx ) ) 570 return NULL; 571 } 572 573 HWND hComWnd = CreateWindowExW( WS_EX_TOOLWINDOW, SAL_COM_CLASSNAMEW, 574 L"", WS_POPUP, 0, 0, 0, 0, 0, 0, 575 pSalData->mhInst, NULL ); 576 if ( !hComWnd ) 577 return NULL; 578 579 WinSalInstance* pInst = new WinSalInstance; 580 581 // init instance (only one instance in this version !!!) 582 pSalData->mpFirstInstance = pInst; 583 pInst->mhInst = pSalData->mhInst; 584 pInst->mhComWnd = hComWnd; 585 586 // init static GDI Data 587 ImplInitSalGDI(); 588 589 return pInst; 590 } 591 592 // ----------------------------------------------------------------------- 593 594 void DestroySalInstance( SalInstance* pInst ) 595 { 596 SalData* pSalData = GetSalData(); 597 598 // (only one instance in this version !!!) 599 600 ImplFreeSalGDI(); 601 602 // reset instance 603 if ( pSalData->mpFirstInstance == pInst ) 604 pSalData->mpFirstInstance = NULL; 605 606 delete pInst; 607 } 608 609 // ----------------------------------------------------------------------- 610 611 WinSalInstance::WinSalInstance() 612 { 613 mhComWnd = 0; 614 mpSalYieldMutex = new SalYieldMutex( this ); 615 mpSalWaitMutex = new vos::OMutex; 616 mnYieldWaitCount = 0; 617 mpSalYieldMutex->acquire(); 618 ::tools::SolarMutex::SetSolarMutex( mpSalYieldMutex ); 619 } 620 621 // ----------------------------------------------------------------------- 622 623 WinSalInstance::~WinSalInstance() 624 { 625 ::tools::SolarMutex::SetSolarMutex( 0 ); 626 mpSalYieldMutex->release(); 627 delete mpSalYieldMutex; 628 delete mpSalWaitMutex; 629 DestroyWindow( mhComWnd ); 630 } 631 632 // ----------------------------------------------------------------------- 633 634 vos::IMutex* WinSalInstance::GetYieldMutex() 635 { 636 return mpSalYieldMutex; 637 } 638 639 // ----------------------------------------------------------------------- 640 641 sal_uLong WinSalInstance::ReleaseYieldMutex() 642 { 643 return ImplSalReleaseYieldMutex(); 644 } 645 646 // ----------------------------------------------------------------------- 647 648 void WinSalInstance::AcquireYieldMutex( sal_uLong nCount ) 649 { 650 ImplSalAcquireYieldMutex( nCount ); 651 } 652 653 // ----------------------------------------------------------------------- 654 655 static void ImplSalDispatchMessage( MSG* pMsg ) 656 { 657 SalData* pSalData = GetSalData(); 658 if ( pSalData->mpFirstObject ) 659 { 660 if ( ImplSalPreDispatchMsg( pMsg ) ) 661 return; 662 } 663 LRESULT lResult = ImplDispatchMessage( pMsg ); 664 if ( pSalData->mpFirstObject ) 665 ImplSalPostDispatchMsg( pMsg, lResult ); 666 } 667 668 // ----------------------------------------------------------------------- 669 670 void ImplSalYield( sal_Bool bWait, sal_Bool bHandleAllCurrentEvents ) 671 { 672 MSG aMsg; 673 bool bWasMsg = false, bOneEvent = false; 674 675 int nMaxEvents = bHandleAllCurrentEvents ? 100 : 1; 676 do 677 { 678 if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) ) 679 { 680 if ( !ImplInterceptChildWindowKeyDown( aMsg ) ) 681 { 682 TranslateMessage( &aMsg ); 683 ImplSalDispatchMessage( &aMsg ); 684 } 685 686 bOneEvent = bWasMsg = true; 687 } 688 else 689 bOneEvent = false; 690 } while( --nMaxEvents && bOneEvent ); 691 692 if ( bWait && ! bWasMsg ) 693 { 694 if ( ImplGetMessage( &aMsg, 0, 0, 0 ) ) 695 { 696 if ( !ImplInterceptChildWindowKeyDown( aMsg ) ) 697 { 698 TranslateMessage( &aMsg ); 699 ImplSalDispatchMessage( &aMsg ); 700 } 701 } 702 } 703 } 704 705 // ----------------------------------------------------------------------- 706 707 void WinSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents ) 708 { 709 SalYieldMutex* pYieldMutex = mpSalYieldMutex; 710 SalData* pSalData = GetSalData(); 711 DWORD nCurThreadId = GetCurrentThreadId(); 712 sal_uLong nCount = pYieldMutex->GetAcquireCount( nCurThreadId ); 713 sal_uLong n = nCount; 714 while ( n ) 715 { 716 pYieldMutex->release(); 717 n--; 718 } 719 if ( pSalData->mnAppThreadId != nCurThreadId ) 720 { 721 // #97739# A SendMessage call blocks until the called thread (here: the main thread) 722 // returns. During a yield however, messages are processed in the main thread that might 723 // result in a new message loop due to opening a dialog. Thus, SendMessage would not 724 // return which will block this thread! 725 // Solution: just give up the time slice and hope that messages are processed 726 // by the main thread anyway (where all windows are created) 727 // If the mainthread is not currently handling messages, then our SendMessage would 728 // also do nothing, so this seems to be reasonable. 729 730 // #i18883# only sleep if potential deadlock scenario, ie, when a dialog is open 731 if( ImplGetSVData()->maAppData.mnModalMode ) 732 Sleep(1); 733 else 734 ImplSendMessage( mhComWnd, SAL_MSG_THREADYIELD, (WPARAM)bWait, (LPARAM)bHandleAllCurrentEvents ); 735 736 n = nCount; 737 while ( n ) 738 { 739 pYieldMutex->acquire(); 740 n--; 741 } 742 } 743 else 744 { 745 ImplSalYield( bWait, bHandleAllCurrentEvents ); 746 747 n = nCount; 748 while ( n ) 749 { 750 ImplSalYieldMutexAcquireWithWait(); 751 n--; 752 } 753 } 754 } 755 756 // ----------------------------------------------------------------------- 757 758 LRESULT CALLBACK SalComWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef ) 759 { 760 LRESULT nRet = 0; 761 762 763 switch ( nMsg ) 764 { 765 case SAL_MSG_PRINTABORTJOB: 766 ImplSalPrinterAbortJobAsync( (HDC)wParam ); 767 rDef = FALSE; 768 break; 769 case SAL_MSG_THREADYIELD: 770 ImplSalYield( (sal_Bool)wParam, (sal_Bool)lParam ); 771 rDef = FALSE; 772 break; 773 // If we get this message, because another GetMessage() call 774 // has recieved this message, we must post this message to 775 // us again, because in the other case we wait forever. 776 case SAL_MSG_RELEASEWAITYIELD: 777 { 778 WinSalInstance* pInst = GetSalData()->mpFirstInstance; 779 if ( pInst && pInst->mnYieldWaitCount ) 780 ImplPostMessage( hWnd, SAL_MSG_RELEASEWAITYIELD, wParam, lParam ); 781 } 782 rDef = FALSE; 783 break; 784 case SAL_MSG_STARTTIMER: 785 ImplSalStartTimer( (sal_uLong) lParam, FALSE ); 786 rDef = FALSE; 787 break; 788 case SAL_MSG_CREATEFRAME: 789 nRet = (LRESULT)ImplSalCreateFrame( GetSalData()->mpFirstInstance, (HWND)lParam, (sal_uLong)wParam ); 790 rDef = FALSE; 791 break; 792 case SAL_MSG_RECREATEHWND: 793 nRet = (LRESULT)ImplSalReCreateHWND( (HWND)wParam, (HWND)lParam, FALSE ); 794 rDef = FALSE; 795 break; 796 case SAL_MSG_RECREATECHILDHWND: 797 nRet = (LRESULT)ImplSalReCreateHWND( (HWND)wParam, (HWND)lParam, TRUE ); 798 rDef = FALSE; 799 break; 800 case SAL_MSG_DESTROYFRAME: 801 delete (SalFrame*)lParam; 802 rDef = FALSE; 803 break; 804 case SAL_MSG_DESTROYHWND: 805 //We only destroy the native window here. We do NOT destroy the SalFrame contained 806 //in the structure (GetWindowPtr()). 807 if (DestroyWindow((HWND)lParam) == 0) 808 { 809 OSL_ENSURE(0, "DestroyWindow failed!"); 810 //Failure: We remove the SalFrame from the window structure. So we avoid that 811 // the window structure may contain an invalid pointer, once the SalFrame is deleted. 812 SetWindowPtr((HWND)lParam, 0); 813 } 814 rDef = FALSE; 815 break; 816 case SAL_MSG_CREATEOBJECT: 817 nRet = (LRESULT)ImplSalCreateObject( GetSalData()->mpFirstInstance, (WinSalFrame*)lParam ); 818 rDef = FALSE; 819 break; 820 case SAL_MSG_DESTROYOBJECT: 821 delete (SalObject*)lParam; 822 rDef = FALSE; 823 break; 824 case SAL_MSG_GETDC: 825 nRet = (LRESULT)GetDCEx( (HWND)wParam, 0, DCX_CACHE ); 826 rDef = FALSE; 827 break; 828 case SAL_MSG_RELEASEDC: 829 ReleaseDC( (HWND)wParam, (HDC)lParam ); 830 rDef = FALSE; 831 break; 832 case SAL_MSG_POSTTIMER: 833 SalTimerProc( 0, 0, SALTIMERPROC_RECURSIVE, lParam ); 834 break; 835 } 836 837 return nRet; 838 } 839 840 LRESULT CALLBACK SalComWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ) 841 { 842 int bDef = TRUE; 843 LRESULT nRet = 0; 844 #ifdef __MINGW32__ 845 jmp_buf jmpbuf; 846 __SEHandler han; 847 if (__builtin_setjmp(jmpbuf) == 0) 848 { 849 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER); 850 #else 851 __try 852 { 853 #endif 854 nRet = SalComWndProc( hWnd, nMsg, wParam, lParam, bDef ); 855 } 856 #ifdef __MINGW32__ 857 han.Reset(); 858 #else 859 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation())) 860 { 861 } 862 #endif 863 if ( bDef ) 864 { 865 if ( !ImplHandleGlobalMsg( hWnd, nMsg, wParam, lParam, nRet ) ) 866 nRet = DefWindowProcA( hWnd, nMsg, wParam, lParam ); 867 } 868 return nRet; 869 } 870 871 LRESULT CALLBACK SalComWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ) 872 { 873 int bDef = TRUE; 874 LRESULT nRet = 0; 875 #ifdef __MINGW32__ 876 jmp_buf jmpbuf; 877 __SEHandler han; 878 if (__builtin_setjmp(jmpbuf) == 0) 879 { 880 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER); 881 #else 882 __try 883 { 884 #endif 885 nRet = SalComWndProc( hWnd, nMsg, wParam, lParam, bDef ); 886 } 887 #ifdef __MINGW32__ 888 han.Reset(); 889 #else 890 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation())) 891 { 892 } 893 #endif 894 if ( bDef ) 895 { 896 if ( !ImplHandleGlobalMsg( hWnd, nMsg, wParam, lParam, nRet ) ) 897 nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam ); 898 } 899 return nRet; 900 } 901 902 // ----------------------------------------------------------------------- 903 904 bool WinSalInstance::AnyInput( sal_uInt16 nType ) 905 { 906 MSG aMsg; 907 908 if ( (nType & (INPUT_ANY)) == (INPUT_ANY) ) 909 { 910 // revert bugfix for #108919# which never reported timeouts when called from the timer handler 911 // which made the application completely unresponsive during background formatting 912 if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_NOREMOVE | PM_NOYIELD ) ) 913 return true; 914 } 915 else 916 { 917 if ( nType & INPUT_MOUSE ) 918 { 919 // Test for mouse input 920 if ( ImplPeekMessage( &aMsg, 0, WM_MOUSEFIRST, WM_MOUSELAST, 921 PM_NOREMOVE | PM_NOYIELD ) ) 922 return true; 923 } 924 925 if ( nType & INPUT_KEYBOARD ) 926 { 927 // Test for key input 928 if ( ImplPeekMessage( &aMsg, 0, WM_KEYDOWN, WM_KEYDOWN, 929 PM_NOREMOVE | PM_NOYIELD ) ) 930 { 931 if ( (aMsg.wParam == VK_SHIFT) || 932 (aMsg.wParam == VK_CONTROL) || 933 (aMsg.wParam == VK_MENU) ) 934 return false; 935 else 936 return true; 937 } 938 } 939 940 if ( nType & INPUT_PAINT ) 941 { 942 // Test for paint input 943 if ( ImplPeekMessage( &aMsg, 0, WM_PAINT, WM_PAINT, 944 PM_NOREMOVE | PM_NOYIELD ) ) 945 return true; 946 947 if ( ImplPeekMessage( &aMsg, 0, WM_SIZE, WM_SIZE, 948 PM_NOREMOVE | PM_NOYIELD ) ) 949 return true; 950 951 if ( ImplPeekMessage( &aMsg, 0, SAL_MSG_POSTCALLSIZE, SAL_MSG_POSTCALLSIZE, 952 PM_NOREMOVE | PM_NOYIELD ) ) 953 return true; 954 955 if ( ImplPeekMessage( &aMsg, 0, WM_MOVE, WM_MOVE, 956 PM_NOREMOVE | PM_NOYIELD ) ) 957 return true; 958 959 if ( ImplPeekMessage( &aMsg, 0, SAL_MSG_POSTMOVE, SAL_MSG_POSTMOVE, 960 PM_NOREMOVE | PM_NOYIELD ) ) 961 return true; 962 } 963 964 if ( nType & INPUT_TIMER ) 965 { 966 // Test for timer input 967 if ( ImplPeekMessage( &aMsg, 0, WM_TIMER, WM_TIMER, 968 PM_NOREMOVE | PM_NOYIELD ) ) 969 return true; 970 971 } 972 973 if ( nType & INPUT_OTHER ) 974 { 975 // Test for any input 976 if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_NOREMOVE | PM_NOYIELD ) ) 977 return true; 978 } 979 } 980 981 return FALSE; 982 } 983 984 // ----------------------------------------------------------------------- 985 986 void SalTimer::Start( sal_uLong nMS ) 987 { 988 // Um auf Main-Thread umzuschalten 989 SalData* pSalData = GetSalData(); 990 if ( pSalData->mpFirstInstance ) 991 { 992 if ( pSalData->mnAppThreadId != GetCurrentThreadId() ) 993 ImplPostMessage( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS ); 994 else 995 ImplSendMessage( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS ); 996 } 997 else 998 ImplSalStartTimer( nMS, FALSE ); 999 } 1000 1001 // ----------------------------------------------------------------------- 1002 1003 SalFrame* WinSalInstance::CreateChildFrame( SystemParentData* pSystemParentData, sal_uLong nSalFrameStyle ) 1004 { 1005 // Um auf Main-Thread umzuschalten 1006 return (SalFrame*)ImplSendMessage( mhComWnd, SAL_MSG_CREATEFRAME, nSalFrameStyle, (LPARAM)pSystemParentData->hWnd ); 1007 } 1008 1009 // ----------------------------------------------------------------------- 1010 1011 SalFrame* WinSalInstance::CreateFrame( SalFrame* pParent, sal_uLong nSalFrameStyle ) 1012 { 1013 // Um auf Main-Thread umzuschalten 1014 HWND hWndParent; 1015 if ( pParent ) 1016 hWndParent = static_cast<WinSalFrame*>(pParent)->mhWnd; 1017 else 1018 hWndParent = 0; 1019 return (SalFrame*)ImplSendMessage( mhComWnd, SAL_MSG_CREATEFRAME, nSalFrameStyle, (LPARAM)hWndParent ); 1020 } 1021 1022 // ----------------------------------------------------------------------- 1023 1024 void WinSalInstance::DestroyFrame( SalFrame* pFrame ) 1025 { 1026 ImplSendMessage( mhComWnd, SAL_MSG_DESTROYFRAME, 0, (LPARAM)pFrame ); 1027 } 1028 1029 // ----------------------------------------------------------------------- 1030 1031 SalObject* WinSalInstance::CreateObject( SalFrame* pParent, 1032 SystemWindowData* /*pWindowData*/, // SystemWindowData meaningless on Windows 1033 sal_Bool /*bShow*/ ) 1034 { 1035 // Um auf Main-Thread umzuschalten 1036 return (SalObject*)ImplSendMessage( mhComWnd, SAL_MSG_CREATEOBJECT, 0, (LPARAM)static_cast<WinSalFrame*>(pParent) ); 1037 } 1038 1039 // ----------------------------------------------------------------------- 1040 1041 void WinSalInstance::DestroyObject( SalObject* pObject ) 1042 { 1043 ImplSendMessage( mhComWnd, SAL_MSG_DESTROYOBJECT, 0, (LPARAM)pObject ); 1044 } 1045 1046 // ----------------------------------------------------------------------- 1047 1048 void* WinSalInstance::GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes ) 1049 { 1050 rReturnedBytes = 1; 1051 rReturnedType = AsciiCString; 1052 return const_cast<char *>(""); 1053 } 1054 1055 // ----------------------------------------------------------------------- 1056 1057 /** Add a file to the system shells recent document list if there is any. 1058 This function may have no effect under Unix because there is no 1059 standard API among the different desktop managers. 1060 1061 @param aFileUrl 1062 The file url of the document. 1063 */ 1064 void WinSalInstance::AddToRecentDocumentList(const rtl::OUString& rFileUrl, const rtl::OUString& /*rMimeType*/) 1065 { 1066 rtl::OUString system_path; 1067 osl::FileBase::RC rc = osl::FileBase::getSystemPathFromFileURL(rFileUrl, system_path); 1068 1069 OSL_ENSURE(osl::FileBase::E_None == rc, "Invalid file url"); 1070 1071 if (osl::FileBase::E_None == rc) 1072 SHAddToRecentDocs(SHARD_PATHW, system_path.getStr()); 1073 } 1074 1075 // ----------------------------------------------------------------------- 1076 1077 SalTimer* WinSalInstance::CreateSalTimer() 1078 { 1079 return new WinSalTimer(); 1080 } 1081 1082 // ----------------------------------------------------------------------- 1083 1084 SalBitmap* WinSalInstance::CreateSalBitmap() 1085 { 1086 return new WinSalBitmap(); 1087 } 1088 1089 class WinImeStatus : public SalI18NImeStatus 1090 { 1091 public: 1092 WinImeStatus() {} 1093 virtual ~WinImeStatus() {} 1094 1095 // asks whether there is a status window available 1096 // to toggle into menubar 1097 virtual bool canToggle() { return false; } 1098 virtual void toggle() {} 1099 }; 1100 1101 SalI18NImeStatus* WinSalInstance::CreateI18NImeStatus() 1102 { 1103 return new WinImeStatus(); 1104 } 1105 1106 // ----------------------------------------------------------------------- 1107 1108 const ::rtl::OUString& SalGetDesktopEnvironment() 1109 { 1110 static ::rtl::OUString aDesktopEnvironment( RTL_CONSTASCII_USTRINGPARAM( "Windows" ) ); 1111 return aDesktopEnvironment; 1112 } 1113 1114 SalSession* WinSalInstance::CreateSalSession() 1115 { 1116 return NULL; 1117 } 1118 1119 #ifndef __MINGW32__ 1120 // ----------------------------------------------------------------------- 1121 int WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(int, LPEXCEPTION_POINTERS pExceptionInfo) 1122 { 1123 // Decide if an exception is a c++ (mostly UNO) exception or a process violation. 1124 // Depending on this information we pass process violations directly to our signal handler ... 1125 // and c++ (UNO) exceptions are sended to the following code on the current stack. 1126 // Problem behind: user32.dll sometime consumes exceptions/process violations .-) 1127 // see also #112221# 1128 1129 static DWORD EXCEPTION_MSC_CPP_EXCEPTION = 0xE06D7363; 1130 1131 if (pExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_MSC_CPP_EXCEPTION) 1132 return EXCEPTION_CONTINUE_SEARCH; 1133 1134 return UnhandledExceptionFilter( pExceptionInfo ); 1135 } 1136 #endif 1137