1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
24 #include <osl/file.hxx>
25 #include <comphelper/solarmutex.hxx>
27 #include <tools/solarmutex.hxx>
29 #include <vcl/apptypes.hxx>
30 #include <vcl/opengl/OpenGLHelper.hxx>
31 #include <vcl/opengl/OpenGLContext.hxx>
32 #include <vcl/timer.hxx>
34 #include <opengl/salbmp.hxx>
35 #include <win/wincomp.hxx>
36 #include <win/salids.hrc>
37 #include <win/saldata.hxx>
38 #include <win/salinst.h>
39 #include <win/salframe.h>
40 #include <win/salobj.h>
41 #include <win/saltimer.h>
42 #include <win/salbmp.h>
44 #include <salimestatus.hxx>
49 #define min(a,b) (((a) < (b)) ? (a) : (b))
52 #define max(a,b) (((a) > (b)) ? (a) : (b))
57 #pragma warning(push, 1)
58 #pragma warning( disable: 4917 )
65 #define GetObject GetObjectA
69 #include <gdiplusenums.h>
70 #include <gdipluscolor.h>
73 #ifdef _WIN32_WINNT_WINBLUE
74 #include <VersionHelpers.h>
88 #include <sehandler.hxx>
91 void SalAbort( const OUString
& rErrorText
, bool )
95 if ( rErrorText
.isEmpty() )
97 // make sure crash reporter is triggered
98 RaiseException( 0, EXCEPTION_NONCONTINUABLE
, 0, NULL
);
99 FatalAppExitW( 0, L
"Application Error" );
103 // make sure crash reporter is triggered
104 RaiseException( 0, EXCEPTION_NONCONTINUABLE
, 0, NULL
);
105 FatalAppExitW( 0, reinterpret_cast<LPCWSTR
>(rErrorText
.getStr()) );
109 LRESULT CALLBACK
SalComWndProcW( HWND hWnd
, UINT nMsg
, WPARAM wParam
, LPARAM lParam
);
111 class SalYieldMutex
: public comphelper::SolarMutex
115 public: // for ImplSalYield()
116 WinSalInstance
* mpInstData
;
121 SalYieldMutex( WinSalInstance
* pInstData
);
123 virtual void acquire();
124 virtual void release();
125 virtual bool tryToAcquire();
127 sal_uLong
GetAcquireCount( sal_uLong nThreadId
);
130 SalYieldMutex::SalYieldMutex( WinSalInstance
* pInstData
)
132 mpInstData
= pInstData
;
137 void SalYieldMutex::acquire()
141 mnThreadId
= GetCurrentThreadId();
144 void SalYieldMutex::release()
146 DWORD nThreadId
= GetCurrentThreadId();
147 if ( mnThreadId
!= nThreadId
)
151 SalData
* pSalData
= GetSalData();
152 if ( pSalData
->mnAppThreadId
!= nThreadId
)
156 OpenGLContext::prepareForYield();
158 // If we don't call these message, the Output from the
159 // Java clients doesn't come in the right order
162 mpInstData
->mpSalWaitMutex
->acquire();
163 if ( mpInstData
->mnYieldWaitCount
)
164 PostMessageW( mpInstData
->mhComWnd
, SAL_MSG_RELEASEWAITYIELD
, 0, 0 );
168 mpInstData
->mpSalWaitMutex
->release();
181 OpenGLContext::prepareForYield();
189 bool SalYieldMutex::tryToAcquire()
191 if( m_mutex
.tryToAcquire() )
194 mnThreadId
= GetCurrentThreadId();
201 sal_uLong
SalYieldMutex::GetAcquireCount( sal_uLong nThreadId
)
203 if ( nThreadId
== mnThreadId
)
209 void ImplSalYieldMutexAcquireWithWait()
211 WinSalInstance
* pInst
= GetSalData()->mpFirstInstance
;
215 // If we are the main thread, then we must wait with wait, because
216 // in if we don't reschedule, then we create deadlocks if a Windows
217 // Function is called from another thread. If we aren't the main thread,
218 // than we call acquire directly.
219 DWORD nThreadId
= GetCurrentThreadId();
220 SalData
* pSalData
= GetSalData();
221 if ( pSalData
->mnAppThreadId
== nThreadId
)
223 // wait till we get the Mutex
224 bool bAcquire
= FALSE
;
227 if ( pInst
->mpSalYieldMutex
->tryToAcquire() )
231 pInst
->mpSalWaitMutex
->acquire();
232 if ( pInst
->mpSalYieldMutex
->tryToAcquire() )
235 pInst
->mpSalWaitMutex
->release();
239 pInst
->mnYieldWaitCount
++;
240 pInst
->mpSalWaitMutex
->release();
242 GetMessageW( &aTmpMsg
, pInst
->mhComWnd
, SAL_MSG_RELEASEWAITYIELD
, SAL_MSG_RELEASEWAITYIELD
);
243 pInst
->mnYieldWaitCount
--;
244 if ( pInst
->mnYieldWaitCount
)
245 PostMessageW( pInst
->mhComWnd
, SAL_MSG_RELEASEWAITYIELD
, 0, 0 );
252 pInst
->mpSalYieldMutex
->acquire();
255 bool ImplSalYieldMutexTryToAcquire()
257 WinSalInstance
* pInst
= GetSalData()->mpFirstInstance
;
259 return pInst
->mpSalYieldMutex
->tryToAcquire();
264 void ImplSalYieldMutexRelease()
266 WinSalInstance
* pInst
= GetSalData()->mpFirstInstance
;
270 pInst
->mpSalYieldMutex
->release();
274 sal_uLong
ImplSalReleaseYieldMutex()
276 WinSalInstance
* pInst
= GetSalData()->mpFirstInstance
;
280 SalYieldMutex
* pYieldMutex
= pInst
->mpSalYieldMutex
;
281 sal_uLong nCount
= pYieldMutex
->GetAcquireCount( GetCurrentThreadId() );
282 sal_uLong n
= nCount
;
285 pYieldMutex
->release();
292 void ImplSalAcquireYieldMutex( sal_uLong nCount
)
294 WinSalInstance
* pInst
= GetSalData()->mpFirstInstance
;
298 SalYieldMutex
* pYieldMutex
= pInst
->mpSalYieldMutex
;
301 pYieldMutex
->acquire();
306 bool WinSalInstance::CheckYieldMutex()
308 SalData
* pSalData
= GetSalData();
309 if ( pSalData
->mpFirstInstance
)
311 SalYieldMutex
* pYieldMutex
= pSalData
->mpFirstInstance
->mpSalYieldMutex
;
312 return (pYieldMutex
->mnThreadId
== (GetCurrentThreadId()));
317 void SalData::initKeyCodeMap()
319 UINT nKey
= 0xffffffff;
320 #define initKey( a, b )\
321 nKey = LOWORD( VkKeyScan( a ) );\
325 initKey( '+', KEY_ADD
);
326 initKey( '-', KEY_SUBTRACT
);
327 initKey( '*', KEY_MULTIPLY
);
328 initKey( '/', KEY_DIVIDE
);
329 initKey( '.', KEY_POINT
);
330 initKey( ',', KEY_COMMA
);
331 initKey( '<', KEY_LESS
);
332 initKey( '>', KEY_GREATER
);
333 initKey( '=', KEY_EQUAL
);
334 initKey( '~', KEY_TILDE
);
335 initKey( '`', KEY_QUOTELEFT
);
336 initKey( '[', KEY_BRACKETLEFT
);
337 initKey( ']', KEY_BRACKETRIGHT
);
338 initKey( ';', KEY_SEMICOLON
);
339 initKey( '\'', KEY_QUOTERIGHT
);
346 mhInst
= 0; // default instance handle
347 mnCmdShow
= 0; // default frame show style
348 mhDitherPal
= 0; // dither palette
349 mhDitherDIB
= 0; // dither memory handle
350 mpDitherDIB
= 0; // dither memory
351 mpDitherDIBData
= 0; // beginning of DIB data
352 mpDitherDiff
= 0; // Dither mapping table
353 mpDitherLow
= 0; // Dither mapping table
354 mpDitherHigh
= 0; // Dither mapping table
355 mnTimerMS
= 0; // Current Time (in MS) of the Timer
356 mnTimerOrgMS
= 0; // Current Original Time (in MS)
359 mnTimerId
= 0; // windows timer id
360 mhSalObjMsgHook
= 0; // hook to get interesting msg for SalObject
361 mhWantLeaveMsg
= 0; // window handle, that want a MOUSELEAVE message
362 mpMouseLeaveTimer
= 0; // Timer for MouseLeave Test
363 mpFirstInstance
= 0; // pointer of first instance
364 mpFirstFrame
= 0; // pointer of first frame
365 mpFirstObject
= 0; // pointer of first object window
366 mpFirstVD
= 0; // first VirDev
367 mpFirstPrinter
= 0; // first printing printer
368 mpHDCCache
= 0; // Cache for three DC's
369 mh50Bmp
= 0; // 50% Bitmap
370 mh50Brush
= 0; // 50% Brush
372 for(i
=0; i
<MAX_STOCKPEN
; i
++)
374 maStockPenColorAry
[i
] = 0;
375 mhStockPenAry
[i
] = 0;
377 for(i
=0; i
<MAX_STOCKBRUSH
; i
++)
379 maStockBrushColorAry
[i
] = 0;
380 mhStockBrushAry
[i
] = 0;
382 mnStockPenCount
= 0; // count of static pens
383 mnStockBrushCount
= 0; // count of static brushes
384 mnSalObjWantKeyEvt
= 0; // KeyEvent for the SalObj hook
385 mnCacheDCInUse
= 0; // count of CacheDC in use
386 mbObjClassInit
= FALSE
; // is SALOBJECTCLASS initialised
387 mbInPalChange
= FALSE
; // is in WM_QUERYNEWPALETTE
388 mnAppThreadId
= 0; // Id from Applikation-Thread
389 mbScrSvrEnabled
= FALSE
; // ScreenSaver enabled
390 mnSageStatus
= 0; // status of Sage-DLL (DISABLE_AGENT == not available)
391 mpSageEnableProc
= 0; // funktion to deactivate the system agent
392 mpFirstIcon
= 0; // icon cache, points to first icon, NULL if none
394 mbThemeChanged
= FALSE
; // true if visual theme was changed: throw away theme handles
395 mbThemeMenuSupport
= FALSE
;
400 mpDwmIsCompositionEnabled
= 0;
416 SalData
* pSalData
= new SalData
;
417 CoInitialize(0); // put main thread in Single Threaded Apartment (STA)
420 static Gdiplus::GdiplusStartupInput gdiplusStartupInput
;
421 Gdiplus::GdiplusStartup(&pSalData
->gdiplusToken
, &gdiplusStartupInput
, NULL
);
427 SalData
* pSalData
= GetSalData();
432 Gdiplus::GdiplusShutdown(pSalData
->gdiplusToken
);
440 // remember data, copied from WinMain
441 SalData
* pData
= GetSalData();
442 if ( pData
) // Im AppServer NULL
445 aSI
.cb
= sizeof( aSI
);
446 GetStartupInfo( &aSI
);
447 pData
->mhInst
= GetModuleHandle( NULL
);
448 pData
->mnCmdShow
= aSI
.wShowWindow
;
452 SalInstance
* CreateSalInstance()
454 SalData
* pSalData
= GetSalData();
456 // determine the windows version
457 aSalShlData
.mbWXP
= 0;
458 aSalShlData
.mbWVista
= 0;
459 aSalShlData
.mbW7
= 0;
460 // the Win32 SDK 8.1 deprecates GetVersionEx()
461 #ifdef _WIN32_WINNT_WINBLUE
462 aSalShlData
.mbWXP
= IsWindowsXPOrGreater() ? 1 : 0;
463 aSalShlData
.mbWVista
= IsWindowsVistaOrGreater() ? 1 : 0;
464 aSalShlData
.mbW7
= IsWindows7OrGreater() ? 1 : 0;
466 OSVERSIONINFO aVersionInfo
;
467 memset( &aVersionInfo
, 0, sizeof(aVersionInfo
) );
468 aVersionInfo
.dwOSVersionInfoSize
= sizeof( aVersionInfo
);
469 if (GetVersionEx( &aVersionInfo
))
472 if (aVersionInfo
.dwMajorVersion
> 5 ||
473 (aVersionInfo
.dwMajorVersion
== 5 && aVersionInfo
.dwMinorVersion
>= 1))
474 aSalShlData
.mbWXP
= 1;
476 if (aVersionInfo
.dwMajorVersion
>= 6)
477 aSalShlData
.mbWVista
= 1;
479 if (aVersionInfo
.dwMajorVersion
> 6 ||
480 (aVersionInfo
.dwMajorVersion
== 6 && aVersionInfo
.dwMinorVersion
>= 1))
481 aSalShlData
.mbW7
= 1;
485 pSalData
->mnAppThreadId
= GetCurrentThreadId();
487 // register frame class
488 WNDCLASSEXW aWndClassEx
;
489 aWndClassEx
.cbSize
= sizeof( aWndClassEx
);
490 aWndClassEx
.style
= CS_OWNDC
;
491 aWndClassEx
.lpfnWndProc
= SalFrameWndProcW
;
492 aWndClassEx
.cbClsExtra
= 0;
493 aWndClassEx
.cbWndExtra
= SAL_FRAME_WNDEXTRA
;
494 aWndClassEx
.hInstance
= pSalData
->mhInst
;
495 aWndClassEx
.hCursor
= 0;
496 aWndClassEx
.hbrBackground
= 0;
497 aWndClassEx
.lpszMenuName
= 0;
498 aWndClassEx
.lpszClassName
= SAL_FRAME_CLASSNAMEW
;
499 ImplLoadSalIcon( SAL_RESID_ICON_DEFAULT
, aWndClassEx
.hIcon
, aWndClassEx
.hIconSm
);
500 if ( !RegisterClassExW( &aWndClassEx
) )
503 aWndClassEx
.hIcon
= 0;
504 aWndClassEx
.hIconSm
= 0;
505 aWndClassEx
.style
|= CS_SAVEBITS
;
506 aWndClassEx
.lpszClassName
= SAL_SUBFRAME_CLASSNAMEW
;
507 if ( !RegisterClassExW( &aWndClassEx
) )
510 // shadow effect for popups on XP
511 if( aSalShlData
.mbWXP
)
512 aWndClassEx
.style
|= CS_DROPSHADOW
;
513 aWndClassEx
.lpszClassName
= SAL_TMPSUBFRAME_CLASSNAMEW
;
514 if ( !RegisterClassExW( &aWndClassEx
) )
517 aWndClassEx
.style
= 0;
518 aWndClassEx
.lpfnWndProc
= SalComWndProcW
;
519 aWndClassEx
.cbWndExtra
= 0;
520 aWndClassEx
.lpszClassName
= SAL_COM_CLASSNAMEW
;
521 if ( !RegisterClassExW( &aWndClassEx
) )
524 HWND hComWnd
= CreateWindowExW( WS_EX_TOOLWINDOW
, SAL_COM_CLASSNAMEW
,
525 L
"", WS_POPUP
, 0, 0, 0, 0, 0, 0,
526 pSalData
->mhInst
, NULL
);
530 WinSalInstance
* pInst
= new WinSalInstance
;
532 // init instance (only one instance in this version !!!)
533 pSalData
->mpFirstInstance
= pInst
;
534 pInst
->mhInst
= pSalData
->mhInst
;
535 pInst
->mhComWnd
= hComWnd
;
537 // init static GDI Data
543 void DestroySalInstance( SalInstance
* pInst
)
545 SalData
* pSalData
= GetSalData();
547 // (only one instance in this version !!!)
552 if ( pSalData
->mpFirstInstance
== pInst
)
553 pSalData
->mpFirstInstance
= NULL
;
558 WinSalInstance::WinSalInstance()
561 mpSalYieldMutex
= new SalYieldMutex( this );
562 mpSalWaitMutex
= new osl::Mutex
;
563 mnYieldWaitCount
= 0;
564 mpSalYieldMutex
->acquire();
565 ::tools::SolarMutex::SetSolarMutex( mpSalYieldMutex
);
568 WinSalInstance::~WinSalInstance()
570 ::tools::SolarMutex::SetSolarMutex( 0 );
571 mpSalYieldMutex
->release();
572 delete mpSalYieldMutex
;
573 delete mpSalWaitMutex
;
574 DestroyWindow( mhComWnd
);
577 comphelper::SolarMutex
* WinSalInstance::GetYieldMutex()
579 return mpSalYieldMutex
;
582 sal_uLong
WinSalInstance::ReleaseYieldMutex()
584 return ImplSalReleaseYieldMutex();
587 void WinSalInstance::AcquireYieldMutex( sal_uLong nCount
)
589 ImplSalAcquireYieldMutex( nCount
);
592 static void ImplSalDispatchMessage( MSG
* pMsg
)
594 SalData
* pSalData
= GetSalData();
595 if ( pSalData
->mpFirstObject
)
597 if ( ImplSalPreDispatchMsg( pMsg
) )
600 LRESULT lResult
= DispatchMessageW( pMsg
);
601 if ( pSalData
->mpFirstObject
)
602 ImplSalPostDispatchMsg( pMsg
, lResult
);
605 void ImplSalYield( bool bWait
, bool bHandleAllCurrentEvents
)
608 bool bWasMsg
= false, bOneEvent
= false;
610 int nMaxEvents
= bHandleAllCurrentEvents
? 100 : 1;
613 if ( PeekMessageW( &aMsg
, 0, 0, 0, PM_REMOVE
) )
615 TranslateMessage( &aMsg
);
616 ImplSalDispatchMessage( &aMsg
);
618 bOneEvent
= bWasMsg
= true;
622 } while( --nMaxEvents
&& bOneEvent
);
624 if ( bWait
&& ! bWasMsg
)
626 if ( GetMessageW( &aMsg
, 0, 0, 0 ) )
628 TranslateMessage( &aMsg
);
629 ImplSalDispatchMessage( &aMsg
);
634 void WinSalInstance::Yield( bool bWait
, bool bHandleAllCurrentEvents
)
636 SalYieldMutex
* pYieldMutex
= mpSalYieldMutex
;
637 SalData
* pSalData
= GetSalData();
638 DWORD nCurThreadId
= GetCurrentThreadId();
639 sal_uLong nCount
= pYieldMutex
->GetAcquireCount( nCurThreadId
);
640 sal_uLong n
= nCount
;
643 pYieldMutex
->release();
646 if ( pSalData
->mnAppThreadId
!= nCurThreadId
)
648 // #97739# A SendMessage call blocks until the called thread (here: the main thread)
649 // returns. During a yield however, messages are processed in the main thread that might
650 // result in a new message loop due to opening a dialog. Thus, SendMessage would not
651 // return which will block this thread!
652 // Solution: just give up the time slice and hope that messages are processed
653 // by the main thread anyway (where all windows are created)
654 // If the mainthread is not currently handling messages, then our SendMessage would
655 // also do nothing, so this seems to be reasonable.
657 // #i18883# only sleep if potential deadlock scenario, ie, when a dialog is open
658 if( ImplGetSVData()->maAppData
.mnModalMode
)
661 SendMessageW( mhComWnd
, SAL_MSG_THREADYIELD
, (WPARAM
)bWait
, (LPARAM
)bHandleAllCurrentEvents
);
666 pYieldMutex
->acquire();
672 ImplSalYield( bWait
, bHandleAllCurrentEvents
);
677 ImplSalYieldMutexAcquireWithWait();
683 LRESULT CALLBACK
SalComWndProc( HWND hWnd
, UINT nMsg
, WPARAM wParam
, LPARAM lParam
, int& rDef
)
689 case SAL_MSG_PRINTABORTJOB
:
690 ImplSalPrinterAbortJobAsync( (HDC
)wParam
);
693 case SAL_MSG_THREADYIELD
:
694 ImplSalYield( (bool)wParam
, (bool)lParam
);
697 // If we get this message, because another GetMessage() call
698 // has received this message, we must post this message to
699 // us again, because in the other case we wait forever.
700 case SAL_MSG_RELEASEWAITYIELD
:
702 WinSalInstance
* pInst
= GetSalData()->mpFirstInstance
;
703 if ( pInst
&& pInst
->mnYieldWaitCount
)
704 PostMessageW( hWnd
, SAL_MSG_RELEASEWAITYIELD
, wParam
, lParam
);
708 case SAL_MSG_STARTTIMER
:
709 ImplSalStartTimer( (sal_uLong
) lParam
, FALSE
);
712 case SAL_MSG_CREATEFRAME
:
713 nRet
= (LRESULT
)ImplSalCreateFrame( GetSalData()->mpFirstInstance
, (HWND
)lParam
, (sal_uLong
)wParam
);
716 case SAL_MSG_RECREATEHWND
:
717 nRet
= (LRESULT
)ImplSalReCreateHWND( (HWND
)wParam
, (HWND
)lParam
, FALSE
);
720 case SAL_MSG_RECREATECHILDHWND
:
721 nRet
= (LRESULT
)ImplSalReCreateHWND( (HWND
)wParam
, (HWND
)lParam
, TRUE
);
724 case SAL_MSG_DESTROYFRAME
:
725 delete (SalFrame
*)lParam
;
728 case SAL_MSG_DESTROYHWND
:
729 //We only destroy the native window here. We do NOT destroy the SalFrame contained
730 //in the structure (GetWindowPtr()).
731 if (DestroyWindow((HWND
)lParam
) == 0)
733 OSL_FAIL("DestroyWindow failed!");
734 //Failure: We remove the SalFrame from the window structure. So we avoid that
735 // the window structure may contain an invalid pointer, once the SalFrame is deleted.
736 SetWindowPtr((HWND
)lParam
, 0);
740 case SAL_MSG_CREATEOBJECT
:
741 nRet
= (LRESULT
)ImplSalCreateObject( GetSalData()->mpFirstInstance
, (WinSalFrame
*)lParam
);
744 case SAL_MSG_DESTROYOBJECT
:
745 delete (SalObject
*)lParam
;
749 nRet
= (LRESULT
)GetDCEx( (HWND
)wParam
, 0, DCX_CACHE
);
752 case SAL_MSG_RELEASEDC
:
753 ReleaseDC( (HWND
)wParam
, (HDC
)lParam
);
756 case SAL_MSG_POSTTIMER
:
759 case SAL_MSG_TIMER_CALLBACK
:
762 while (PeekMessageW(&aMsg
, 0, SAL_MSG_TIMER_CALLBACK
, SAL_MSG_TIMER_CALLBACK
, PM_REMOVE
))
764 // nothing; just remove all the SAL_MSG_TIMER_CALLBACKs that
765 // accumulated in the queue during the EmitTimerCallback(),
766 // otherwise it happens with short timeouts and long callbacks
767 // that no other events will ever be processed, as the queue
768 // is full of SAL_MSG_TIMER_CALLBACKs.
769 // It is impossible to limit the amount of them being emitted
770 // in the first place, as they are emitted asynchronously, but
771 // here we are already fully synchronized.
779 LRESULT CALLBACK
SalComWndProcW( HWND hWnd
, UINT nMsg
, WPARAM wParam
, LPARAM lParam
)
783 #if defined ( __MINGW32__ ) && !defined ( _WIN64 )
786 if (__builtin_setjmp(jmpbuf
) == 0)
788 han
.Set(jmpbuf
, NULL
, (__SEHandler::PF
)EXCEPTION_EXECUTE_HANDLER
);
793 nRet
= SalComWndProc( hWnd
, nMsg
, wParam
, lParam
, bDef
);
795 #if defined ( __MINGW32__ ) && !defined ( _WIN64 )
798 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
804 if ( !ImplHandleGlobalMsg( hWnd
, nMsg
, wParam
, lParam
, nRet
) )
805 nRet
= DefWindowProcW( hWnd
, nMsg
, wParam
, lParam
);
810 bool WinSalInstance::AnyInput( VclInputFlags nType
)
814 if ( (nType
& VCL_INPUT_ANY
) == VCL_INPUT_ANY
)
816 // revert bugfix for #108919# which never reported timeouts when called from the timer handler
817 // which made the application completely unresponsive during background formatting
818 if ( PeekMessageW( &aMsg
, 0, 0, 0, PM_NOREMOVE
| PM_NOYIELD
) )
823 if ( nType
& VclInputFlags::MOUSE
)
825 // Test for mouse input
826 if ( PeekMessageW( &aMsg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
,
827 PM_NOREMOVE
| PM_NOYIELD
) )
831 if ( nType
& VclInputFlags::KEYBOARD
)
833 // Test for key input
834 if ( PeekMessageW( &aMsg
, 0, WM_KEYDOWN
, WM_KEYDOWN
,
835 PM_NOREMOVE
| PM_NOYIELD
) )
837 if ( (aMsg
.wParam
== VK_SHIFT
) ||
838 (aMsg
.wParam
== VK_CONTROL
) ||
839 (aMsg
.wParam
== VK_MENU
) )
846 if ( nType
& VclInputFlags::PAINT
)
848 // Test for paint input
849 if ( PeekMessageW( &aMsg
, 0, WM_PAINT
, WM_PAINT
,
850 PM_NOREMOVE
| PM_NOYIELD
) )
853 if ( PeekMessageW( &aMsg
, 0, WM_SIZE
, WM_SIZE
,
854 PM_NOREMOVE
| PM_NOYIELD
) )
857 if ( PeekMessageW( &aMsg
, 0, SAL_MSG_POSTCALLSIZE
, SAL_MSG_POSTCALLSIZE
,
858 PM_NOREMOVE
| PM_NOYIELD
) )
861 if ( PeekMessageW( &aMsg
, 0, WM_MOVE
, WM_MOVE
,
862 PM_NOREMOVE
| PM_NOYIELD
) )
865 if ( PeekMessageW( &aMsg
, 0, SAL_MSG_POSTMOVE
, SAL_MSG_POSTMOVE
,
866 PM_NOREMOVE
| PM_NOYIELD
) )
870 if ( nType
& VclInputFlags::TIMER
)
872 // Test for timer input
873 if ( PeekMessageW( &aMsg
, 0, WM_TIMER
, WM_TIMER
,
874 PM_NOREMOVE
| PM_NOYIELD
) )
879 if ( nType
& VclInputFlags::OTHER
)
881 // Test for any input
882 if ( PeekMessageW( &aMsg
, 0, 0, 0, PM_NOREMOVE
| PM_NOYIELD
) )
890 void SalTimer::Start( sal_uLong nMS
)
892 // to switch to Main-Thread
893 SalData
* pSalData
= GetSalData();
894 if ( pSalData
->mpFirstInstance
)
896 if ( pSalData
->mnAppThreadId
!= GetCurrentThreadId() )
897 PostMessageW( pSalData
->mpFirstInstance
->mhComWnd
, SAL_MSG_STARTTIMER
, 0, (LPARAM
)nMS
);
899 SendMessageW( pSalData
->mpFirstInstance
->mhComWnd
, SAL_MSG_STARTTIMER
, 0, (LPARAM
)nMS
);
902 ImplSalStartTimer( nMS
, FALSE
);
905 SalFrame
* WinSalInstance::CreateChildFrame( SystemParentData
* pSystemParentData
, sal_uLong nSalFrameStyle
)
907 // to switch to Main-Thread
908 return (SalFrame
*)(sal_IntPtr
)SendMessageW( mhComWnd
, SAL_MSG_CREATEFRAME
, nSalFrameStyle
, (LPARAM
)pSystemParentData
->hWnd
);
911 SalFrame
* WinSalInstance::CreateFrame( SalFrame
* pParent
, sal_uLong nSalFrameStyle
)
913 // to switch to Main-Thread
916 hWndParent
= static_cast<WinSalFrame
*>(pParent
)->mhWnd
;
919 return (SalFrame
*)(sal_IntPtr
)SendMessageW( mhComWnd
, SAL_MSG_CREATEFRAME
, nSalFrameStyle
, (LPARAM
)hWndParent
);
922 void WinSalInstance::DestroyFrame( SalFrame
* pFrame
)
924 OpenGLContext::prepareForYield();
925 SendMessageW( mhComWnd
, SAL_MSG_DESTROYFRAME
, 0, (LPARAM
)pFrame
);
928 SalObject
* WinSalInstance::CreateObject( SalFrame
* pParent
,
929 SystemWindowData
* /*pWindowData*/, // SystemWindowData meaningless on Windows
932 // to switch to Main-Thread
933 return (SalObject
*)(sal_IntPtr
)SendMessageW( mhComWnd
, SAL_MSG_CREATEOBJECT
, 0, (LPARAM
)static_cast<WinSalFrame
*>(pParent
) );
936 void WinSalInstance::DestroyObject( SalObject
* pObject
)
938 SendMessageW( mhComWnd
, SAL_MSG_DESTROYOBJECT
, 0, (LPARAM
)pObject
);
941 void* WinSalInstance::GetConnectionIdentifier( ConnectionIdentifierType
& rReturnedType
, int& rReturnedBytes
)
944 rReturnedType
= AsciiCString
;
945 return const_cast<char *>("");
948 /** Add a file to the system shells recent document list if there is any.
949 This function may have no effect under Unix because there is no
950 standard API among the different desktop managers.
953 The file url of the document.
955 void WinSalInstance::AddToRecentDocumentList(const OUString
& rFileUrl
, const OUString
& /*rMimeType*/, const OUString
& rDocumentService
)
957 OUString system_path
;
958 osl::FileBase::RC rc
= osl::FileBase::getSystemPathFromFileURL(rFileUrl
, system_path
);
960 OSL_ENSURE(osl::FileBase::E_None
== rc
, "Invalid file url");
962 if (osl::FileBase::E_None
== rc
)
964 if ( aSalShlData
.mbW7
)
966 typedef HRESULT ( WINAPI
*SHCREATEITEMFROMPARSINGNAME
)( PCWSTR
, IBindCtx
*, REFIID
, void **ppv
);
967 SHCREATEITEMFROMPARSINGNAME pSHCreateItemFromParsingName
=
968 ( SHCREATEITEMFROMPARSINGNAME
)GetProcAddress(
969 GetModuleHandleW (L
"shell32.dll"), "SHCreateItemFromParsingName" );
971 if( pSHCreateItemFromParsingName
)
973 IShellItem
* pShellItem
= NULL
;
975 HRESULT hr
= pSHCreateItemFromParsingName ( (PCWSTR
) system_path
.getStr(), NULL
, IID_PPV_ARGS(&pShellItem
) );
977 if ( SUCCEEDED(hr
) && pShellItem
)
979 OUString sApplicationName
;
981 if ( rDocumentService
== "com.sun.star.text.TextDocument" ||
982 rDocumentService
== "com.sun.star.text.GlobalDocument" ||
983 rDocumentService
== "com.sun.star.text.WebDocument" ||
984 rDocumentService
== "com.sun.star.xforms.XMLFormDocument" )
985 sApplicationName
= "Writer";
986 else if ( rDocumentService
== "com.sun.star.sheet.SpreadsheetDocument" ||
987 rDocumentService
== "com.sun.star.chart2.ChartDocument" )
988 sApplicationName
= "Calc";
989 else if ( rDocumentService
== "com.sun.star.presentation.PresentationDocument" )
990 sApplicationName
= "Impress";
991 else if ( rDocumentService
== "com.sun.star.drawing.DrawingDocument" )
992 sApplicationName
= "Draw";
993 else if ( rDocumentService
== "com.sun.star.formula.FormulaProperties" )
994 sApplicationName
= "Math";
995 else if ( rDocumentService
== "com.sun.star.sdb.DatabaseDocument" ||
996 rDocumentService
== "com.sun.star.sdb.OfficeDatabaseDocument" ||
997 rDocumentService
== "com.sun.star.sdb.RelationDesign" ||
998 rDocumentService
== "com.sun.star.sdb.QueryDesign" ||
999 rDocumentService
== "com.sun.star.sdb.TableDesign" ||
1000 rDocumentService
== "com.sun.star.sdb.DataSourceBrowser" )
1001 sApplicationName
= "Base";
1003 if ( !sApplicationName
.isEmpty() )
1005 OUString
sApplicationID("TheDocumentFoundation.LibreOffice.");
1006 sApplicationID
+= sApplicationName
;
1008 #if _WIN32_WINNT < _WIN32_WINNT_WIN7
1009 // just define Windows 7 only constant locally...
1010 #define SHARD_APPIDINFO 0x00000004
1016 } DummyShardAppIDInfo
;
1018 DummyShardAppIDInfo info
;
1019 info
.psi
= pShellItem
;
1020 info
.pszAppID
= (PCWSTR
) sApplicationID
.getStr();
1022 SHAddToRecentDocs ( SHARD_APPIDINFO
, &info
);
1028 // For whatever reason, we could not use the SHARD_APPIDINFO semantics
1029 SHAddToRecentDocs(SHARD_PATHW
, (PCWSTR
) system_path
.getStr());
1033 SalTimer
* WinSalInstance::CreateSalTimer()
1035 return new WinSalTimer();
1038 SalBitmap
* WinSalInstance::CreateSalBitmap()
1040 if (OpenGLHelper::isVCLOpenGLEnabled())
1041 return new OpenGLSalBitmap();
1043 return new WinSalBitmap();
1046 class WinImeStatus
: public SalI18NImeStatus
1050 virtual ~WinImeStatus() {}
1052 // asks whether there is a status window available
1053 // to toggle into menubar
1054 virtual bool canToggle() { return false; }
1055 virtual void toggle() {}
1058 SalI18NImeStatus
* WinSalInstance::CreateI18NImeStatus()
1060 return new WinImeStatus();
1063 const OUString
& SalGetDesktopEnvironment()
1065 static OUString
aDesktopEnvironment( "Windows" );
1066 return aDesktopEnvironment
;
1069 SalSession
* WinSalInstance::CreateSalSession()
1074 #if !defined ( __MINGW32__ ) || defined ( _WIN64 )
1076 int WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(int, LPEXCEPTION_POINTERS pExceptionInfo
)
1078 // Decide if an exception is a c++ (mostly UNO) exception or a process violation.
1079 // Depending on this information we pass process violations directly to our signal handler ...
1080 // and c++ (UNO) exceptions are sended to the following code on the current stack.
1081 // Problem behind: user32.dll sometime consumes exceptions/process violations .-)
1082 // see also #112221#
1084 static DWORD EXCEPTION_MSC_CPP_EXCEPTION
= 0xE06D7363;
1086 if (pExceptionInfo
->ExceptionRecord
->ExceptionCode
== EXCEPTION_MSC_CPP_EXCEPTION
)
1087 return EXCEPTION_CONTINUE_SEARCH
;
1089 return UnhandledExceptionFilter( pExceptionInfo
);
1093 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */