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 .
25 #include <osl/file.hxx>
26 #include <comphelper/solarmutex.hxx>
28 #include <tools/solarmutex.hxx>
30 #include <vcl/timer.hxx>
31 #include <vcl/apptypes.hxx>
33 #include <vcl/solarmutex.hxx>
34 #include <win/wincomp.hxx>
35 #include <win/salids.hrc>
36 #include <win/saldata.hxx>
37 #include <win/salinst.h>
38 #include <win/salframe.h>
39 #include <win/salobj.h>
40 #include <win/saltimer.h>
41 #include <win/salbmp.h>
43 #include <salimestatus.hxx>
48 #define min(a,b) (((a) < (b)) ? (a) : (b))
51 #define max(a,b) (((a) > (b)) ? (a) : (b))
56 #pragma warning(push, 1)
57 #pragma warning( disable: 4917 )
61 #include <gdiplusenums.h>
62 #include <gdipluscolor.h>
70 #include <sehandler.hxx>
73 // =======================================================================
75 void SalAbort( const OUString
& rErrorText
, bool )
79 if ( rErrorText
.isEmpty() )
81 // make sure crash reporter is triggered
82 RaiseException( 0, EXCEPTION_NONCONTINUABLE
, 0, NULL
);
83 FatalAppExitW( 0, L
"Application Error" );
87 // make sure crash reporter is triggered
88 RaiseException( 0, EXCEPTION_NONCONTINUABLE
, 0, NULL
);
89 FatalAppExitW( 0, reinterpret_cast<LPCWSTR
>(rErrorText
.getStr()) );
93 // =======================================================================
95 LRESULT CALLBACK
SalComWndProcA( HWND hWnd
, UINT nMsg
, WPARAM wParam
, LPARAM lParam
);
96 LRESULT CALLBACK
SalComWndProcW( HWND hWnd
, UINT nMsg
, WPARAM wParam
, LPARAM lParam
);
98 // =======================================================================
100 class SalYieldMutex
: public vcl::SolarMutexObject
102 public: // for ImplSalYield()
103 WinSalInstance
* mpInstData
;
108 SalYieldMutex( WinSalInstance
* pInstData
);
110 virtual void acquire();
111 virtual void release();
112 virtual bool tryToAcquire();
114 sal_uLong
GetAcquireCount( sal_uLong nThreadId
);
117 // -----------------------------------------------------------------------
119 SalYieldMutex::SalYieldMutex( WinSalInstance
* pInstData
)
121 mpInstData
= pInstData
;
126 // -----------------------------------------------------------------------
128 void SalYieldMutex::acquire()
130 SolarMutexObject::acquire();
132 mnThreadId
= GetCurrentThreadId();
135 // -----------------------------------------------------------------------
137 void SalYieldMutex::release()
139 DWORD nThreadId
= GetCurrentThreadId();
140 if ( mnThreadId
!= nThreadId
)
141 SolarMutexObject::release();
144 SalData
* pSalData
= GetSalData();
145 if ( pSalData
->mnAppThreadId
!= nThreadId
)
149 // If we don't call these message, the Output from the
150 // Java clients doesn't come in the right order
153 mpInstData
->mpSalWaitMutex
->acquire();
154 if ( mpInstData
->mnYieldWaitCount
)
155 ImplPostMessage( mpInstData
->mhComWnd
, SAL_MSG_RELEASEWAITYIELD
, 0, 0 );
158 SolarMutexObject::release();
159 mpInstData
->mpSalWaitMutex
->release();
164 SolarMutexObject::release();
172 SolarMutexObject::release();
177 // -----------------------------------------------------------------------
179 bool SalYieldMutex::tryToAcquire()
181 if( SolarMutexObject::tryToAcquire() )
184 mnThreadId
= GetCurrentThreadId();
191 // -----------------------------------------------------------------------
193 sal_uLong
SalYieldMutex::GetAcquireCount( sal_uLong nThreadId
)
195 if ( nThreadId
== mnThreadId
)
201 // -----------------------------------------------------------------------
203 void ImplSalYieldMutexAcquireWithWait()
205 WinSalInstance
* pInst
= GetSalData()->mpFirstInstance
;
209 // If we are the main thread, then we must wait with wait, because
210 // in if we don't reschedule, then we create deadlocks if a Windows
211 // Function is called from another thread. If we arn't the main thread,
212 // than we call qcquire directly.
213 DWORD nThreadId
= GetCurrentThreadId();
214 SalData
* pSalData
= GetSalData();
215 if ( pSalData
->mnAppThreadId
== nThreadId
)
217 // wait till we get the Mutex
218 sal_Bool bAcquire
= FALSE
;
221 if ( pInst
->mpSalYieldMutex
->tryToAcquire() )
225 pInst
->mpSalWaitMutex
->acquire();
226 if ( pInst
->mpSalYieldMutex
->tryToAcquire() )
229 pInst
->mpSalWaitMutex
->release();
233 pInst
->mnYieldWaitCount
++;
234 pInst
->mpSalWaitMutex
->release();
236 ImplGetMessage( &aTmpMsg
, pInst
->mhComWnd
, SAL_MSG_RELEASEWAITYIELD
, SAL_MSG_RELEASEWAITYIELD
);
237 pInst
->mnYieldWaitCount
--;
238 if ( pInst
->mnYieldWaitCount
)
239 ImplPostMessage( pInst
->mhComWnd
, SAL_MSG_RELEASEWAITYIELD
, 0, 0 );
246 pInst
->mpSalYieldMutex
->acquire();
249 // -----------------------------------------------------------------------
251 sal_Bool
ImplSalYieldMutexTryToAcquire()
253 WinSalInstance
* pInst
= GetSalData()->mpFirstInstance
;
255 return pInst
->mpSalYieldMutex
->tryToAcquire();
260 // -----------------------------------------------------------------------
262 void ImplSalYieldMutexAcquire()
264 WinSalInstance
* pInst
= GetSalData()->mpFirstInstance
;
266 pInst
->mpSalYieldMutex
->acquire();
269 // -----------------------------------------------------------------------
271 void ImplSalYieldMutexRelease()
273 WinSalInstance
* pInst
= GetSalData()->mpFirstInstance
;
277 pInst
->mpSalYieldMutex
->release();
281 // -----------------------------------------------------------------------
283 sal_uLong
ImplSalReleaseYieldMutex()
285 WinSalInstance
* pInst
= GetSalData()->mpFirstInstance
;
289 SalYieldMutex
* pYieldMutex
= pInst
->mpSalYieldMutex
;
290 sal_uLong nCount
= pYieldMutex
->GetAcquireCount( GetCurrentThreadId() );
291 sal_uLong n
= nCount
;
294 pYieldMutex
->release();
301 // -----------------------------------------------------------------------
303 void ImplSalAcquireYieldMutex( sal_uLong nCount
)
305 WinSalInstance
* pInst
= GetSalData()->mpFirstInstance
;
309 SalYieldMutex
* pYieldMutex
= pInst
->mpSalYieldMutex
;
312 pYieldMutex
->acquire();
317 // -----------------------------------------------------------------------
319 bool WinSalInstance::CheckYieldMutex()
321 SalData
* pSalData
= GetSalData();
322 if ( pSalData
->mpFirstInstance
)
324 SalYieldMutex
* pYieldMutex
= pSalData
->mpFirstInstance
->mpSalYieldMutex
;
325 return (pYieldMutex
->mnThreadId
== (GetCurrentThreadId()));
330 // =======================================================================
332 void SalData::initKeyCodeMap()
334 UINT nKey
= 0xffffffff;
335 #define initKey( a, b )\
336 nKey = LOWORD( VkKeyScan( a ) );\
340 initKey( '+', KEY_ADD
);
341 initKey( '-', KEY_SUBTRACT
);
342 initKey( '*', KEY_MULTIPLY
);
343 initKey( '/', KEY_DIVIDE
);
344 initKey( '.', KEY_POINT
);
345 initKey( ',', KEY_COMMA
);
346 initKey( '<', KEY_LESS
);
347 initKey( '>', KEY_GREATER
);
348 initKey( '=', KEY_EQUAL
);
349 initKey( '~', KEY_TILDE
);
350 initKey( '`', KEY_QUOTELEFT
);
351 initKey( '[', KEY_BRACKETLEFT
);
352 initKey( ']', KEY_BRACKETRIGHT
);
353 initKey( ';', KEY_SEMICOLON
);
356 // =======================================================================
363 mhInst
= 0; // default instance handle
364 mhPrevInst
= 0; // previous instance handle
365 mnCmdShow
= 0; // default frame show style
366 mhDitherPal
= 0; // dither palette
367 mhDitherDIB
= 0; // dither memory handle
368 mpDitherDIB
= 0; // dither memory
369 mpDitherDIBData
= 0; // beginning of DIB data
370 mpDitherDiff
= 0; // Dither mapping table
371 mpDitherLow
= 0; // Dither mapping table
372 mpDitherHigh
= 0; // Dither mapping table
373 mnTimerMS
= 0; // Current Time (in MS) of the Timer
374 mnTimerOrgMS
= 0; // Current Original Time (in MS)
377 mnTimerId
= 0; // windows timer id
378 mbInTimerProc
= FALSE
; // timer event is currently being dispatched
379 mhSalObjMsgHook
= 0; // hook to get interesting msg for SalObject
380 mhWantLeaveMsg
= 0; // window handle, that want a MOUSELEAVE message
381 mpMouseLeaveTimer
= 0; // Timer for MouseLeave Test
382 mpFirstInstance
= 0; // pointer of first instance
383 mpFirstFrame
= 0; // pointer of first frame
384 mpFirstObject
= 0; // pointer of first object window
385 mpFirstVD
= 0; // first VirDev
386 mpFirstPrinter
= 0; // first printing printer
387 mpHDCCache
= 0; // Cache for three DC's
388 mh50Bmp
= 0; // 50% Bitmap
389 mh50Brush
= 0; // 50% Brush
391 for(i
=0; i
<MAX_STOCKPEN
; i
++)
393 maStockPenColorAry
[i
] = 0;
394 mhStockPenAry
[i
] = 0;
396 for(i
=0; i
<MAX_STOCKBRUSH
; i
++)
398 maStockBrushColorAry
[i
] = 0;
399 mhStockBrushAry
[i
] = 0;
401 mnStockPenCount
= 0; // count of static pens
402 mnStockBrushCount
= 0; // count of static brushes
403 mnSalObjWantKeyEvt
= 0; // KeyEvent for the SalObj hook
404 mnCacheDCInUse
= 0; // count of CacheDC in use
405 mbObjClassInit
= FALSE
; // is SALOBJECTCLASS initialised
406 mbInPalChange
= FALSE
; // is in WM_QUERYNEWPALETTE
407 mnAppThreadId
= 0; // Id from Applikation-Thread
408 mbScrSvrEnabled
= FALSE
; // ScreenSaver enabled
409 mnSageStatus
= 0; // status of Sage-DLL (DISABLE_AGENT == not available)
410 mpSageEnableProc
= 0; // funktion to deactivate the system agent
411 mpFirstIcon
= 0; // icon cache, points to first icon, NULL if none
413 mbThemeChanged
= FALSE
; // true if visual theme was changed: throw away theme handles
414 mbThemeMenuSupport
= FALSE
;
419 mpDwmIsCompositionEnabled
= 0;
435 SalData
* pSalData
= new SalData
;
439 static Gdiplus::GdiplusStartupInput gdiplusStartupInput
;
440 Gdiplus::GdiplusStartup(&pSalData
->gdiplusToken
, &gdiplusStartupInput
, NULL
);
447 SalData
* pSalData
= GetSalData();
452 Gdiplus::GdiplusShutdown(pSalData
->gdiplusToken
);
458 // -----------------------------------------------------------------------
462 // remember data, copied from WinMain
463 SalData
* pData
= GetSalData();
464 if ( pData
) // Im AppServer NULL
467 aSI
.cb
= sizeof( aSI
);
468 GetStartupInfo( &aSI
);
469 pData
->mhInst
= GetModuleHandle( NULL
);
470 pData
->mhPrevInst
= NULL
;
471 pData
->mnCmdShow
= aSI
.wShowWindow
;
475 // -----------------------------------------------------------------------
477 SalInstance
* CreateSalInstance()
479 SalData
* pSalData
= GetSalData();
481 // determine the windows version
482 aSalShlData
.mbWXP
= 0;
483 aSalShlData
.mbW7
= 0;
484 memset( &aSalShlData
.maVersionInfo
, 0, sizeof(aSalShlData
.maVersionInfo
) );
485 aSalShlData
.maVersionInfo
.dwOSVersionInfoSize
= sizeof( aSalShlData
.maVersionInfo
);
486 if ( GetVersionEx( &aSalShlData
.maVersionInfo
) )
489 if ( aSalShlData
.maVersionInfo
.dwMajorVersion
> 5 ||
490 ( aSalShlData
.maVersionInfo
.dwMajorVersion
== 5 && aSalShlData
.maVersionInfo
.dwMinorVersion
>= 1 ) )
491 aSalShlData
.mbWXP
= 1;
493 if ( aSalShlData
.maVersionInfo
.dwMajorVersion
> 6 ||
494 ( aSalShlData
.maVersionInfo
.dwMajorVersion
== 6 && aSalShlData
.maVersionInfo
.dwMinorVersion
>= 1 ) )
495 aSalShlData
.mbW7
= 1;
498 pSalData
->mnAppThreadId
= GetCurrentThreadId();
500 // register frame class
501 if ( !pSalData
->mhPrevInst
)
503 WNDCLASSEXW aWndClassEx
;
504 aWndClassEx
.cbSize
= sizeof( aWndClassEx
);
505 aWndClassEx
.style
= CS_OWNDC
;
506 aWndClassEx
.lpfnWndProc
= SalFrameWndProcW
;
507 aWndClassEx
.cbClsExtra
= 0;
508 aWndClassEx
.cbWndExtra
= SAL_FRAME_WNDEXTRA
;
509 aWndClassEx
.hInstance
= pSalData
->mhInst
;
510 aWndClassEx
.hCursor
= 0;
511 aWndClassEx
.hbrBackground
= 0;
512 aWndClassEx
.lpszMenuName
= 0;
513 aWndClassEx
.lpszClassName
= SAL_FRAME_CLASSNAMEW
;
514 ImplLoadSalIcon( SAL_RESID_ICON_DEFAULT
, aWndClassEx
.hIcon
, aWndClassEx
.hIconSm
);
515 if ( !RegisterClassExW( &aWndClassEx
) )
518 aWndClassEx
.hIcon
= 0;
519 aWndClassEx
.hIconSm
= 0;
520 aWndClassEx
.style
|= CS_SAVEBITS
;
521 aWndClassEx
.lpszClassName
= SAL_SUBFRAME_CLASSNAMEW
;
522 if ( !RegisterClassExW( &aWndClassEx
) )
525 // shadow effect for popups on XP
526 if( aSalShlData
.mbWXP
)
527 aWndClassEx
.style
|= CS_DROPSHADOW
;
528 aWndClassEx
.lpszClassName
= SAL_TMPSUBFRAME_CLASSNAMEW
;
529 if ( !RegisterClassExW( &aWndClassEx
) )
532 aWndClassEx
.style
= 0;
533 aWndClassEx
.lpfnWndProc
= SalComWndProcW
;
534 aWndClassEx
.cbWndExtra
= 0;
535 aWndClassEx
.lpszClassName
= SAL_COM_CLASSNAMEW
;
536 if ( !RegisterClassExW( &aWndClassEx
) )
540 HWND hComWnd
= CreateWindowExW( WS_EX_TOOLWINDOW
, SAL_COM_CLASSNAMEW
,
541 L
"", WS_POPUP
, 0, 0, 0, 0, 0, 0,
542 pSalData
->mhInst
, NULL
);
546 WinSalInstance
* pInst
= new WinSalInstance
;
548 // init instance (only one instance in this version !!!)
549 pSalData
->mpFirstInstance
= pInst
;
550 pInst
->mhInst
= pSalData
->mhInst
;
551 pInst
->mhComWnd
= hComWnd
;
553 // init static GDI Data
559 // -----------------------------------------------------------------------
561 void DestroySalInstance( SalInstance
* pInst
)
563 SalData
* pSalData
= GetSalData();
565 // (only one instance in this version !!!)
570 if ( pSalData
->mpFirstInstance
== pInst
)
571 pSalData
->mpFirstInstance
= NULL
;
576 // -----------------------------------------------------------------------
578 WinSalInstance::WinSalInstance()
581 mpSalYieldMutex
= new SalYieldMutex( this );
582 mpSalWaitMutex
= new osl::Mutex
;
583 mnYieldWaitCount
= 0;
584 mpSalYieldMutex
->acquire();
585 ::tools::SolarMutex::SetSolarMutex( mpSalYieldMutex
);
588 // -----------------------------------------------------------------------
590 WinSalInstance::~WinSalInstance()
592 ::tools::SolarMutex::SetSolarMutex( 0 );
593 mpSalYieldMutex
->release();
594 delete mpSalYieldMutex
;
595 delete mpSalWaitMutex
;
596 DestroyWindow( mhComWnd
);
599 // -----------------------------------------------------------------------
601 comphelper::SolarMutex
* WinSalInstance::GetYieldMutex()
603 return mpSalYieldMutex
;
606 // -----------------------------------------------------------------------
608 sal_uLong
WinSalInstance::ReleaseYieldMutex()
610 return ImplSalReleaseYieldMutex();
613 // -----------------------------------------------------------------------
615 void WinSalInstance::AcquireYieldMutex( sal_uLong nCount
)
617 ImplSalAcquireYieldMutex( nCount
);
620 // -----------------------------------------------------------------------
622 static void ImplSalDispatchMessage( MSG
* pMsg
)
624 SalData
* pSalData
= GetSalData();
625 if ( pSalData
->mpFirstObject
)
627 if ( ImplSalPreDispatchMsg( pMsg
) )
630 LRESULT lResult
= ImplDispatchMessage( pMsg
);
631 if ( pSalData
->mpFirstObject
)
632 ImplSalPostDispatchMsg( pMsg
, lResult
);
635 // -----------------------------------------------------------------------
637 void ImplSalYield( sal_Bool bWait
, sal_Bool bHandleAllCurrentEvents
)
640 bool bWasMsg
= false, bOneEvent
= false;
642 int nMaxEvents
= bHandleAllCurrentEvents
? 100 : 1;
645 if ( ImplPeekMessage( &aMsg
, 0, 0, 0, PM_REMOVE
) )
647 TranslateMessage( &aMsg
);
648 ImplSalDispatchMessage( &aMsg
);
650 bOneEvent
= bWasMsg
= true;
654 } while( --nMaxEvents
&& bOneEvent
);
656 if ( bWait
&& ! bWasMsg
)
658 if ( ImplGetMessage( &aMsg
, 0, 0, 0 ) )
660 TranslateMessage( &aMsg
);
661 ImplSalDispatchMessage( &aMsg
);
666 // -----------------------------------------------------------------------
668 void WinSalInstance::Yield( bool bWait
, bool bHandleAllCurrentEvents
)
670 SalYieldMutex
* pYieldMutex
= mpSalYieldMutex
;
671 SalData
* pSalData
= GetSalData();
672 DWORD nCurThreadId
= GetCurrentThreadId();
673 sal_uLong nCount
= pYieldMutex
->GetAcquireCount( nCurThreadId
);
674 sal_uLong n
= nCount
;
677 pYieldMutex
->release();
680 if ( pSalData
->mnAppThreadId
!= nCurThreadId
)
682 // #97739# A SendMessage call blocks until the called thread (here: the main thread)
683 // returns. During a yield however, messages are processed in the main thread that might
684 // result in a new message loop due to opening a dialog. Thus, SendMessage would not
685 // return which will block this thread!
686 // Solution: just give up the time slice and hope that messages are processed
687 // by the main thread anyway (where all windows are created)
688 // If the mainthread is not currently handling messages, then our SendMessage would
689 // also do nothing, so this seems to be reasonable.
691 // #i18883# only sleep if potential deadlock scenario, ie, when a dialog is open
692 if( ImplGetSVData()->maAppData
.mnModalMode
)
695 ImplSendMessage( mhComWnd
, SAL_MSG_THREADYIELD
, (WPARAM
)bWait
, (LPARAM
)bHandleAllCurrentEvents
);
700 pYieldMutex
->acquire();
706 ImplSalYield( bWait
, bHandleAllCurrentEvents
);
711 ImplSalYieldMutexAcquireWithWait();
717 // -----------------------------------------------------------------------
719 LRESULT CALLBACK
SalComWndProc( HWND hWnd
, UINT nMsg
, WPARAM wParam
, LPARAM lParam
, int& rDef
)
726 case SAL_MSG_PRINTABORTJOB
:
727 ImplSalPrinterAbortJobAsync( (HDC
)wParam
);
730 case SAL_MSG_THREADYIELD
:
731 ImplSalYield( (sal_Bool
)wParam
, (sal_Bool
)lParam
);
734 // If we get this message, because another GetMessage() call
735 // has received this message, we must post this message to
736 // us again, because in the other case we wait forever.
737 case SAL_MSG_RELEASEWAITYIELD
:
739 WinSalInstance
* pInst
= GetSalData()->mpFirstInstance
;
740 if ( pInst
&& pInst
->mnYieldWaitCount
)
741 ImplPostMessage( hWnd
, SAL_MSG_RELEASEWAITYIELD
, wParam
, lParam
);
745 case SAL_MSG_STARTTIMER
:
746 ImplSalStartTimer( (sal_uLong
) lParam
, FALSE
);
749 case SAL_MSG_CREATEFRAME
:
750 nRet
= (LRESULT
)ImplSalCreateFrame( GetSalData()->mpFirstInstance
, (HWND
)lParam
, (sal_uLong
)wParam
);
753 case SAL_MSG_RECREATEHWND
:
754 nRet
= (LRESULT
)ImplSalReCreateHWND( (HWND
)wParam
, (HWND
)lParam
, FALSE
);
757 case SAL_MSG_RECREATECHILDHWND
:
758 nRet
= (LRESULT
)ImplSalReCreateHWND( (HWND
)wParam
, (HWND
)lParam
, TRUE
);
761 case SAL_MSG_DESTROYFRAME
:
762 delete (SalFrame
*)lParam
;
765 case SAL_MSG_DESTROYHWND
:
766 //We only destroy the native window here. We do NOT destroy the SalFrame contained
767 //in the structure (GetWindowPtr()).
768 if (DestroyWindow((HWND
)lParam
) == 0)
770 OSL_FAIL("DestroyWindow failed!");
771 //Failure: We remove the SalFrame from the window structure. So we avoid that
772 // the window structure may contain an invalid pointer, once the SalFrame is deleted.
773 SetWindowPtr((HWND
)lParam
, 0);
777 case SAL_MSG_CREATEOBJECT
:
778 nRet
= (LRESULT
)ImplSalCreateObject( GetSalData()->mpFirstInstance
, (WinSalFrame
*)lParam
);
781 case SAL_MSG_DESTROYOBJECT
:
782 delete (SalObject
*)lParam
;
786 nRet
= (LRESULT
)GetDCEx( (HWND
)wParam
, 0, DCX_CACHE
);
789 case SAL_MSG_RELEASEDC
:
790 ReleaseDC( (HWND
)wParam
, (HDC
)lParam
);
793 case SAL_MSG_POSTTIMER
:
794 SalTimerProc( 0, 0, SALTIMERPROC_RECURSIVE
, lParam
);
801 LRESULT CALLBACK
SalComWndProcA( HWND hWnd
, UINT nMsg
, WPARAM wParam
, LPARAM lParam
)
808 if (__builtin_setjmp(jmpbuf
) == 0)
810 han
.Set(jmpbuf
, NULL
, (__SEHandler::PF
)EXCEPTION_EXECUTE_HANDLER
);
815 nRet
= SalComWndProc( hWnd
, nMsg
, wParam
, lParam
, bDef
);
820 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
826 if ( !ImplHandleGlobalMsg( hWnd
, nMsg
, wParam
, lParam
, nRet
) )
827 nRet
= DefWindowProcA( hWnd
, nMsg
, wParam
, lParam
);
832 LRESULT CALLBACK
SalComWndProcW( HWND hWnd
, UINT nMsg
, WPARAM wParam
, LPARAM lParam
)
839 if (__builtin_setjmp(jmpbuf
) == 0)
841 han
.Set(jmpbuf
, NULL
, (__SEHandler::PF
)EXCEPTION_EXECUTE_HANDLER
);
846 nRet
= SalComWndProc( hWnd
, nMsg
, wParam
, lParam
, bDef
);
851 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
857 if ( !ImplHandleGlobalMsg( hWnd
, nMsg
, wParam
, lParam
, nRet
) )
858 nRet
= DefWindowProcW( hWnd
, nMsg
, wParam
, lParam
);
863 // -----------------------------------------------------------------------
865 bool WinSalInstance::AnyInput( sal_uInt16 nType
)
869 if ( (nType
& (VCL_INPUT_ANY
)) == (VCL_INPUT_ANY
) )
871 // revert bugfix for #108919# which never reported timeouts when called from the timer handler
872 // which made the application completely unresponsive during background formatting
873 if ( ImplPeekMessage( &aMsg
, 0, 0, 0, PM_NOREMOVE
| PM_NOYIELD
) )
878 if ( nType
& VCL_INPUT_MOUSE
)
880 // Test for mouse input
881 if ( ImplPeekMessage( &aMsg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
,
882 PM_NOREMOVE
| PM_NOYIELD
) )
886 if ( nType
& VCL_INPUT_KEYBOARD
)
888 // Test for key input
889 if ( ImplPeekMessage( &aMsg
, 0, WM_KEYDOWN
, WM_KEYDOWN
,
890 PM_NOREMOVE
| PM_NOYIELD
) )
892 if ( (aMsg
.wParam
== VK_SHIFT
) ||
893 (aMsg
.wParam
== VK_CONTROL
) ||
894 (aMsg
.wParam
== VK_MENU
) )
901 if ( nType
& VCL_INPUT_PAINT
)
903 // Test for paint input
904 if ( ImplPeekMessage( &aMsg
, 0, WM_PAINT
, WM_PAINT
,
905 PM_NOREMOVE
| PM_NOYIELD
) )
908 if ( ImplPeekMessage( &aMsg
, 0, WM_SIZE
, WM_SIZE
,
909 PM_NOREMOVE
| PM_NOYIELD
) )
912 if ( ImplPeekMessage( &aMsg
, 0, SAL_MSG_POSTCALLSIZE
, SAL_MSG_POSTCALLSIZE
,
913 PM_NOREMOVE
| PM_NOYIELD
) )
916 if ( ImplPeekMessage( &aMsg
, 0, WM_MOVE
, WM_MOVE
,
917 PM_NOREMOVE
| PM_NOYIELD
) )
920 if ( ImplPeekMessage( &aMsg
, 0, SAL_MSG_POSTMOVE
, SAL_MSG_POSTMOVE
,
921 PM_NOREMOVE
| PM_NOYIELD
) )
925 if ( nType
& VCL_INPUT_TIMER
)
927 // Test for timer input
928 if ( ImplPeekMessage( &aMsg
, 0, WM_TIMER
, WM_TIMER
,
929 PM_NOREMOVE
| PM_NOYIELD
) )
934 if ( nType
& VCL_INPUT_OTHER
)
936 // Test for any input
937 if ( ImplPeekMessage( &aMsg
, 0, 0, 0, PM_NOREMOVE
| PM_NOYIELD
) )
945 // -----------------------------------------------------------------------
947 void SalTimer::Start( sal_uLong nMS
)
949 // to switch to Main-Thread
950 SalData
* pSalData
= GetSalData();
951 if ( pSalData
->mpFirstInstance
)
953 if ( pSalData
->mnAppThreadId
!= GetCurrentThreadId() )
954 ImplPostMessage( pSalData
->mpFirstInstance
->mhComWnd
, SAL_MSG_STARTTIMER
, 0, (LPARAM
)nMS
);
956 ImplSendMessage( pSalData
->mpFirstInstance
->mhComWnd
, SAL_MSG_STARTTIMER
, 0, (LPARAM
)nMS
);
959 ImplSalStartTimer( nMS
, FALSE
);
962 // -----------------------------------------------------------------------
964 SalFrame
* WinSalInstance::CreateChildFrame( SystemParentData
* pSystemParentData
, sal_uLong nSalFrameStyle
)
966 // to switch to Main-Thread
967 return (SalFrame
*)ImplSendMessage( mhComWnd
, SAL_MSG_CREATEFRAME
, nSalFrameStyle
, (LPARAM
)pSystemParentData
->hWnd
);
970 // -----------------------------------------------------------------------
972 SalFrame
* WinSalInstance::CreateFrame( SalFrame
* pParent
, sal_uLong nSalFrameStyle
)
974 // to switch to Main-Thread
977 hWndParent
= static_cast<WinSalFrame
*>(pParent
)->mhWnd
;
980 return (SalFrame
*)ImplSendMessage( mhComWnd
, SAL_MSG_CREATEFRAME
, nSalFrameStyle
, (LPARAM
)hWndParent
);
983 // -----------------------------------------------------------------------
985 void WinSalInstance::DestroyFrame( SalFrame
* pFrame
)
987 ImplSendMessage( mhComWnd
, SAL_MSG_DESTROYFRAME
, 0, (LPARAM
)pFrame
);
990 // -----------------------------------------------------------------------
992 SalObject
* WinSalInstance::CreateObject( SalFrame
* pParent
,
993 SystemWindowData
* /*pWindowData*/, // SystemWindowData meaningless on Windows
996 // to switch to Main-Thread
997 return (SalObject
*)ImplSendMessage( mhComWnd
, SAL_MSG_CREATEOBJECT
, 0, (LPARAM
)static_cast<WinSalFrame
*>(pParent
) );
1000 // -----------------------------------------------------------------------
1002 void WinSalInstance::DestroyObject( SalObject
* pObject
)
1004 ImplSendMessage( mhComWnd
, SAL_MSG_DESTROYOBJECT
, 0, (LPARAM
)pObject
);
1007 // -----------------------------------------------------------------------
1009 void* WinSalInstance::GetConnectionIdentifier( ConnectionIdentifierType
& rReturnedType
, int& rReturnedBytes
)
1012 rReturnedType
= AsciiCString
;
1013 return const_cast<char *>("");
1016 // -----------------------------------------------------------------------
1018 /** Add a file to the system shells recent document list if there is any.
1019 This function may have no effect under Unix because there is no
1020 standard API among the different desktop managers.
1023 The file url of the document.
1025 void WinSalInstance::AddToRecentDocumentList(const OUString
& rFileUrl
, const OUString
& /*rMimeType*/, const OUString
& rDocumentService
)
1027 OUString system_path
;
1028 osl::FileBase::RC rc
= osl::FileBase::getSystemPathFromFileURL(rFileUrl
, system_path
);
1030 OSL_ENSURE(osl::FileBase::E_None
== rc
, "Invalid file url");
1032 if (osl::FileBase::E_None
== rc
)
1034 if ( aSalShlData
.mbW7
)
1036 typedef HRESULT ( WINAPI
*SHCREATEITEMFROMPARSINGNAME
)( PCWSTR
, IBindCtx
*, REFIID
, void **ppv
);
1037 SHCREATEITEMFROMPARSINGNAME pSHCreateItemFromParsingName
=
1038 ( SHCREATEITEMFROMPARSINGNAME
)GetProcAddress(
1039 GetModuleHandleW (L
"shell32.dll"), "SHCreateItemFromParsingName" );
1041 if( pSHCreateItemFromParsingName
)
1043 IShellItem
* pShellItem
= NULL
;
1045 HRESULT hr
= pSHCreateItemFromParsingName ( system_path
.getStr(), NULL
, IID_PPV_ARGS(&pShellItem
) );
1047 if ( SUCCEEDED(hr
) && pShellItem
)
1049 OUString sApplicationName
;
1051 if ( rDocumentService
== "com.sun.star.text.TextDocument" ||
1052 rDocumentService
== "com.sun.star.text.GlobalDocument" ||
1053 rDocumentService
== "com.sun.star.text.WebDocument" ||
1054 rDocumentService
== "com.sun.star.xforms.XMLFormDocument" )
1055 sApplicationName
= "Writer";
1056 else if ( rDocumentService
== "com.sun.star.sheet.SpreadsheetDocument" ||
1057 rDocumentService
== "com.sun.star.chart2.ChartDocument" )
1058 sApplicationName
= "Calc";
1059 else if ( rDocumentService
== "com.sun.star.presentation.PresentationDocument" )
1060 sApplicationName
= "Impress";
1061 else if ( rDocumentService
== "com.sun.star.drawing.DrawingDocument" )
1062 sApplicationName
= "Draw";
1063 else if ( rDocumentService
== "com.sun.star.formula.FormulaProperties" )
1064 sApplicationName
= "Math";
1065 else if ( rDocumentService
== "com.sun.star.sdb.DatabaseDocument" ||
1066 rDocumentService
== "com.sun.star.sdb.OfficeDatabaseDocument" ||
1067 rDocumentService
== "com.sun.star.sdb.RelationDesign" ||
1068 rDocumentService
== "com.sun.star.sdb.QueryDesign" ||
1069 rDocumentService
== "com.sun.star.sdb.TableDesign" ||
1070 rDocumentService
== "com.sun.star.sdb.DataSourceBrowser" )
1071 sApplicationName
= "Base";
1073 if ( !sApplicationName
.isEmpty() )
1075 OUString
sApplicationID("TheDocumentFoundation.LibreOffice.");
1076 sApplicationID
+= sApplicationName
;
1078 SHARDAPPIDINFO info
;
1079 info
.psi
= pShellItem
;
1080 info
.pszAppID
= sApplicationID
.getStr();
1082 SHAddToRecentDocs ( SHARD_APPIDINFO
, &info
);
1088 // For whatever reason, we could not use the SHARD_APPIDNFO semantics
1089 SHAddToRecentDocs(SHARD_PATHW
, system_path
.getStr());
1093 // -----------------------------------------------------------------------
1095 SalTimer
* WinSalInstance::CreateSalTimer()
1097 return new WinSalTimer();
1100 // -----------------------------------------------------------------------
1102 SalBitmap
* WinSalInstance::CreateSalBitmap()
1104 return new WinSalBitmap();
1107 class WinImeStatus
: public SalI18NImeStatus
1111 virtual ~WinImeStatus() {}
1113 // asks whether there is a status window available
1114 // to toggle into menubar
1115 virtual bool canToggle() { return false; }
1116 virtual void toggle() {}
1119 SalI18NImeStatus
* WinSalInstance::CreateI18NImeStatus()
1121 return new WinImeStatus();
1124 // -----------------------------------------------------------------------
1126 const OUString
& SalGetDesktopEnvironment()
1128 static OUString
aDesktopEnvironment( "Windows" );
1129 return aDesktopEnvironment
;
1132 SalSession
* WinSalInstance::CreateSalSession()
1138 // -----------------------------------------------------------------------
1139 int WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(int, LPEXCEPTION_POINTERS pExceptionInfo
)
1141 // Decide if an exception is a c++ (mostly UNO) exception or a process violation.
1142 // Depending on this information we pass process violations directly to our signal handler ...
1143 // and c++ (UNO) exceptions are sended to the following code on the current stack.
1144 // Problem behind: user32.dll sometime consumes exceptions/process violations .-)
1145 // see also #112221#
1147 static DWORD EXCEPTION_MSC_CPP_EXCEPTION
= 0xE06D7363;
1149 if (pExceptionInfo
->ExceptionRecord
->ExceptionCode
== EXCEPTION_MSC_CPP_EXCEPTION
)
1150 return EXCEPTION_CONTINUE_SEARCH
;
1152 return UnhandledExceptionFilter( pExceptionInfo
);
1156 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */