merged tag ooo/DEV300_m102
[LibreOffice.git] / vcl / win / source / app / salinst.cxx
blob05cb20750abdb7771422e4a6bf1d63780e82e6a9
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"
31 #include <string.h>
32 #include <tools/svwin.h>
33 #ifdef WNT
34 #include <process.h>
35 #endif
36 #ifdef __MINGW32__
37 #include <excpt.h>
38 #endif
39 #include <osl/file.hxx>
40 #include <vos/mutex.hxx>
41 #include <tools/debug.hxx>
42 #include <wincomp.hxx>
43 #include <salids.hrc>
44 #include <saldata.hxx>
45 #include <salinst.h>
46 #include <salframe.h>
47 #include <salobj.h>
48 #include <vcl/salsys.hxx>
49 #include <saltimer.h>
50 #include <vcl/apptypes.hxx>
51 #include <salbmp.h>
52 #include <vcl/salimestatus.hxx>
53 #include <vcl/timer.hxx>
54 #include <wincomp.hxx> // CS_DROPSHADOW
55 #include <tools/solarmutex.hxx>
57 #ifndef min
58 #define min(a,b) (((a) < (b)) ? (a) : (b))
59 #endif
60 #ifndef max
61 #define max(a,b) (((a) > (b)) ? (a) : (b))
62 #endif
64 #if defined _MSC_VER
65 #pragma warning(push, 1)
66 #pragma warning( disable: 4917 )
67 #endif
69 #include <GdiPlus.h>
70 #include <GdiPlusEnums.h>
71 #include <GdiPlusColor.h>
72 #include <Shlobj.h>
74 #if defined _MSC_VER
75 #pragma warning(pop)
76 #endif
78 // =======================================================================
80 void SalAbort( const XubString& rErrorText )
82 ImplFreeSalGDI();
84 if ( !rErrorText.Len() )
86 // #112255# make sure crash reporter is triggered
87 RaiseException( 0, EXCEPTION_NONCONTINUABLE, 0, NULL );
88 FatalAppExit( 0, "Application Error" );
90 else
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;
110 sal_uLong mnCount;
111 DWORD mnThreadId;
113 public:
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;
128 mnCount = 0;
129 mnThreadId = 0;
132 // -----------------------------------------------------------------------
134 void SAL_CALL SalYieldMutex::acquire()
136 OMutex::acquire();
137 mnCount++;
138 mnThreadId = GetCurrentThreadId();
141 // -----------------------------------------------------------------------
143 void SAL_CALL SalYieldMutex::release()
145 DWORD nThreadId = GetCurrentThreadId();
146 if ( mnThreadId != nThreadId )
147 OMutex::release();
148 else
150 SalData* pSalData = GetSalData();
151 if ( pSalData->mnAppThreadId != nThreadId )
153 if ( mnCount == 1 )
155 // If we don't call these message, the Output from the
156 // Java clients doesn't come in the right order
157 GdiFlush();
159 mpInstData->mpSalWaitMutex->acquire();
160 if ( mpInstData->mnYieldWaitCount )
161 ImplPostMessage( mpInstData->mhComWnd, SAL_MSG_RELEASEWAITYIELD, 0, 0 );
162 mnThreadId = 0;
163 mnCount--;
164 OMutex::release();
165 mpInstData->mpSalWaitMutex->release();
167 else
169 mnCount--;
170 OMutex::release();
173 else
175 if ( mnCount == 1 )
176 mnThreadId = 0;
177 mnCount--;
178 OMutex::release();
183 // -----------------------------------------------------------------------
185 sal_Bool SAL_CALL SalYieldMutex::tryToAcquire()
187 if( OMutex::tryToAcquire() )
189 mnCount++;
190 mnThreadId = GetCurrentThreadId();
191 return sal_True;
193 else
194 return sal_False;
197 // -----------------------------------------------------------------------
199 sal_uLong SalYieldMutex::GetAcquireCount( sal_uLong nThreadId )
201 if ( nThreadId == mnThreadId )
202 return mnCount;
203 else
204 return 0;
207 // -----------------------------------------------------------------------
209 void ImplSalYieldMutexAcquireWithWait()
211 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
212 if ( !pInst )
213 return;
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() )
229 bAcquire = TRUE;
230 else
232 pInst->mpSalWaitMutex->acquire();
233 if ( pInst->mpSalYieldMutex->tryToAcquire() )
235 bAcquire = TRUE;
236 pInst->mpSalWaitMutex->release();
238 else
240 pInst->mnYieldWaitCount++;
241 pInst->mpSalWaitMutex->release();
242 MSG aTmpMsg;
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 );
250 while ( !bAcquire );
252 else
253 pInst->mpSalYieldMutex->acquire();
256 // -----------------------------------------------------------------------
258 sal_Bool ImplSalYieldMutexTryToAcquire()
260 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
261 if ( pInst )
262 return pInst->mpSalYieldMutex->tryToAcquire();
263 else
264 return FALSE;
267 // -----------------------------------------------------------------------
269 void ImplSalYieldMutexAcquire()
271 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
272 if ( pInst )
273 pInst->mpSalYieldMutex->acquire();
276 // -----------------------------------------------------------------------
278 void ImplSalYieldMutexRelease()
280 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
281 if ( pInst )
283 GdiFlush();
284 pInst->mpSalYieldMutex->release();
288 // -----------------------------------------------------------------------
290 sal_uLong ImplSalReleaseYieldMutex()
292 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
293 if ( !pInst )
294 return 0;
296 SalYieldMutex* pYieldMutex = pInst->mpSalYieldMutex;
297 sal_uLong nCount = pYieldMutex->GetAcquireCount( GetCurrentThreadId() );
298 sal_uLong n = nCount;
299 while ( n )
301 pYieldMutex->release();
302 n--;
305 return nCount;
308 // -----------------------------------------------------------------------
310 void ImplSalAcquireYieldMutex( sal_uLong nCount )
312 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
313 if ( !pInst )
314 return;
316 SalYieldMutex* pYieldMutex = pInst->mpSalYieldMutex;
317 while ( nCount )
319 pYieldMutex->acquire();
320 nCount--;
324 // -----------------------------------------------------------------------
326 bool WinSalInstance::CheckYieldMutex()
328 bool bRet = true;
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 )
338 bRet = false;
342 else
344 if ( pSalData->mpFirstInstance )
346 SalYieldMutex* pYieldMutex = pSalData->mpFirstInstance->mpSalYieldMutex;
347 if ( pYieldMutex->mnThreadId != nCurThreadId )
349 bRet = false;
353 return bRet;
356 // =======================================================================
358 void SalData::initKeyCodeMap()
360 UINT nKey = 0xffffffff;
361 #define initKey( a, b )\
362 nKey = LOWORD( VkKeyScan( a ) );\
363 if( nKey < 0xffff )\
364 maVKMap[ nKey ] = b;
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 // =======================================================================
380 // -------
381 // SalData
382 // -------
384 SalData::SalData()
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)
398 mnNextTimerTime = 0;
399 mnLastEventTime = 0;
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
413 int i;
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
435 mpTempFontItem = 0;
436 mbThemeChanged = FALSE; // true if visual theme was changed: throw away theme handles
437 mbThemeMenuSupport = FALSE;
439 // init with NULL
440 gdiplusToken = 0;
441 maDwmLib = 0;
442 mpDwmIsCompositionEnabled = 0;
444 initKeyCodeMap();
446 SetSalData( this );
447 initNWF();
450 SalData::~SalData()
452 deInitNWF();
453 SetSalData( NULL );
456 void InitSalData()
458 SalData* pSalData = new SalData;
459 CoInitialize(0);
461 // init GDIPlus
462 static Gdiplus::GdiplusStartupInput gdiplusStartupInput;
463 Gdiplus::GdiplusStartup(&pSalData->gdiplusToken, &gdiplusStartupInput, NULL);
467 void DeInitSalData()
469 CoUninitialize();
470 SalData* pSalData = GetSalData();
472 // deinit GDIPlus
473 if(pSalData)
475 Gdiplus::GdiplusShutdown(pSalData->gdiplusToken);
478 delete pSalData;
481 // -----------------------------------------------------------------------
483 void InitSalMain()
485 // remember data, copied from WinMain
486 SalData* pData = GetAppSalData();
487 if ( pData ) // Im AppServer NULL
489 STARTUPINFO aSI;
490 aSI.cb = sizeof( aSI );
491 GetStartupInfo( &aSI );
492 pData->mhInst = GetModuleHandle( NULL );
493 pData->mhPrevInst = NULL;
494 pData->mnCmdShow = aSI.wShowWindow;
498 void DeInitSalMain()
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 )
521 // Windows XP ?
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 ) )
548 return NULL;
550 aWndClassEx.hIcon = 0;
551 aWndClassEx.hIconSm = 0;
552 aWndClassEx.style |= CS_SAVEBITS;
553 aWndClassEx.lpszClassName = SAL_SUBFRAME_CLASSNAMEW;
554 if ( !RegisterClassExW( &aWndClassEx ) )
555 return NULL;
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 ) )
562 return NULL;
564 aWndClassEx.style = 0;
565 aWndClassEx.lpfnWndProc = SalComWndProcW;
566 aWndClassEx.cbWndExtra = 0;
567 aWndClassEx.lpszClassName = SAL_COM_CLASSNAMEW;
568 if ( !RegisterClassExW( &aWndClassEx ) )
569 return NULL;
572 HWND hComWnd = CreateWindowExW( WS_EX_TOOLWINDOW, SAL_COM_CLASSNAMEW,
573 L"", WS_POPUP, 0, 0, 0, 0, 0, 0,
574 pSalData->mhInst, NULL );
575 if ( !hComWnd )
576 return 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
586 ImplInitSalGDI();
588 return pInst;
591 // -----------------------------------------------------------------------
593 void DestroySalInstance( SalInstance* pInst )
595 SalData* pSalData = GetSalData();
597 // (only one instance in this version !!!)
599 ImplFreeSalGDI();
601 // reset instance
602 if ( pSalData->mpFirstInstance == pInst )
603 pSalData->mpFirstInstance = NULL;
605 delete pInst;
608 // -----------------------------------------------------------------------
610 WinSalInstance::WinSalInstance()
612 mhComWnd = 0;
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 ) )
660 return;
662 LRESULT lResult = ImplDispatchMessage( pMsg );
663 if ( pSalData->mpFirstObject )
664 ImplSalPostDispatchMsg( pMsg, lResult );
667 // -----------------------------------------------------------------------
669 void ImplSalYield( sal_Bool bWait, sal_Bool bHandleAllCurrentEvents )
671 MSG aMsg;
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;
687 else
688 bOneEvent = false;
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;
713 while ( n )
715 pYieldMutex->release();
716 n--;
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 )
731 Sleep(1);
732 else
733 ImplSendMessage( mhComWnd, SAL_MSG_THREADYIELD, (WPARAM)bWait, (LPARAM)bHandleAllCurrentEvents );
735 n = nCount;
736 while ( n )
738 pYieldMutex->acquire();
739 n--;
742 else
744 ImplSalYield( bWait, bHandleAllCurrentEvents );
746 n = nCount;
747 while ( n )
749 ImplSalYieldMutexAcquireWithWait();
750 n--;
755 // -----------------------------------------------------------------------
757 LRESULT CALLBACK SalComWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef )
759 LRESULT nRet = 0;
762 switch ( nMsg )
764 case SAL_MSG_PRINTABORTJOB:
765 ImplSalPrinterAbortJobAsync( (HDC)wParam );
766 rDef = FALSE;
767 break;
768 case SAL_MSG_THREADYIELD:
769 ImplSalYield( (sal_Bool)wParam, (sal_Bool)lParam );
770 rDef = FALSE;
771 break;
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 );
781 rDef = FALSE;
782 break;
783 case SAL_MSG_STARTTIMER:
784 ImplSalStartTimer( (sal_uLong) lParam, FALSE );
785 rDef = FALSE;
786 break;
787 case SAL_MSG_CREATEFRAME:
788 nRet = (LRESULT)ImplSalCreateFrame( GetSalData()->mpFirstInstance, (HWND)lParam, (sal_uLong)wParam );
789 rDef = FALSE;
790 break;
791 case SAL_MSG_RECREATEHWND:
792 nRet = (LRESULT)ImplSalReCreateHWND( (HWND)wParam, (HWND)lParam, FALSE );
793 rDef = FALSE;
794 break;
795 case SAL_MSG_RECREATECHILDHWND:
796 nRet = (LRESULT)ImplSalReCreateHWND( (HWND)wParam, (HWND)lParam, TRUE );
797 rDef = FALSE;
798 break;
799 case SAL_MSG_DESTROYFRAME:
800 delete (SalFrame*)lParam;
801 rDef = FALSE;
802 break;
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);
813 rDef = FALSE;
814 break;
815 case SAL_MSG_CREATEOBJECT:
816 nRet = (LRESULT)ImplSalCreateObject( GetSalData()->mpFirstInstance, (WinSalFrame*)lParam );
817 rDef = FALSE;
818 break;
819 case SAL_MSG_DESTROYOBJECT:
820 delete (SalObject*)lParam;
821 rDef = FALSE;
822 break;
823 case SAL_MSG_GETDC:
824 nRet = (LRESULT)GetDCEx( (HWND)wParam, 0, DCX_CACHE );
825 rDef = FALSE;
826 break;
827 case SAL_MSG_RELEASEDC:
828 ReleaseDC( (HWND)wParam, (HDC)lParam );
829 rDef = FALSE;
830 break;
831 case SAL_MSG_POSTTIMER:
832 SalTimerProc( 0, 0, SALTIMERPROC_RECURSIVE, lParam );
833 break;
836 return nRet;
839 LRESULT CALLBACK SalComWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
841 int bDef = TRUE;
842 LRESULT nRet = 0;
843 #ifdef __MINGW32__
844 jmp_buf jmpbuf;
845 __SEHandler han;
846 if (__builtin_setjmp(jmpbuf) == 0)
848 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
849 #else
850 __try
852 #endif
853 nRet = SalComWndProc( hWnd, nMsg, wParam, lParam, bDef );
855 #ifdef __MINGW32__
856 han.Reset();
857 #else
858 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
861 #endif
862 if ( bDef )
864 if ( !ImplHandleGlobalMsg( hWnd, nMsg, wParam, lParam, nRet ) )
865 nRet = DefWindowProcA( hWnd, nMsg, wParam, lParam );
867 return nRet;
870 LRESULT CALLBACK SalComWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
872 int bDef = TRUE;
873 LRESULT nRet = 0;
874 #ifdef __MINGW32__
875 jmp_buf jmpbuf;
876 __SEHandler han;
877 if (__builtin_setjmp(jmpbuf) == 0)
879 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
880 #else
881 __try
883 #endif
884 nRet = SalComWndProc( hWnd, nMsg, wParam, lParam, bDef );
886 #ifdef __MINGW32__
887 han.Reset();
888 #else
889 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
892 #endif
893 if ( bDef )
895 if ( !ImplHandleGlobalMsg( hWnd, nMsg, wParam, lParam, nRet ) )
896 nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam );
898 return nRet;
901 // -----------------------------------------------------------------------
903 bool WinSalInstance::AnyInput( sal_uInt16 nType )
905 MSG aMsg;
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 ) )
912 return true;
914 else
916 if ( nType & INPUT_MOUSE )
918 // Test for mouse input
919 if ( ImplPeekMessage( &aMsg, 0, WM_MOUSEFIRST, WM_MOUSELAST,
920 PM_NOREMOVE | PM_NOYIELD ) )
921 return true;
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) )
933 return false;
934 else
935 return true;
939 if ( nType & INPUT_PAINT )
941 // Test for paint input
942 if ( ImplPeekMessage( &aMsg, 0, WM_PAINT, WM_PAINT,
943 PM_NOREMOVE | PM_NOYIELD ) )
944 return true;
946 if ( ImplPeekMessage( &aMsg, 0, WM_SIZE, WM_SIZE,
947 PM_NOREMOVE | PM_NOYIELD ) )
948 return true;
950 if ( ImplPeekMessage( &aMsg, 0, SAL_MSG_POSTCALLSIZE, SAL_MSG_POSTCALLSIZE,
951 PM_NOREMOVE | PM_NOYIELD ) )
952 return true;
954 if ( ImplPeekMessage( &aMsg, 0, WM_MOVE, WM_MOVE,
955 PM_NOREMOVE | PM_NOYIELD ) )
956 return true;
958 if ( ImplPeekMessage( &aMsg, 0, SAL_MSG_POSTMOVE, SAL_MSG_POSTMOVE,
959 PM_NOREMOVE | PM_NOYIELD ) )
960 return true;
963 if ( nType & INPUT_TIMER )
965 // Test for timer input
966 if ( ImplPeekMessage( &aMsg, 0, WM_TIMER, WM_TIMER,
967 PM_NOREMOVE | PM_NOYIELD ) )
968 return true;
972 if ( nType & INPUT_OTHER )
974 // Test for any input
975 if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_NOREMOVE | PM_NOYIELD ) )
976 return true;
980 return FALSE;
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 );
993 else
994 ImplSendMessage( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS );
996 else
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
1013 HWND hWndParent;
1014 if ( pParent )
1015 hWndParent = static_cast<WinSalFrame*>(pParent)->mhWnd;
1016 else
1017 hWndParent = 0;
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 )
1049 rReturnedBytes = 1;
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.
1060 @param aFileUrl
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
1090 public:
1091 WinImeStatus() {}
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()
1115 return NULL;
1118 #ifndef __MINGW32__
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 );
1135 #endif