update dev300-m58
[ooovba.git] / vcl / win / source / app / salinst.cxx
blobc071cb6a43bf1d672f803d71cb0182953a96e69a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salinst.cxx,v $
10 * $Revision: 1.42.154.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include <string.h>
35 #include <tools/svwin.h>
36 #ifdef WNT
37 #include <process.h>
38 #endif
39 #ifdef __MINGW32__
40 #include <excpt.h>
41 #endif
43 #include <vos/mutex.hxx>
44 #include <tools/debug.hxx>
45 #include <wincomp.hxx>
46 #include <salids.hrc>
47 #include <saldata.hxx>
48 #include <salinst.h>
49 #include <salframe.h>
50 #include <salobj.h>
51 #include <vcl/salsys.hxx>
52 #include <saltimer.h>
53 #include <vcl/salatype.hxx>
54 #include <salbmp.h>
55 #include <vcl/salimestatus.hxx>
56 #include <vcl/timer.hxx>
57 #include <wincomp.hxx> // CS_DROPSHADOW
59 #ifndef min
60 #define min(a,b) (((a) < (b)) ? (a) : (b))
61 #endif
62 #ifndef max
63 #define max(a,b) (((a) > (b)) ? (a) : (b))
64 #endif
66 #if defined _MSC_VER
67 #pragma warning(push, 1)
68 #endif
70 #include <GdiPlus.h>
71 #include <GdiPlusEnums.h>
72 #include <GdiPlusColor.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 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 ULONG GetAcquireCount( 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 ULONG SalYieldMutex::GetAcquireCount( 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 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 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 ULONG ImplSalReleaseYieldMutex()
292 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
293 if ( !pInst )
294 return 0;
296 SalYieldMutex* pYieldMutex = pInst->mpSalYieldMutex;
297 ULONG nCount = pYieldMutex->GetAcquireCount( GetCurrentThreadId() );
298 ULONG n = nCount;
299 while ( n )
301 pYieldMutex->release();
302 n--;
305 return nCount;
308 // -----------------------------------------------------------------------
310 void ImplSalAcquireYieldMutex( 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 #ifdef DBG_UTIL
328 void ImplDbgTestSolarMutex()
330 SalData* pSalData = GetSalData();
331 DWORD nCurThreadId = GetCurrentThreadId();
332 if ( pSalData->mnAppThreadId != nCurThreadId )
334 if ( pSalData->mpFirstInstance )
336 SalYieldMutex* pYieldMutex = pSalData->mpFirstInstance->mpSalYieldMutex;
337 if ( pYieldMutex->mnThreadId != nCurThreadId )
339 DBG_ERROR( "SolarMutex not locked, and not thread save code in VCL is called from outside of the main thread" );
343 else
345 if ( pSalData->mpFirstInstance )
347 SalYieldMutex* pYieldMutex = pSalData->mpFirstInstance->mpSalYieldMutex;
348 if ( pYieldMutex->mnThreadId != nCurThreadId )
350 DBG_ERROR( "SolarMutex not locked in the main thread" );
356 #endif
358 // =======================================================================
360 void SalData::initKeyCodeMap()
362 UINT nKey = 0xffffffff;
363 #define initKey( a, b )\
364 nKey = LOWORD( VkKeyScan( a ) );\
365 if( nKey < 0xffff )\
366 maVKMap[ nKey ] = b;
368 initKey( '+', KEY_ADD );
369 initKey( '-', KEY_SUBTRACT );
370 initKey( '*', KEY_MULTIPLY );
371 initKey( '/', KEY_DIVIDE );
372 initKey( '.', KEY_POINT );
373 initKey( ',', KEY_COMMA );
374 initKey( '<', KEY_LESS );
375 initKey( '>', KEY_GREATER );
376 initKey( '=', KEY_EQUAL );
377 initKey( '~', KEY_TILDE );
378 initKey( '`', KEY_QUOTELEFT );
379 initKey( '[', KEY_BRACKETLEFT );
380 initKey( ']', KEY_BRACKETRIGHT );
383 // =======================================================================
384 // -------
385 // SalData
386 // -------
388 SalData::SalData()
390 mhInst = 0; // default instance handle
391 mhPrevInst = 0; // previous instance handle
392 mnCmdShow = 0; // default frame show style
393 mhDitherPal = 0; // dither palette
394 mhDitherDIB = 0; // dither memory handle
395 mpDitherDIB = 0; // dither memory
396 mpDitherDIBData = 0; // beginning of DIB data
397 mpDitherDiff = 0; // Dither mapping table
398 mpDitherLow = 0; // Dither mapping table
399 mpDitherHigh = 0; // Dither mapping table
400 mnTimerMS = 0; // Current Time (in MS) of the Timer
401 mnTimerOrgMS = 0; // Current Original Time (in MS)
402 mnNextTimerTime = 0;
403 mnLastEventTime = 0;
404 mnTimerId = 0; // windows timer id
405 mbInTimerProc = FALSE; // timer event is currently being dispatched
406 mhSalObjMsgHook = 0; // hook to get interesting msg for SalObject
407 mhWantLeaveMsg = 0; // window handle, that want a MOUSELEAVE message
408 mpMouseLeaveTimer = 0; // Timer for MouseLeave Test
409 mpFirstInstance = 0; // pointer of first instance
410 mpFirstFrame = 0; // pointer of first frame
411 mpFirstObject = 0; // pointer of first object window
412 mpFirstVD = 0; // first VirDev
413 mpFirstPrinter = 0; // first printing printer
414 mpHDCCache = 0; // Cache for three DC's
415 mh50Bmp = 0; // 50% Bitmap
416 mh50Brush = 0; // 50% Brush
417 int i;
418 for(i=0; i<MAX_STOCKPEN; i++)
420 maStockPenColorAry[i] = 0;
421 mhStockPenAry[i] = 0;
423 for(i=0; i<MAX_STOCKBRUSH; i++)
425 maStockBrushColorAry[i] = 0;
426 mhStockBrushAry[i] = 0;
428 mnStockPenCount = 0; // count of static pens
429 mnStockBrushCount = 0; // count of static brushes
430 mnSalObjWantKeyEvt = 0; // KeyEvent, welcher vom SalObj-Hook verarbeitet werden soll
431 mnCacheDCInUse = 0; // count of CacheDC in use
432 mbObjClassInit = FALSE; // is SALOBJECTCLASS initialised
433 mbInPalChange = FALSE; // is in WM_QUERYNEWPALETTE
434 mnAppThreadId = 0; // Id from Applikation-Thread
435 mbScrSvrEnabled = FALSE; // ScreenSaver enabled
436 mnSageStatus = 0; // status of Sage-DLL (DISABLE_AGENT == nicht vorhanden)
437 mpSageEnableProc = 0; // funktion to deactivate the system agent
438 mpFirstIcon = 0; // icon cache, points to first icon, NULL if none
439 mpTempFontItem = 0;
440 mbThemeChanged = FALSE; // true if visual theme was changed: throw away theme handles
442 // init with NULL
443 gdiplusToken = 0;
445 initKeyCodeMap();
447 SetSalData( this );
448 initNWF();
451 SalData::~SalData()
453 deInitNWF();
454 SetSalData( NULL );
457 void InitSalData()
459 SalData* pSalData = new SalData;
460 CoInitialize(0);
462 // init GDIPlus
463 static Gdiplus::GdiplusStartupInput gdiplusStartupInput;
464 Gdiplus::GdiplusStartup(&pSalData->gdiplusToken, &gdiplusStartupInput, NULL);
468 void DeInitSalData()
470 CoUninitialize();
471 SalData* pSalData = GetSalData();
473 // deinit GDIPlus
474 if(pSalData)
476 Gdiplus::GdiplusShutdown(pSalData->gdiplusToken);
479 delete pSalData;
482 // -----------------------------------------------------------------------
484 void InitSalMain()
486 // remember data, copied from WinMain
487 SalData* pData = GetAppSalData();
488 if ( pData ) // Im AppServer NULL
490 STARTUPINFO aSI;
491 aSI.cb = sizeof( aSI );
492 GetStartupInfo( &aSI );
493 pData->mhInst = GetModuleHandle( NULL );
494 pData->mhPrevInst = NULL;
495 pData->mnCmdShow = aSI.wShowWindow;
499 void DeInitSalMain()
503 // -----------------------------------------------------------------------
505 SalInstance* CreateSalInstance()
507 SalData* pSalData = GetSalData();
509 // determine the windows version
510 aSalShlData.mbWNT = 0;
511 aSalShlData.mbWXP = 0;
512 aSalShlData.mbWPrinter = 0;
513 WORD nVer = (WORD)GetVersion();
514 aSalShlData.mnVersion = (((WORD)LOBYTE(nVer)) * 100) + HIBYTE(nVer);
515 if ( aSalShlData.mnVersion >= 400 )
516 aSalShlData.mbW40 = 1;
517 rtl_zeroMemory( &aSalShlData.maVersionInfo, sizeof(aSalShlData.maVersionInfo) );
518 aSalShlData.maVersionInfo.dwOSVersionInfoSize = sizeof( aSalShlData.maVersionInfo );
519 if ( GetVersionEx( &aSalShlData.maVersionInfo ) )
521 if ( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
523 aSalShlData.mbWNT = 1;
524 // Windows XP ?
525 if ( aSalShlData.maVersionInfo.dwMajorVersion > 5 ||
526 ( aSalShlData.maVersionInfo.dwMajorVersion == 5 && aSalShlData.maVersionInfo.dwMinorVersion >= 1 ) )
527 aSalShlData.mbWXP = 1;
528 if( aSalShlData.maVersionInfo.dwMajorVersion >= 5 )
529 aSalShlData.mbWPrinter = 1;
533 pSalData->mnAppThreadId = GetCurrentThreadId();
535 // register frame class
536 if ( !pSalData->mhPrevInst )
538 if ( aSalShlData.mbWNT )
540 WNDCLASSEXW aWndClassEx;
541 aWndClassEx.cbSize = sizeof( aWndClassEx );
542 aWndClassEx.style = CS_OWNDC;
543 aWndClassEx.lpfnWndProc = SalFrameWndProcW;
544 aWndClassEx.cbClsExtra = 0;
545 aWndClassEx.cbWndExtra = SAL_FRAME_WNDEXTRA;
546 aWndClassEx.hInstance = pSalData->mhInst;
547 aWndClassEx.hCursor = 0;
548 aWndClassEx.hbrBackground = 0;
549 aWndClassEx.lpszMenuName = 0;
550 aWndClassEx.lpszClassName = SAL_FRAME_CLASSNAMEW;
551 ImplLoadSalIcon( SAL_RESID_ICON_DEFAULT, aWndClassEx.hIcon, aWndClassEx.hIconSm );
552 if ( !RegisterClassExW( &aWndClassEx ) )
553 return NULL;
555 aWndClassEx.hIcon = 0;
556 aWndClassEx.hIconSm = 0;
557 aWndClassEx.style |= CS_SAVEBITS;
558 aWndClassEx.lpszClassName = SAL_SUBFRAME_CLASSNAMEW;
559 if ( !RegisterClassExW( &aWndClassEx ) )
560 return NULL;
562 // shadow effect for popups on XP
563 if( aSalShlData.mbWXP )
564 aWndClassEx.style |= CS_DROPSHADOW;
565 aWndClassEx.lpszClassName = SAL_TMPSUBFRAME_CLASSNAMEW;
566 if ( !RegisterClassExW( &aWndClassEx ) )
567 return NULL;
569 aWndClassEx.style = 0;
570 aWndClassEx.lpfnWndProc = SalComWndProcW;
571 aWndClassEx.cbWndExtra = 0;
572 aWndClassEx.lpszClassName = SAL_COM_CLASSNAMEW;
573 if ( !RegisterClassExW( &aWndClassEx ) )
574 return NULL;
576 else
578 WNDCLASSEXA aWndClassEx;
579 aWndClassEx.cbSize = sizeof( aWndClassEx );
580 aWndClassEx.style = CS_OWNDC;
581 aWndClassEx.lpfnWndProc = SalFrameWndProcA;
582 aWndClassEx.cbClsExtra = 0;
583 aWndClassEx.cbWndExtra = SAL_FRAME_WNDEXTRA;
584 aWndClassEx.hInstance = pSalData->mhInst;
585 aWndClassEx.hCursor = 0;
586 aWndClassEx.hbrBackground = 0;
587 aWndClassEx.lpszMenuName = 0;
588 aWndClassEx.lpszClassName = SAL_FRAME_CLASSNAMEA;
589 ImplLoadSalIcon( SAL_RESID_ICON_DEFAULT, aWndClassEx.hIcon, aWndClassEx.hIconSm );
590 if ( !RegisterClassExA( &aWndClassEx ) )
591 return NULL;
593 aWndClassEx.hIcon = 0;
594 aWndClassEx.hIconSm = 0;
595 aWndClassEx.style |= CS_SAVEBITS;
596 aWndClassEx.lpszClassName = SAL_SUBFRAME_CLASSNAMEA;
597 if ( !RegisterClassExA( &aWndClassEx ) )
598 return NULL;
600 aWndClassEx.style = 0;
601 aWndClassEx.lpfnWndProc = SalComWndProcA;
602 aWndClassEx.cbWndExtra = 0;
603 aWndClassEx.lpszClassName = SAL_COM_CLASSNAMEA;
604 if ( !RegisterClassExA( &aWndClassEx ) )
605 return NULL;
609 HWND hComWnd;
610 if ( aSalShlData.mbWNT )
612 hComWnd = CreateWindowExW( WS_EX_TOOLWINDOW, SAL_COM_CLASSNAMEW,
613 L"", WS_POPUP, 0, 0, 0, 0, 0, 0,
614 pSalData->mhInst, NULL );
616 else
618 hComWnd = CreateWindowExA( WS_EX_TOOLWINDOW, SAL_COM_CLASSNAMEA,
619 "", WS_POPUP, 0, 0, 0, 0, 0, 0,
620 pSalData->mhInst, NULL );
622 if ( !hComWnd )
623 return NULL;
625 WinSalInstance* pInst = new WinSalInstance;
627 // init instance (only one instance in this version !!!)
628 pSalData->mpFirstInstance = pInst;
629 pInst->mhInst = pSalData->mhInst;
630 pInst->mhComWnd = hComWnd;
632 // init static GDI Data
633 ImplInitSalGDI();
635 return pInst;
638 // -----------------------------------------------------------------------
640 void DestroySalInstance( SalInstance* pInst )
642 SalData* pSalData = GetSalData();
644 // (only one instance in this version !!!)
646 ImplFreeSalGDI();
648 // reset instance
649 if ( pSalData->mpFirstInstance == pInst )
650 pSalData->mpFirstInstance = NULL;
652 delete pInst;
655 // -----------------------------------------------------------------------
657 WinSalInstance::WinSalInstance()
659 mhComWnd = 0;
660 mpSalYieldMutex = new SalYieldMutex( this );
661 mpSalWaitMutex = new vos::OMutex;
662 mnYieldWaitCount = 0;
663 mpSalYieldMutex->acquire();
666 // -----------------------------------------------------------------------
668 WinSalInstance::~WinSalInstance()
670 mpSalYieldMutex->release();
671 delete mpSalYieldMutex;
672 delete mpSalWaitMutex;
673 DestroyWindow( mhComWnd );
676 // -----------------------------------------------------------------------
678 vos::IMutex* WinSalInstance::GetYieldMutex()
680 return mpSalYieldMutex;
683 // -----------------------------------------------------------------------
685 ULONG WinSalInstance::ReleaseYieldMutex()
687 return ImplSalReleaseYieldMutex();
690 // -----------------------------------------------------------------------
692 void WinSalInstance::AcquireYieldMutex( ULONG nCount )
694 ImplSalAcquireYieldMutex( nCount );
697 // -----------------------------------------------------------------------
699 static void ImplSalDispatchMessage( MSG* pMsg )
701 SalData* pSalData = GetSalData();
702 if ( pSalData->mpFirstObject )
704 if ( ImplSalPreDispatchMsg( pMsg ) )
705 return;
707 LRESULT lResult = ImplDispatchMessage( pMsg );
708 if ( pSalData->mpFirstObject )
709 ImplSalPostDispatchMsg( pMsg, lResult );
712 // -----------------------------------------------------------------------
714 void ImplSalYield( BOOL bWait, BOOL bHandleAllCurrentEvents )
716 MSG aMsg;
717 bool bWasMsg = false, bOneEvent = false;
719 int nMaxEvents = bHandleAllCurrentEvents ? 100 : 1;
722 if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) )
724 TranslateMessage( &aMsg );
725 ImplSalDispatchMessage( &aMsg );
726 bOneEvent = bWasMsg = true;
728 else
729 bOneEvent = false;
730 } while( --nMaxEvents && bOneEvent );
732 if ( bWait && ! bWasMsg )
734 if ( ImplGetMessage( &aMsg, 0, 0, 0 ) )
736 TranslateMessage( &aMsg );
737 ImplSalDispatchMessage( &aMsg );
742 // -----------------------------------------------------------------------
744 void WinSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents )
746 SalYieldMutex* pYieldMutex = mpSalYieldMutex;
747 SalData* pSalData = GetSalData();
748 DWORD nCurThreadId = GetCurrentThreadId();
749 ULONG nCount = pYieldMutex->GetAcquireCount( nCurThreadId );
750 ULONG n = nCount;
751 while ( n )
753 pYieldMutex->release();
754 n--;
756 if ( pSalData->mnAppThreadId != nCurThreadId )
758 // #97739# A SendMessage call blocks until the called thread (here: the main thread)
759 // returns. During a yield however, messages are processed in the main thread that might
760 // result in a new message loop due to opening a dialog. Thus, SendMessage would not
761 // return which will block this thread!
762 // Solution: just give up the time slice and hope that messages are processed
763 // by the main thread anyway (where all windows are created)
764 // If the mainthread is not currently handling messages, then our SendMessage would
765 // also do nothing, so this seems to be reasonable.
767 // #i18883# only sleep if potential deadlock scenario, ie, when a dialog is open
768 if( ImplGetSVData()->maAppData.mnModalMode )
769 Sleep(1);
770 else
771 ImplSendMessage( mhComWnd, SAL_MSG_THREADYIELD, (WPARAM)bWait, (LPARAM)bHandleAllCurrentEvents );
773 n = nCount;
774 while ( n )
776 pYieldMutex->acquire();
777 n--;
780 else
782 ImplSalYield( bWait, bHandleAllCurrentEvents );
784 n = nCount;
785 while ( n )
787 ImplSalYieldMutexAcquireWithWait();
788 n--;
793 // -----------------------------------------------------------------------
795 LRESULT CALLBACK SalComWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef )
797 LRESULT nRet = 0;
800 switch ( nMsg )
802 case SAL_MSG_PRINTABORTJOB:
803 ImplSalPrinterAbortJobAsync( (HDC)wParam );
804 rDef = FALSE;
805 break;
806 case SAL_MSG_THREADYIELD:
807 ImplSalYield( (BOOL)wParam, (BOOL)lParam );
808 rDef = FALSE;
809 break;
810 // If we get this message, because another GetMessage() call
811 // has recieved this message, we must post this message to
812 // us again, because in the other case we wait forever.
813 case SAL_MSG_RELEASEWAITYIELD:
815 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
816 if ( pInst && pInst->mnYieldWaitCount )
817 ImplPostMessage( hWnd, SAL_MSG_RELEASEWAITYIELD, wParam, lParam );
819 rDef = FALSE;
820 break;
821 case SAL_MSG_STARTTIMER:
822 ImplSalStartTimer( (ULONG) lParam, FALSE );
823 rDef = FALSE;
824 break;
825 case SAL_MSG_CREATEFRAME:
826 nRet = (LRESULT)ImplSalCreateFrame( GetSalData()->mpFirstInstance, (HWND)lParam, (ULONG)wParam );
827 rDef = FALSE;
828 break;
829 case SAL_MSG_RECREATEHWND:
830 nRet = (LRESULT)ImplSalReCreateHWND( (HWND)wParam, (HWND)lParam, FALSE );
831 rDef = FALSE;
832 break;
833 case SAL_MSG_RECREATECHILDHWND:
834 nRet = (LRESULT)ImplSalReCreateHWND( (HWND)wParam, (HWND)lParam, TRUE );
835 rDef = FALSE;
836 break;
837 case SAL_MSG_DESTROYFRAME:
838 delete (SalFrame*)lParam;
839 rDef = FALSE;
840 break;
841 case SAL_MSG_DESTROYHWND:
842 //We only destroy the native window here. We do NOT destroy the SalFrame contained
843 //in the structure (GetWindowPtr()).
844 if (DestroyWindow((HWND)lParam) == 0)
846 OSL_ENSURE(0, "DestroyWindow failed!");
847 //Failure: We remove the SalFrame from the window structure. So we avoid that
848 // the window structure may contain an invalid pointer, once the SalFrame is deleted.
849 SetWindowPtr((HWND)lParam, 0);
851 rDef = FALSE;
852 break;
853 case SAL_MSG_CREATEOBJECT:
854 nRet = (LRESULT)ImplSalCreateObject( GetSalData()->mpFirstInstance, (WinSalFrame*)lParam );
855 rDef = FALSE;
856 break;
857 case SAL_MSG_DESTROYOBJECT:
858 delete (SalObject*)lParam;
859 rDef = FALSE;
860 break;
861 case SAL_MSG_GETDC:
862 nRet = (LRESULT)GetDCEx( (HWND)wParam, 0, DCX_CACHE );
863 rDef = FALSE;
864 break;
865 case SAL_MSG_RELEASEDC:
866 ReleaseDC( (HWND)wParam, (HDC)lParam );
867 rDef = FALSE;
868 break;
869 case SAL_MSG_POSTTIMER:
870 SalTimerProc( 0, 0, SALTIMERPROC_RECURSIVE, lParam );
871 break;
874 return nRet;
877 LRESULT CALLBACK SalComWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
879 int bDef = TRUE;
880 LRESULT nRet = 0;
881 #ifdef __MINGW32__
882 jmp_buf jmpbuf;
883 __SEHandler han;
884 if (__builtin_setjmp(jmpbuf) == 0)
886 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
887 #else
888 __try
890 #endif
891 nRet = SalComWndProc( hWnd, nMsg, wParam, lParam, bDef );
893 #ifdef __MINGW32__
894 han.Reset();
895 #else
896 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
899 #endif
900 if ( bDef )
902 if ( !ImplHandleGlobalMsg( hWnd, nMsg, wParam, lParam, nRet ) )
903 nRet = DefWindowProcA( hWnd, nMsg, wParam, lParam );
905 return nRet;
908 LRESULT CALLBACK SalComWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
910 int bDef = TRUE;
911 LRESULT nRet = 0;
912 #ifdef __MINGW32__
913 jmp_buf jmpbuf;
914 __SEHandler han;
915 if (__builtin_setjmp(jmpbuf) == 0)
917 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
918 #else
919 __try
921 #endif
922 nRet = SalComWndProc( hWnd, nMsg, wParam, lParam, bDef );
924 #ifdef __MINGW32__
925 han.Reset();
926 #else
927 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
930 #endif
931 if ( bDef )
933 if ( !ImplHandleGlobalMsg( hWnd, nMsg, wParam, lParam, nRet ) )
934 nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam );
936 return nRet;
939 // -----------------------------------------------------------------------
941 bool WinSalInstance::AnyInput( USHORT nType )
943 MSG aMsg;
945 if ( (nType & (INPUT_ANY)) == (INPUT_ANY) )
947 // revert bugfix for #108919# which never reported timeouts when called from the timer handler
948 // which made the application completely unresponsive during background formatting
949 if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_NOREMOVE | PM_NOYIELD ) )
950 return true;
952 else
954 if ( nType & INPUT_MOUSE )
956 // Test for mouse input
957 if ( ImplPeekMessage( &aMsg, 0, WM_MOUSEFIRST, WM_MOUSELAST,
958 PM_NOREMOVE | PM_NOYIELD ) )
959 return true;
962 if ( nType & INPUT_KEYBOARD )
964 // Test for key input
965 if ( ImplPeekMessage( &aMsg, 0, WM_KEYDOWN, WM_KEYDOWN,
966 PM_NOREMOVE | PM_NOYIELD ) )
968 if ( (aMsg.wParam == VK_SHIFT) ||
969 (aMsg.wParam == VK_CONTROL) ||
970 (aMsg.wParam == VK_MENU) )
971 return false;
972 else
973 return true;
977 if ( nType & INPUT_PAINT )
979 // Test for paint input
980 if ( ImplPeekMessage( &aMsg, 0, WM_PAINT, WM_PAINT,
981 PM_NOREMOVE | PM_NOYIELD ) )
982 return true;
984 if ( ImplPeekMessage( &aMsg, 0, WM_SIZE, WM_SIZE,
985 PM_NOREMOVE | PM_NOYIELD ) )
986 return true;
988 if ( ImplPeekMessage( &aMsg, 0, SAL_MSG_POSTCALLSIZE, SAL_MSG_POSTCALLSIZE,
989 PM_NOREMOVE | PM_NOYIELD ) )
990 return true;
992 if ( ImplPeekMessage( &aMsg, 0, WM_MOVE, WM_MOVE,
993 PM_NOREMOVE | PM_NOYIELD ) )
994 return true;
996 if ( ImplPeekMessage( &aMsg, 0, SAL_MSG_POSTMOVE, SAL_MSG_POSTMOVE,
997 PM_NOREMOVE | PM_NOYIELD ) )
998 return true;
1001 if ( nType & INPUT_TIMER )
1003 // Test for timer input
1004 if ( ImplPeekMessage( &aMsg, 0, WM_TIMER, WM_TIMER,
1005 PM_NOREMOVE | PM_NOYIELD ) )
1006 return true;
1010 if ( nType & INPUT_OTHER )
1012 // Test for any input
1013 if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_NOREMOVE | PM_NOYIELD ) )
1014 return true;
1018 return FALSE;
1021 // -----------------------------------------------------------------------
1023 void SalTimer::Start( ULONG nMS )
1025 // Um auf Main-Thread umzuschalten
1026 SalData* pSalData = GetSalData();
1027 if ( pSalData->mpFirstInstance )
1029 if ( pSalData->mnAppThreadId != GetCurrentThreadId() )
1030 ImplPostMessage( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS );
1031 else
1032 ImplSendMessage( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS );
1034 else
1035 ImplSalStartTimer( nMS, FALSE );
1038 // -----------------------------------------------------------------------
1040 SalFrame* WinSalInstance::CreateChildFrame( SystemParentData* pSystemParentData, ULONG nSalFrameStyle )
1042 // Um auf Main-Thread umzuschalten
1043 return (SalFrame*)ImplSendMessage( mhComWnd, SAL_MSG_CREATEFRAME, nSalFrameStyle, (LPARAM)pSystemParentData->hWnd );
1046 // -----------------------------------------------------------------------
1048 SalFrame* WinSalInstance::CreateFrame( SalFrame* pParent, ULONG nSalFrameStyle )
1050 // Um auf Main-Thread umzuschalten
1051 HWND hWndParent;
1052 if ( pParent )
1053 hWndParent = static_cast<WinSalFrame*>(pParent)->mhWnd;
1054 else
1055 hWndParent = 0;
1056 return (SalFrame*)ImplSendMessage( mhComWnd, SAL_MSG_CREATEFRAME, nSalFrameStyle, (LPARAM)hWndParent );
1059 // -----------------------------------------------------------------------
1061 void WinSalInstance::DestroyFrame( SalFrame* pFrame )
1063 ImplSendMessage( mhComWnd, SAL_MSG_DESTROYFRAME, 0, (LPARAM)pFrame );
1066 // -----------------------------------------------------------------------
1068 SalObject* WinSalInstance::CreateObject( SalFrame* pParent,
1069 SystemWindowData* /*pWindowData*/, // SystemWindowData meaningless on Windows
1070 BOOL /*bShow*/ )
1072 // Um auf Main-Thread umzuschalten
1073 return (SalObject*)ImplSendMessage( mhComWnd, SAL_MSG_CREATEOBJECT, 0, (LPARAM)static_cast<WinSalFrame*>(pParent) );
1076 // -----------------------------------------------------------------------
1078 void WinSalInstance::DestroyObject( SalObject* pObject )
1080 ImplSendMessage( mhComWnd, SAL_MSG_DESTROYOBJECT, 0, (LPARAM)pObject );
1083 // -----------------------------------------------------------------------
1085 void* WinSalInstance::GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes )
1087 rReturnedBytes = 1;
1088 rReturnedType = AsciiCString;
1089 return const_cast<char *>("");
1092 // -----------------------------------------------------------------------
1094 SalTimer* WinSalInstance::CreateSalTimer()
1096 return new WinSalTimer();
1099 // -----------------------------------------------------------------------
1101 SalBitmap* WinSalInstance::CreateSalBitmap()
1103 return new WinSalBitmap();
1106 class WinImeStatus : public SalI18NImeStatus
1108 public:
1109 WinImeStatus() {}
1110 virtual ~WinImeStatus() {}
1112 // asks whether there is a status window available
1113 // to toggle into menubar
1114 virtual bool canToggle() { return false; }
1115 virtual void toggle() {}
1118 SalI18NImeStatus* WinSalInstance::CreateI18NImeStatus()
1120 return new WinImeStatus();
1123 // -----------------------------------------------------------------------
1125 const ::rtl::OUString& SalGetDesktopEnvironment()
1127 static ::rtl::OUString aDesktopEnvironment( RTL_CONSTASCII_USTRINGPARAM( "Windows" ) );
1128 return aDesktopEnvironment;
1131 SalSession* WinSalInstance::CreateSalSession()
1133 return NULL;
1136 #ifndef __MINGW32__
1137 // -----------------------------------------------------------------------
1138 int WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(int, LPEXCEPTION_POINTERS pExceptionInfo)
1140 // Decide if an exception is a c++ (mostly UNO) exception or a process violation.
1141 // Depending on this information we pass process violations directly to our signal handler ...
1142 // and c++ (UNO) exceptions are sended to the following code on the current stack.
1143 // Problem behind: user32.dll sometime consumes exceptions/process violations .-)
1144 // see also #112221#
1146 static DWORD EXCEPTION_MSC_CPP_EXCEPTION = 0xE06D7363;
1148 if (pExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_MSC_CPP_EXCEPTION)
1149 return EXCEPTION_CONTINUE_SEARCH;
1151 return UnhandledExceptionFilter( pExceptionInfo );
1153 #endif