1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
32 #include <tools/svwin.h>
39 #include <osl/file.hxx>
40 #include <vos/mutex.hxx>
41 #include <tools/debug.hxx>
42 #include <wincomp.hxx>
44 #include <saldata.hxx>
48 #include <vcl/salsys.hxx>
50 #include <vcl/apptypes.hxx>
52 #include <vcl/salimestatus.hxx>
53 #include <vcl/timer.hxx>
54 #include <wincomp.hxx> // CS_DROPSHADOW
55 #include <tools/solarmutex.hxx>
58 #define min(a,b) (((a) < (b)) ? (a) : (b))
61 #define max(a,b) (((a) > (b)) ? (a) : (b))
65 #pragma warning(push, 1)
66 #pragma warning( disable: 4917 )
70 #include <GdiPlusEnums.h>
71 #include <GdiPlusColor.h>
78 // =======================================================================
80 void SalAbort( const XubString
& rErrorText
)
84 if ( !rErrorText
.Len() )
86 // #112255# make sure crash reporter is triggered
87 RaiseException( 0, EXCEPTION_NONCONTINUABLE
, 0, NULL
);
88 FatalAppExit( 0, "Application Error" );
92 // #112255# make sure crash reporter is triggered
93 RaiseException( 0, EXCEPTION_NONCONTINUABLE
, 0, NULL
);
94 ByteString
aErrorText( ImplSalGetWinAnsiString( rErrorText
) );
95 FatalAppExit( 0, aErrorText
.GetBuffer() );
99 // =======================================================================
101 LRESULT CALLBACK
SalComWndProcA( HWND hWnd
, UINT nMsg
, WPARAM wParam
, LPARAM lParam
);
102 LRESULT CALLBACK
SalComWndProcW( HWND hWnd
, UINT nMsg
, WPARAM wParam
, LPARAM lParam
);
104 // =======================================================================
106 class SalYieldMutex
: public vos::OMutex
108 public: // for ImplSalYield()
109 WinSalInstance
* mpInstData
;
114 SalYieldMutex( WinSalInstance
* pInstData
);
116 virtual void SAL_CALL
acquire();
117 virtual void SAL_CALL
release();
118 virtual sal_Bool SAL_CALL
tryToAcquire();
120 sal_uLong
GetAcquireCount( sal_uLong nThreadId
);
123 // -----------------------------------------------------------------------
125 SalYieldMutex::SalYieldMutex( WinSalInstance
* pInstData
)
127 mpInstData
= pInstData
;
132 // -----------------------------------------------------------------------
134 void SAL_CALL
SalYieldMutex::acquire()
138 mnThreadId
= GetCurrentThreadId();
141 // -----------------------------------------------------------------------
143 void SAL_CALL
SalYieldMutex::release()
145 DWORD nThreadId
= GetCurrentThreadId();
146 if ( mnThreadId
!= nThreadId
)
150 SalData
* pSalData
= GetSalData();
151 if ( pSalData
->mnAppThreadId
!= nThreadId
)
155 // If we don't call these message, the Output from the
156 // Java clients doesn't come in the right order
159 mpInstData
->mpSalWaitMutex
->acquire();
160 if ( mpInstData
->mnYieldWaitCount
)
161 ImplPostMessage( mpInstData
->mhComWnd
, SAL_MSG_RELEASEWAITYIELD
, 0, 0 );
165 mpInstData
->mpSalWaitMutex
->release();
183 // -----------------------------------------------------------------------
185 sal_Bool SAL_CALL
SalYieldMutex::tryToAcquire()
187 if( OMutex::tryToAcquire() )
190 mnThreadId
= GetCurrentThreadId();
197 // -----------------------------------------------------------------------
199 sal_uLong
SalYieldMutex::GetAcquireCount( sal_uLong nThreadId
)
201 if ( nThreadId
== mnThreadId
)
207 // -----------------------------------------------------------------------
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 arn't the main thread,
218 // than we call qcquire directly.
219 DWORD nThreadId
= GetCurrentThreadId();
220 SalData
* pSalData
= GetSalData();
221 if ( pSalData
->mnAppThreadId
== nThreadId
)
223 // Wenn wir den Mutex nicht bekommen, muessen wir solange
224 // warten, bis wir Ihn bekommen
225 sal_Bool bAcquire
= FALSE
;
228 if ( pInst
->mpSalYieldMutex
->tryToAcquire() )
232 pInst
->mpSalWaitMutex
->acquire();
233 if ( pInst
->mpSalYieldMutex
->tryToAcquire() )
236 pInst
->mpSalWaitMutex
->release();
240 pInst
->mnYieldWaitCount
++;
241 pInst
->mpSalWaitMutex
->release();
243 ImplGetMessage( &aTmpMsg
, pInst
->mhComWnd
, SAL_MSG_RELEASEWAITYIELD
, SAL_MSG_RELEASEWAITYIELD
);
244 pInst
->mnYieldWaitCount
--;
245 if ( pInst
->mnYieldWaitCount
)
246 ImplPostMessage( pInst
->mhComWnd
, SAL_MSG_RELEASEWAITYIELD
, 0, 0 );
253 pInst
->mpSalYieldMutex
->acquire();
256 // -----------------------------------------------------------------------
258 sal_Bool
ImplSalYieldMutexTryToAcquire()
260 WinSalInstance
* pInst
= GetSalData()->mpFirstInstance
;
262 return pInst
->mpSalYieldMutex
->tryToAcquire();
267 // -----------------------------------------------------------------------
269 void ImplSalYieldMutexAcquire()
271 WinSalInstance
* pInst
= GetSalData()->mpFirstInstance
;
273 pInst
->mpSalYieldMutex
->acquire();
276 // -----------------------------------------------------------------------
278 void ImplSalYieldMutexRelease()
280 WinSalInstance
* pInst
= GetSalData()->mpFirstInstance
;
284 pInst
->mpSalYieldMutex
->release();
288 // -----------------------------------------------------------------------
290 sal_uLong
ImplSalReleaseYieldMutex()
292 WinSalInstance
* pInst
= GetSalData()->mpFirstInstance
;
296 SalYieldMutex
* pYieldMutex
= pInst
->mpSalYieldMutex
;
297 sal_uLong nCount
= pYieldMutex
->GetAcquireCount( GetCurrentThreadId() );
298 sal_uLong n
= nCount
;
301 pYieldMutex
->release();
308 // -----------------------------------------------------------------------
310 void ImplSalAcquireYieldMutex( sal_uLong nCount
)
312 WinSalInstance
* pInst
= GetSalData()->mpFirstInstance
;
316 SalYieldMutex
* pYieldMutex
= pInst
->mpSalYieldMutex
;
319 pYieldMutex
->acquire();
324 // -----------------------------------------------------------------------
326 bool WinSalInstance::CheckYieldMutex()
329 SalData
* pSalData
= GetSalData();
330 DWORD nCurThreadId
= GetCurrentThreadId();
331 if ( pSalData
->mnAppThreadId
!= nCurThreadId
)
333 if ( pSalData
->mpFirstInstance
)
335 SalYieldMutex
* pYieldMutex
= pSalData
->mpFirstInstance
->mpSalYieldMutex
;
336 if ( pYieldMutex
->mnThreadId
!= nCurThreadId
)
344 if ( pSalData
->mpFirstInstance
)
346 SalYieldMutex
* pYieldMutex
= pSalData
->mpFirstInstance
->mpSalYieldMutex
;
347 if ( pYieldMutex
->mnThreadId
!= nCurThreadId
)
356 // =======================================================================
358 void SalData::initKeyCodeMap()
360 UINT nKey
= 0xffffffff;
361 #define initKey( a, b )\
362 nKey = LOWORD( VkKeyScan( a ) );\
366 initKey( '+', KEY_ADD
);
367 initKey( '-', KEY_SUBTRACT
);
368 initKey( '*', KEY_MULTIPLY
);
369 initKey( '/', KEY_DIVIDE
);
370 initKey( '.', KEY_POINT
);
371 initKey( ',', KEY_COMMA
);
372 initKey( '<', KEY_LESS
);
373 initKey( '>', KEY_GREATER
);
374 initKey( '=', KEY_EQUAL
);
375 initKey( '~', KEY_TILDE
);
376 initKey( '`', KEY_QUOTELEFT
);
379 // =======================================================================
386 mhInst
= 0; // default instance handle
387 mhPrevInst
= 0; // previous instance handle
388 mnCmdShow
= 0; // default frame show style
389 mhDitherPal
= 0; // dither palette
390 mhDitherDIB
= 0; // dither memory handle
391 mpDitherDIB
= 0; // dither memory
392 mpDitherDIBData
= 0; // beginning of DIB data
393 mpDitherDiff
= 0; // Dither mapping table
394 mpDitherLow
= 0; // Dither mapping table
395 mpDitherHigh
= 0; // Dither mapping table
396 mnTimerMS
= 0; // Current Time (in MS) of the Timer
397 mnTimerOrgMS
= 0; // Current Original Time (in MS)
400 mnTimerId
= 0; // windows timer id
401 mbInTimerProc
= FALSE
; // timer event is currently being dispatched
402 mhSalObjMsgHook
= 0; // hook to get interesting msg for SalObject
403 mhWantLeaveMsg
= 0; // window handle, that want a MOUSELEAVE message
404 mpMouseLeaveTimer
= 0; // Timer for MouseLeave Test
405 mpFirstInstance
= 0; // pointer of first instance
406 mpFirstFrame
= 0; // pointer of first frame
407 mpFirstObject
= 0; // pointer of first object window
408 mpFirstVD
= 0; // first VirDev
409 mpFirstPrinter
= 0; // first printing printer
410 mpHDCCache
= 0; // Cache for three DC's
411 mh50Bmp
= 0; // 50% Bitmap
412 mh50Brush
= 0; // 50% Brush
414 for(i
=0; i
<MAX_STOCKPEN
; i
++)
416 maStockPenColorAry
[i
] = 0;
417 mhStockPenAry
[i
] = 0;
419 for(i
=0; i
<MAX_STOCKBRUSH
; i
++)
421 maStockBrushColorAry
[i
] = 0;
422 mhStockBrushAry
[i
] = 0;
424 mnStockPenCount
= 0; // count of static pens
425 mnStockBrushCount
= 0; // count of static brushes
426 mnSalObjWantKeyEvt
= 0; // KeyEvent, welcher vom SalObj-Hook verarbeitet werden soll
427 mnCacheDCInUse
= 0; // count of CacheDC in use
428 mbObjClassInit
= FALSE
; // is SALOBJECTCLASS initialised
429 mbInPalChange
= FALSE
; // is in WM_QUERYNEWPALETTE
430 mnAppThreadId
= 0; // Id from Applikation-Thread
431 mbScrSvrEnabled
= FALSE
; // ScreenSaver enabled
432 mnSageStatus
= 0; // status of Sage-DLL (DISABLE_AGENT == nicht vorhanden)
433 mpSageEnableProc
= 0; // funktion to deactivate the system agent
434 mpFirstIcon
= 0; // icon cache, points to first icon, NULL if none
436 mbThemeChanged
= FALSE
; // true if visual theme was changed: throw away theme handles
437 mbThemeMenuSupport
= FALSE
;
442 mpDwmIsCompositionEnabled
= 0;
458 SalData
* pSalData
= new SalData
;
462 static Gdiplus::GdiplusStartupInput gdiplusStartupInput
;
463 Gdiplus::GdiplusStartup(&pSalData
->gdiplusToken
, &gdiplusStartupInput
, NULL
);
470 SalData
* pSalData
= GetSalData();
475 Gdiplus::GdiplusShutdown(pSalData
->gdiplusToken
);
481 // -----------------------------------------------------------------------
485 // remember data, copied from WinMain
486 SalData
* pData
= GetAppSalData();
487 if ( pData
) // Im AppServer NULL
490 aSI
.cb
= sizeof( aSI
);
491 GetStartupInfo( &aSI
);
492 pData
->mhInst
= GetModuleHandle( NULL
);
493 pData
->mhPrevInst
= NULL
;
494 pData
->mnCmdShow
= aSI
.wShowWindow
;
502 // -----------------------------------------------------------------------
504 SalInstance
* CreateSalInstance()
506 SalData
* pSalData
= GetSalData();
508 // determine the windows version
509 aSalShlData
.mbWXP
= 0;
510 aSalShlData
.mbWPrinter
= 0;
511 WORD nVer
= (WORD
)GetVersion();
512 aSalShlData
.mnVersion
= (((WORD
)LOBYTE(nVer
)) * 100) + HIBYTE(nVer
);
513 if ( aSalShlData
.mnVersion
>= 400 )
514 aSalShlData
.mbW40
= 1;
515 rtl_zeroMemory( &aSalShlData
.maVersionInfo
, sizeof(aSalShlData
.maVersionInfo
) );
516 aSalShlData
.maVersionInfo
.dwOSVersionInfoSize
= sizeof( aSalShlData
.maVersionInfo
);
517 if ( GetVersionEx( &aSalShlData
.maVersionInfo
) )
519 if ( aSalShlData
.maVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
522 if ( aSalShlData
.maVersionInfo
.dwMajorVersion
> 5 ||
523 ( aSalShlData
.maVersionInfo
.dwMajorVersion
== 5 && aSalShlData
.maVersionInfo
.dwMinorVersion
>= 1 ) )
524 aSalShlData
.mbWXP
= 1;
525 if( aSalShlData
.maVersionInfo
.dwMajorVersion
>= 5 )
526 aSalShlData
.mbWPrinter
= 1;
530 pSalData
->mnAppThreadId
= GetCurrentThreadId();
532 // register frame class
533 if ( !pSalData
->mhPrevInst
)
535 WNDCLASSEXW aWndClassEx
;
536 aWndClassEx
.cbSize
= sizeof( aWndClassEx
);
537 aWndClassEx
.style
= CS_OWNDC
;
538 aWndClassEx
.lpfnWndProc
= SalFrameWndProcW
;
539 aWndClassEx
.cbClsExtra
= 0;
540 aWndClassEx
.cbWndExtra
= SAL_FRAME_WNDEXTRA
;
541 aWndClassEx
.hInstance
= pSalData
->mhInst
;
542 aWndClassEx
.hCursor
= 0;
543 aWndClassEx
.hbrBackground
= 0;
544 aWndClassEx
.lpszMenuName
= 0;
545 aWndClassEx
.lpszClassName
= SAL_FRAME_CLASSNAMEW
;
546 ImplLoadSalIcon( SAL_RESID_ICON_DEFAULT
, aWndClassEx
.hIcon
, aWndClassEx
.hIconSm
);
547 if ( !RegisterClassExW( &aWndClassEx
) )
550 aWndClassEx
.hIcon
= 0;
551 aWndClassEx
.hIconSm
= 0;
552 aWndClassEx
.style
|= CS_SAVEBITS
;
553 aWndClassEx
.lpszClassName
= SAL_SUBFRAME_CLASSNAMEW
;
554 if ( !RegisterClassExW( &aWndClassEx
) )
557 // shadow effect for popups on XP
558 if( aSalShlData
.mbWXP
)
559 aWndClassEx
.style
|= CS_DROPSHADOW
;
560 aWndClassEx
.lpszClassName
= SAL_TMPSUBFRAME_CLASSNAMEW
;
561 if ( !RegisterClassExW( &aWndClassEx
) )
564 aWndClassEx
.style
= 0;
565 aWndClassEx
.lpfnWndProc
= SalComWndProcW
;
566 aWndClassEx
.cbWndExtra
= 0;
567 aWndClassEx
.lpszClassName
= SAL_COM_CLASSNAMEW
;
568 if ( !RegisterClassExW( &aWndClassEx
) )
572 HWND hComWnd
= CreateWindowExW( WS_EX_TOOLWINDOW
, SAL_COM_CLASSNAMEW
,
573 L
"", WS_POPUP
, 0, 0, 0, 0, 0, 0,
574 pSalData
->mhInst
, NULL
);
578 WinSalInstance
* pInst
= new WinSalInstance
;
580 // init instance (only one instance in this version !!!)
581 pSalData
->mpFirstInstance
= pInst
;
582 pInst
->mhInst
= pSalData
->mhInst
;
583 pInst
->mhComWnd
= hComWnd
;
585 // init static GDI Data
591 // -----------------------------------------------------------------------
593 void DestroySalInstance( SalInstance
* pInst
)
595 SalData
* pSalData
= GetSalData();
597 // (only one instance in this version !!!)
602 if ( pSalData
->mpFirstInstance
== pInst
)
603 pSalData
->mpFirstInstance
= NULL
;
608 // -----------------------------------------------------------------------
610 WinSalInstance::WinSalInstance()
613 mpSalYieldMutex
= new SalYieldMutex( this );
614 mpSalWaitMutex
= new vos::OMutex
;
615 mnYieldWaitCount
= 0;
616 mpSalYieldMutex
->acquire();
617 ::tools::SolarMutex::SetSolarMutex( mpSalYieldMutex
);
620 // -----------------------------------------------------------------------
622 WinSalInstance::~WinSalInstance()
624 ::tools::SolarMutex::SetSolarMutex( 0 );
625 mpSalYieldMutex
->release();
626 delete mpSalYieldMutex
;
627 delete mpSalWaitMutex
;
628 DestroyWindow( mhComWnd
);
631 // -----------------------------------------------------------------------
633 vos::IMutex
* WinSalInstance::GetYieldMutex()
635 return mpSalYieldMutex
;
638 // -----------------------------------------------------------------------
640 sal_uLong
WinSalInstance::ReleaseYieldMutex()
642 return ImplSalReleaseYieldMutex();
645 // -----------------------------------------------------------------------
647 void WinSalInstance::AcquireYieldMutex( sal_uLong nCount
)
649 ImplSalAcquireYieldMutex( nCount
);
652 // -----------------------------------------------------------------------
654 static void ImplSalDispatchMessage( MSG
* pMsg
)
656 SalData
* pSalData
= GetSalData();
657 if ( pSalData
->mpFirstObject
)
659 if ( ImplSalPreDispatchMsg( pMsg
) )
662 LRESULT lResult
= ImplDispatchMessage( pMsg
);
663 if ( pSalData
->mpFirstObject
)
664 ImplSalPostDispatchMsg( pMsg
, lResult
);
667 // -----------------------------------------------------------------------
669 void ImplSalYield( sal_Bool bWait
, sal_Bool bHandleAllCurrentEvents
)
672 bool bWasMsg
= false, bOneEvent
= false;
674 int nMaxEvents
= bHandleAllCurrentEvents
? 100 : 1;
677 if ( ImplPeekMessage( &aMsg
, 0, 0, 0, PM_REMOVE
) )
679 if ( !ImplInterceptChildWindowKeyDown( aMsg
) )
681 TranslateMessage( &aMsg
);
682 ImplSalDispatchMessage( &aMsg
);
685 bOneEvent
= bWasMsg
= true;
689 } while( --nMaxEvents
&& bOneEvent
);
691 if ( bWait
&& ! bWasMsg
)
693 if ( ImplGetMessage( &aMsg
, 0, 0, 0 ) )
695 if ( !ImplInterceptChildWindowKeyDown( aMsg
) )
697 TranslateMessage( &aMsg
);
698 ImplSalDispatchMessage( &aMsg
);
704 // -----------------------------------------------------------------------
706 void WinSalInstance::Yield( bool bWait
, bool bHandleAllCurrentEvents
)
708 SalYieldMutex
* pYieldMutex
= mpSalYieldMutex
;
709 SalData
* pSalData
= GetSalData();
710 DWORD nCurThreadId
= GetCurrentThreadId();
711 sal_uLong nCount
= pYieldMutex
->GetAcquireCount( nCurThreadId
);
712 sal_uLong n
= nCount
;
715 pYieldMutex
->release();
718 if ( pSalData
->mnAppThreadId
!= nCurThreadId
)
720 // #97739# A SendMessage call blocks until the called thread (here: the main thread)
721 // returns. During a yield however, messages are processed in the main thread that might
722 // result in a new message loop due to opening a dialog. Thus, SendMessage would not
723 // return which will block this thread!
724 // Solution: just give up the time slice and hope that messages are processed
725 // by the main thread anyway (where all windows are created)
726 // If the mainthread is not currently handling messages, then our SendMessage would
727 // also do nothing, so this seems to be reasonable.
729 // #i18883# only sleep if potential deadlock scenario, ie, when a dialog is open
730 if( ImplGetSVData()->maAppData
.mnModalMode
)
733 ImplSendMessage( mhComWnd
, SAL_MSG_THREADYIELD
, (WPARAM
)bWait
, (LPARAM
)bHandleAllCurrentEvents
);
738 pYieldMutex
->acquire();
744 ImplSalYield( bWait
, bHandleAllCurrentEvents
);
749 ImplSalYieldMutexAcquireWithWait();
755 // -----------------------------------------------------------------------
757 LRESULT CALLBACK
SalComWndProc( HWND hWnd
, UINT nMsg
, WPARAM wParam
, LPARAM lParam
, int& rDef
)
764 case SAL_MSG_PRINTABORTJOB
:
765 ImplSalPrinterAbortJobAsync( (HDC
)wParam
);
768 case SAL_MSG_THREADYIELD
:
769 ImplSalYield( (sal_Bool
)wParam
, (sal_Bool
)lParam
);
772 // If we get this message, because another GetMessage() call
773 // has recieved this message, we must post this message to
774 // us again, because in the other case we wait forever.
775 case SAL_MSG_RELEASEWAITYIELD
:
777 WinSalInstance
* pInst
= GetSalData()->mpFirstInstance
;
778 if ( pInst
&& pInst
->mnYieldWaitCount
)
779 ImplPostMessage( hWnd
, SAL_MSG_RELEASEWAITYIELD
, wParam
, lParam
);
783 case SAL_MSG_STARTTIMER
:
784 ImplSalStartTimer( (sal_uLong
) lParam
, FALSE
);
787 case SAL_MSG_CREATEFRAME
:
788 nRet
= (LRESULT
)ImplSalCreateFrame( GetSalData()->mpFirstInstance
, (HWND
)lParam
, (sal_uLong
)wParam
);
791 case SAL_MSG_RECREATEHWND
:
792 nRet
= (LRESULT
)ImplSalReCreateHWND( (HWND
)wParam
, (HWND
)lParam
, FALSE
);
795 case SAL_MSG_RECREATECHILDHWND
:
796 nRet
= (LRESULT
)ImplSalReCreateHWND( (HWND
)wParam
, (HWND
)lParam
, TRUE
);
799 case SAL_MSG_DESTROYFRAME
:
800 delete (SalFrame
*)lParam
;
803 case SAL_MSG_DESTROYHWND
:
804 //We only destroy the native window here. We do NOT destroy the SalFrame contained
805 //in the structure (GetWindowPtr()).
806 if (DestroyWindow((HWND
)lParam
) == 0)
808 OSL_ENSURE(0, "DestroyWindow failed!");
809 //Failure: We remove the SalFrame from the window structure. So we avoid that
810 // the window structure may contain an invalid pointer, once the SalFrame is deleted.
811 SetWindowPtr((HWND
)lParam
, 0);
815 case SAL_MSG_CREATEOBJECT
:
816 nRet
= (LRESULT
)ImplSalCreateObject( GetSalData()->mpFirstInstance
, (WinSalFrame
*)lParam
);
819 case SAL_MSG_DESTROYOBJECT
:
820 delete (SalObject
*)lParam
;
824 nRet
= (LRESULT
)GetDCEx( (HWND
)wParam
, 0, DCX_CACHE
);
827 case SAL_MSG_RELEASEDC
:
828 ReleaseDC( (HWND
)wParam
, (HDC
)lParam
);
831 case SAL_MSG_POSTTIMER
:
832 SalTimerProc( 0, 0, SALTIMERPROC_RECURSIVE
, lParam
);
839 LRESULT CALLBACK
SalComWndProcA( HWND hWnd
, UINT nMsg
, WPARAM wParam
, LPARAM lParam
)
846 if (__builtin_setjmp(jmpbuf
) == 0)
848 han
.Set(jmpbuf
, NULL
, (__SEHandler::PF
)EXCEPTION_EXECUTE_HANDLER
);
853 nRet
= SalComWndProc( hWnd
, nMsg
, wParam
, lParam
, bDef
);
858 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
864 if ( !ImplHandleGlobalMsg( hWnd
, nMsg
, wParam
, lParam
, nRet
) )
865 nRet
= DefWindowProcA( hWnd
, nMsg
, wParam
, lParam
);
870 LRESULT CALLBACK
SalComWndProcW( HWND hWnd
, UINT nMsg
, WPARAM wParam
, LPARAM lParam
)
877 if (__builtin_setjmp(jmpbuf
) == 0)
879 han
.Set(jmpbuf
, NULL
, (__SEHandler::PF
)EXCEPTION_EXECUTE_HANDLER
);
884 nRet
= SalComWndProc( hWnd
, nMsg
, wParam
, lParam
, bDef
);
889 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
895 if ( !ImplHandleGlobalMsg( hWnd
, nMsg
, wParam
, lParam
, nRet
) )
896 nRet
= DefWindowProcW( hWnd
, nMsg
, wParam
, lParam
);
901 // -----------------------------------------------------------------------
903 bool WinSalInstance::AnyInput( sal_uInt16 nType
)
907 if ( (nType
& (INPUT_ANY
)) == (INPUT_ANY
) )
909 // revert bugfix for #108919# which never reported timeouts when called from the timer handler
910 // which made the application completely unresponsive during background formatting
911 if ( ImplPeekMessage( &aMsg
, 0, 0, 0, PM_NOREMOVE
| PM_NOYIELD
) )
916 if ( nType
& INPUT_MOUSE
)
918 // Test for mouse input
919 if ( ImplPeekMessage( &aMsg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
,
920 PM_NOREMOVE
| PM_NOYIELD
) )
924 if ( nType
& INPUT_KEYBOARD
)
926 // Test for key input
927 if ( ImplPeekMessage( &aMsg
, 0, WM_KEYDOWN
, WM_KEYDOWN
,
928 PM_NOREMOVE
| PM_NOYIELD
) )
930 if ( (aMsg
.wParam
== VK_SHIFT
) ||
931 (aMsg
.wParam
== VK_CONTROL
) ||
932 (aMsg
.wParam
== VK_MENU
) )
939 if ( nType
& INPUT_PAINT
)
941 // Test for paint input
942 if ( ImplPeekMessage( &aMsg
, 0, WM_PAINT
, WM_PAINT
,
943 PM_NOREMOVE
| PM_NOYIELD
) )
946 if ( ImplPeekMessage( &aMsg
, 0, WM_SIZE
, WM_SIZE
,
947 PM_NOREMOVE
| PM_NOYIELD
) )
950 if ( ImplPeekMessage( &aMsg
, 0, SAL_MSG_POSTCALLSIZE
, SAL_MSG_POSTCALLSIZE
,
951 PM_NOREMOVE
| PM_NOYIELD
) )
954 if ( ImplPeekMessage( &aMsg
, 0, WM_MOVE
, WM_MOVE
,
955 PM_NOREMOVE
| PM_NOYIELD
) )
958 if ( ImplPeekMessage( &aMsg
, 0, SAL_MSG_POSTMOVE
, SAL_MSG_POSTMOVE
,
959 PM_NOREMOVE
| PM_NOYIELD
) )
963 if ( nType
& INPUT_TIMER
)
965 // Test for timer input
966 if ( ImplPeekMessage( &aMsg
, 0, WM_TIMER
, WM_TIMER
,
967 PM_NOREMOVE
| PM_NOYIELD
) )
972 if ( nType
& INPUT_OTHER
)
974 // Test for any input
975 if ( ImplPeekMessage( &aMsg
, 0, 0, 0, PM_NOREMOVE
| PM_NOYIELD
) )
983 // -----------------------------------------------------------------------
985 void SalTimer::Start( sal_uLong nMS
)
987 // Um auf Main-Thread umzuschalten
988 SalData
* pSalData
= GetSalData();
989 if ( pSalData
->mpFirstInstance
)
991 if ( pSalData
->mnAppThreadId
!= GetCurrentThreadId() )
992 ImplPostMessage( pSalData
->mpFirstInstance
->mhComWnd
, SAL_MSG_STARTTIMER
, 0, (LPARAM
)nMS
);
994 ImplSendMessage( pSalData
->mpFirstInstance
->mhComWnd
, SAL_MSG_STARTTIMER
, 0, (LPARAM
)nMS
);
997 ImplSalStartTimer( nMS
, FALSE
);
1000 // -----------------------------------------------------------------------
1002 SalFrame
* WinSalInstance::CreateChildFrame( SystemParentData
* pSystemParentData
, sal_uLong nSalFrameStyle
)
1004 // Um auf Main-Thread umzuschalten
1005 return (SalFrame
*)ImplSendMessage( mhComWnd
, SAL_MSG_CREATEFRAME
, nSalFrameStyle
, (LPARAM
)pSystemParentData
->hWnd
);
1008 // -----------------------------------------------------------------------
1010 SalFrame
* WinSalInstance::CreateFrame( SalFrame
* pParent
, sal_uLong nSalFrameStyle
)
1012 // Um auf Main-Thread umzuschalten
1015 hWndParent
= static_cast<WinSalFrame
*>(pParent
)->mhWnd
;
1018 return (SalFrame
*)ImplSendMessage( mhComWnd
, SAL_MSG_CREATEFRAME
, nSalFrameStyle
, (LPARAM
)hWndParent
);
1021 // -----------------------------------------------------------------------
1023 void WinSalInstance::DestroyFrame( SalFrame
* pFrame
)
1025 ImplSendMessage( mhComWnd
, SAL_MSG_DESTROYFRAME
, 0, (LPARAM
)pFrame
);
1028 // -----------------------------------------------------------------------
1030 SalObject
* WinSalInstance::CreateObject( SalFrame
* pParent
,
1031 SystemWindowData
* /*pWindowData*/, // SystemWindowData meaningless on Windows
1032 sal_Bool
/*bShow*/ )
1034 // Um auf Main-Thread umzuschalten
1035 return (SalObject
*)ImplSendMessage( mhComWnd
, SAL_MSG_CREATEOBJECT
, 0, (LPARAM
)static_cast<WinSalFrame
*>(pParent
) );
1038 // -----------------------------------------------------------------------
1040 void WinSalInstance::DestroyObject( SalObject
* pObject
)
1042 ImplSendMessage( mhComWnd
, SAL_MSG_DESTROYOBJECT
, 0, (LPARAM
)pObject
);
1045 // -----------------------------------------------------------------------
1047 void* WinSalInstance::GetConnectionIdentifier( ConnectionIdentifierType
& rReturnedType
, int& rReturnedBytes
)
1050 rReturnedType
= AsciiCString
;
1051 return const_cast<char *>("");
1054 // -----------------------------------------------------------------------
1056 /** Add a file to the system shells recent document list if there is any.
1057 This function may have no effect under Unix because there is no
1058 standard API among the different desktop managers.
1061 The file url of the document.
1063 void WinSalInstance::AddToRecentDocumentList(const rtl::OUString
& rFileUrl
, const rtl::OUString
& /*rMimeType*/)
1065 rtl::OUString system_path
;
1066 osl::FileBase::RC rc
= osl::FileBase::getSystemPathFromFileURL(rFileUrl
, system_path
);
1068 OSL_ENSURE(osl::FileBase::E_None
== rc
, "Invalid file url");
1070 if (osl::FileBase::E_None
== rc
)
1071 SHAddToRecentDocs(SHARD_PATHW
, system_path
.getStr());
1074 // -----------------------------------------------------------------------
1076 SalTimer
* WinSalInstance::CreateSalTimer()
1078 return new WinSalTimer();
1081 // -----------------------------------------------------------------------
1083 SalBitmap
* WinSalInstance::CreateSalBitmap()
1085 return new WinSalBitmap();
1088 class WinImeStatus
: public SalI18NImeStatus
1092 virtual ~WinImeStatus() {}
1094 // asks whether there is a status window available
1095 // to toggle into menubar
1096 virtual bool canToggle() { return false; }
1097 virtual void toggle() {}
1100 SalI18NImeStatus
* WinSalInstance::CreateI18NImeStatus()
1102 return new WinImeStatus();
1105 // -----------------------------------------------------------------------
1107 const ::rtl::OUString
& SalGetDesktopEnvironment()
1109 static ::rtl::OUString
aDesktopEnvironment( RTL_CONSTASCII_USTRINGPARAM( "Windows" ) );
1110 return aDesktopEnvironment
;
1113 SalSession
* WinSalInstance::CreateSalSession()
1119 // -----------------------------------------------------------------------
1120 int WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(int, LPEXCEPTION_POINTERS pExceptionInfo
)
1122 // Decide if an exception is a c++ (mostly UNO) exception or a process violation.
1123 // Depending on this information we pass process violations directly to our signal handler ...
1124 // and c++ (UNO) exceptions are sended to the following code on the current stack.
1125 // Problem behind: user32.dll sometime consumes exceptions/process violations .-)
1126 // see also #112221#
1128 static DWORD EXCEPTION_MSC_CPP_EXCEPTION
= 0xE06D7363;
1130 if (pExceptionInfo
->ExceptionRecord
->ExceptionCode
== EXCEPTION_MSC_CPP_EXCEPTION
)
1131 return EXCEPTION_CONTINUE_SEARCH
;
1133 return UnhandledExceptionFilter( pExceptionInfo
);