Bump version to 4.1-6
[LibreOffice.git] / vcl / win / source / app / salinst.cxx
blob99356ba8889aa616f5aea02a2cb9b962027096aa
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
21 #include <string.h>
22 #include <svsys.h>
23 #include <process.h>
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>
44 #include <salsys.hxx>
46 #if defined _MSC_VER
47 #ifndef min
48 #define min(a,b) (((a) < (b)) ? (a) : (b))
49 #endif
50 #ifndef max
51 #define max(a,b) (((a) > (b)) ? (a) : (b))
52 #endif
53 #endif
55 #if defined _MSC_VER
56 #pragma warning(push, 1)
57 #pragma warning( disable: 4917 )
58 #endif
60 #include <gdiplus.h>
61 #include <gdiplusenums.h>
62 #include <gdipluscolor.h>
63 #include <shlobj.h>
65 #if defined _MSC_VER
66 #pragma warning(pop)
67 #endif
69 #ifdef __MINGW32__
70 #include <sehandler.hxx>
71 #endif
73 // =======================================================================
75 void SalAbort( const OUString& rErrorText, bool )
77 ImplFreeSalGDI();
79 if ( rErrorText.isEmpty() )
81 // make sure crash reporter is triggered
82 RaiseException( 0, EXCEPTION_NONCONTINUABLE, 0, NULL );
83 FatalAppExitW( 0, L"Application Error" );
85 else
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;
104 sal_uLong mnCount;
105 DWORD mnThreadId;
107 public:
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;
122 mnCount = 0;
123 mnThreadId = 0;
126 // -----------------------------------------------------------------------
128 void SalYieldMutex::acquire()
130 SolarMutexObject::acquire();
131 mnCount++;
132 mnThreadId = GetCurrentThreadId();
135 // -----------------------------------------------------------------------
137 void SalYieldMutex::release()
139 DWORD nThreadId = GetCurrentThreadId();
140 if ( mnThreadId != nThreadId )
141 SolarMutexObject::release();
142 else
144 SalData* pSalData = GetSalData();
145 if ( pSalData->mnAppThreadId != nThreadId )
147 if ( mnCount == 1 )
149 // If we don't call these message, the Output from the
150 // Java clients doesn't come in the right order
151 GdiFlush();
153 mpInstData->mpSalWaitMutex->acquire();
154 if ( mpInstData->mnYieldWaitCount )
155 ImplPostMessage( mpInstData->mhComWnd, SAL_MSG_RELEASEWAITYIELD, 0, 0 );
156 mnThreadId = 0;
157 mnCount--;
158 SolarMutexObject::release();
159 mpInstData->mpSalWaitMutex->release();
161 else
163 mnCount--;
164 SolarMutexObject::release();
167 else
169 if ( mnCount == 1 )
170 mnThreadId = 0;
171 mnCount--;
172 SolarMutexObject::release();
177 // -----------------------------------------------------------------------
179 bool SalYieldMutex::tryToAcquire()
181 if( SolarMutexObject::tryToAcquire() )
183 mnCount++;
184 mnThreadId = GetCurrentThreadId();
185 return true;
187 else
188 return false;
191 // -----------------------------------------------------------------------
193 sal_uLong SalYieldMutex::GetAcquireCount( sal_uLong nThreadId )
195 if ( nThreadId == mnThreadId )
196 return mnCount;
197 else
198 return 0;
201 // -----------------------------------------------------------------------
203 void ImplSalYieldMutexAcquireWithWait()
205 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
206 if ( !pInst )
207 return;
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() )
222 bAcquire = TRUE;
223 else
225 pInst->mpSalWaitMutex->acquire();
226 if ( pInst->mpSalYieldMutex->tryToAcquire() )
228 bAcquire = TRUE;
229 pInst->mpSalWaitMutex->release();
231 else
233 pInst->mnYieldWaitCount++;
234 pInst->mpSalWaitMutex->release();
235 MSG aTmpMsg;
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 );
243 while ( !bAcquire );
245 else
246 pInst->mpSalYieldMutex->acquire();
249 // -----------------------------------------------------------------------
251 sal_Bool ImplSalYieldMutexTryToAcquire()
253 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
254 if ( pInst )
255 return pInst->mpSalYieldMutex->tryToAcquire();
256 else
257 return FALSE;
260 // -----------------------------------------------------------------------
262 void ImplSalYieldMutexAcquire()
264 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
265 if ( pInst )
266 pInst->mpSalYieldMutex->acquire();
269 // -----------------------------------------------------------------------
271 void ImplSalYieldMutexRelease()
273 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
274 if ( pInst )
276 GdiFlush();
277 pInst->mpSalYieldMutex->release();
281 // -----------------------------------------------------------------------
283 sal_uLong ImplSalReleaseYieldMutex()
285 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
286 if ( !pInst )
287 return 0;
289 SalYieldMutex* pYieldMutex = pInst->mpSalYieldMutex;
290 sal_uLong nCount = pYieldMutex->GetAcquireCount( GetCurrentThreadId() );
291 sal_uLong n = nCount;
292 while ( n )
294 pYieldMutex->release();
295 n--;
298 return nCount;
301 // -----------------------------------------------------------------------
303 void ImplSalAcquireYieldMutex( sal_uLong nCount )
305 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
306 if ( !pInst )
307 return;
309 SalYieldMutex* pYieldMutex = pInst->mpSalYieldMutex;
310 while ( nCount )
312 pYieldMutex->acquire();
313 nCount--;
317 // -----------------------------------------------------------------------
319 bool WinSalInstance::CheckYieldMutex()
321 SalData* pSalData = GetSalData();
322 if ( pSalData->mpFirstInstance )
324 SalYieldMutex* pYieldMutex = pSalData->mpFirstInstance->mpSalYieldMutex;
325 return (pYieldMutex->mnThreadId == (GetCurrentThreadId()));
327 return true;
330 // =======================================================================
332 void SalData::initKeyCodeMap()
334 UINT nKey = 0xffffffff;
335 #define initKey( a, b )\
336 nKey = LOWORD( VkKeyScan( a ) );\
337 if( nKey < 0xffff )\
338 maVKMap[ nKey ] = b;
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 // =======================================================================
357 // -------
358 // SalData
359 // -------
361 SalData::SalData()
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)
375 mnNextTimerTime = 0;
376 mnLastEventTime = 0;
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
390 int i;
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
412 mpTempFontItem = 0;
413 mbThemeChanged = FALSE; // true if visual theme was changed: throw away theme handles
414 mbThemeMenuSupport = FALSE;
416 // init with NULL
417 gdiplusToken = 0;
418 maDwmLib = 0;
419 mpDwmIsCompositionEnabled = 0;
421 initKeyCodeMap();
423 SetSalData( this );
424 initNWF();
427 SalData::~SalData()
429 deInitNWF();
430 SetSalData( NULL );
433 void InitSalData()
435 SalData* pSalData = new SalData;
436 CoInitialize(0);
438 // init GDIPlus
439 static Gdiplus::GdiplusStartupInput gdiplusStartupInput;
440 Gdiplus::GdiplusStartup(&pSalData->gdiplusToken, &gdiplusStartupInput, NULL);
444 void DeInitSalData()
446 CoUninitialize();
447 SalData* pSalData = GetSalData();
449 // deinit GDIPlus
450 if(pSalData)
452 Gdiplus::GdiplusShutdown(pSalData->gdiplusToken);
455 delete pSalData;
458 // -----------------------------------------------------------------------
460 void InitSalMain()
462 // remember data, copied from WinMain
463 SalData* pData = GetSalData();
464 if ( pData ) // Im AppServer NULL
466 STARTUPINFO aSI;
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 ) )
488 // Windows XP ?
489 if ( aSalShlData.maVersionInfo.dwMajorVersion > 5 ||
490 ( aSalShlData.maVersionInfo.dwMajorVersion == 5 && aSalShlData.maVersionInfo.dwMinorVersion >= 1 ) )
491 aSalShlData.mbWXP = 1;
492 // Windows 7 ?
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 ) )
516 return NULL;
518 aWndClassEx.hIcon = 0;
519 aWndClassEx.hIconSm = 0;
520 aWndClassEx.style |= CS_SAVEBITS;
521 aWndClassEx.lpszClassName = SAL_SUBFRAME_CLASSNAMEW;
522 if ( !RegisterClassExW( &aWndClassEx ) )
523 return NULL;
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 ) )
530 return NULL;
532 aWndClassEx.style = 0;
533 aWndClassEx.lpfnWndProc = SalComWndProcW;
534 aWndClassEx.cbWndExtra = 0;
535 aWndClassEx.lpszClassName = SAL_COM_CLASSNAMEW;
536 if ( !RegisterClassExW( &aWndClassEx ) )
537 return NULL;
540 HWND hComWnd = CreateWindowExW( WS_EX_TOOLWINDOW, SAL_COM_CLASSNAMEW,
541 L"", WS_POPUP, 0, 0, 0, 0, 0, 0,
542 pSalData->mhInst, NULL );
543 if ( !hComWnd )
544 return 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
554 ImplInitSalGDI();
556 return pInst;
559 // -----------------------------------------------------------------------
561 void DestroySalInstance( SalInstance* pInst )
563 SalData* pSalData = GetSalData();
565 // (only one instance in this version !!!)
567 ImplFreeSalGDI();
569 // reset instance
570 if ( pSalData->mpFirstInstance == pInst )
571 pSalData->mpFirstInstance = NULL;
573 delete pInst;
576 // -----------------------------------------------------------------------
578 WinSalInstance::WinSalInstance()
580 mhComWnd = 0;
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 ) )
628 return;
630 LRESULT lResult = ImplDispatchMessage( pMsg );
631 if ( pSalData->mpFirstObject )
632 ImplSalPostDispatchMsg( pMsg, lResult );
635 // -----------------------------------------------------------------------
637 void ImplSalYield( sal_Bool bWait, sal_Bool bHandleAllCurrentEvents )
639 MSG aMsg;
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;
652 else
653 bOneEvent = false;
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;
675 while ( n )
677 pYieldMutex->release();
678 n--;
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 )
693 Sleep(1);
694 else
695 ImplSendMessage( mhComWnd, SAL_MSG_THREADYIELD, (WPARAM)bWait, (LPARAM)bHandleAllCurrentEvents );
697 n = nCount;
698 while ( n )
700 pYieldMutex->acquire();
701 n--;
704 else
706 ImplSalYield( bWait, bHandleAllCurrentEvents );
708 n = nCount;
709 while ( n )
711 ImplSalYieldMutexAcquireWithWait();
712 n--;
717 // -----------------------------------------------------------------------
719 LRESULT CALLBACK SalComWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef )
721 LRESULT nRet = 0;
724 switch ( nMsg )
726 case SAL_MSG_PRINTABORTJOB:
727 ImplSalPrinterAbortJobAsync( (HDC)wParam );
728 rDef = FALSE;
729 break;
730 case SAL_MSG_THREADYIELD:
731 ImplSalYield( (sal_Bool)wParam, (sal_Bool)lParam );
732 rDef = FALSE;
733 break;
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 );
743 rDef = FALSE;
744 break;
745 case SAL_MSG_STARTTIMER:
746 ImplSalStartTimer( (sal_uLong) lParam, FALSE );
747 rDef = FALSE;
748 break;
749 case SAL_MSG_CREATEFRAME:
750 nRet = (LRESULT)ImplSalCreateFrame( GetSalData()->mpFirstInstance, (HWND)lParam, (sal_uLong)wParam );
751 rDef = FALSE;
752 break;
753 case SAL_MSG_RECREATEHWND:
754 nRet = (LRESULT)ImplSalReCreateHWND( (HWND)wParam, (HWND)lParam, FALSE );
755 rDef = FALSE;
756 break;
757 case SAL_MSG_RECREATECHILDHWND:
758 nRet = (LRESULT)ImplSalReCreateHWND( (HWND)wParam, (HWND)lParam, TRUE );
759 rDef = FALSE;
760 break;
761 case SAL_MSG_DESTROYFRAME:
762 delete (SalFrame*)lParam;
763 rDef = FALSE;
764 break;
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);
775 rDef = FALSE;
776 break;
777 case SAL_MSG_CREATEOBJECT:
778 nRet = (LRESULT)ImplSalCreateObject( GetSalData()->mpFirstInstance, (WinSalFrame*)lParam );
779 rDef = FALSE;
780 break;
781 case SAL_MSG_DESTROYOBJECT:
782 delete (SalObject*)lParam;
783 rDef = FALSE;
784 break;
785 case SAL_MSG_GETDC:
786 nRet = (LRESULT)GetDCEx( (HWND)wParam, 0, DCX_CACHE );
787 rDef = FALSE;
788 break;
789 case SAL_MSG_RELEASEDC:
790 ReleaseDC( (HWND)wParam, (HDC)lParam );
791 rDef = FALSE;
792 break;
793 case SAL_MSG_POSTTIMER:
794 SalTimerProc( 0, 0, SALTIMERPROC_RECURSIVE, lParam );
795 break;
798 return nRet;
801 LRESULT CALLBACK SalComWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
803 int bDef = TRUE;
804 LRESULT nRet = 0;
805 #ifdef __MINGW32__
806 jmp_buf jmpbuf;
807 __SEHandler han;
808 if (__builtin_setjmp(jmpbuf) == 0)
810 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
811 #else
812 __try
814 #endif
815 nRet = SalComWndProc( hWnd, nMsg, wParam, lParam, bDef );
817 #ifdef __MINGW32__
818 han.Reset();
819 #else
820 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
823 #endif
824 if ( bDef )
826 if ( !ImplHandleGlobalMsg( hWnd, nMsg, wParam, lParam, nRet ) )
827 nRet = DefWindowProcA( hWnd, nMsg, wParam, lParam );
829 return nRet;
832 LRESULT CALLBACK SalComWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
834 int bDef = TRUE;
835 LRESULT nRet = 0;
836 #ifdef __MINGW32__
837 jmp_buf jmpbuf;
838 __SEHandler han;
839 if (__builtin_setjmp(jmpbuf) == 0)
841 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
842 #else
843 __try
845 #endif
846 nRet = SalComWndProc( hWnd, nMsg, wParam, lParam, bDef );
848 #ifdef __MINGW32__
849 han.Reset();
850 #else
851 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
854 #endif
855 if ( bDef )
857 if ( !ImplHandleGlobalMsg( hWnd, nMsg, wParam, lParam, nRet ) )
858 nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam );
860 return nRet;
863 // -----------------------------------------------------------------------
865 bool WinSalInstance::AnyInput( sal_uInt16 nType )
867 MSG aMsg;
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 ) )
874 return true;
876 else
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 ) )
883 return true;
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) )
895 return false;
896 else
897 return true;
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 ) )
906 return true;
908 if ( ImplPeekMessage( &aMsg, 0, WM_SIZE, WM_SIZE,
909 PM_NOREMOVE | PM_NOYIELD ) )
910 return true;
912 if ( ImplPeekMessage( &aMsg, 0, SAL_MSG_POSTCALLSIZE, SAL_MSG_POSTCALLSIZE,
913 PM_NOREMOVE | PM_NOYIELD ) )
914 return true;
916 if ( ImplPeekMessage( &aMsg, 0, WM_MOVE, WM_MOVE,
917 PM_NOREMOVE | PM_NOYIELD ) )
918 return true;
920 if ( ImplPeekMessage( &aMsg, 0, SAL_MSG_POSTMOVE, SAL_MSG_POSTMOVE,
921 PM_NOREMOVE | PM_NOYIELD ) )
922 return true;
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 ) )
930 return true;
934 if ( nType & VCL_INPUT_OTHER )
936 // Test for any input
937 if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_NOREMOVE | PM_NOYIELD ) )
938 return true;
942 return FALSE;
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 );
955 else
956 ImplSendMessage( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS );
958 else
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
975 HWND hWndParent;
976 if ( pParent )
977 hWndParent = static_cast<WinSalFrame*>(pParent)->mhWnd;
978 else
979 hWndParent = 0;
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
994 sal_Bool /*bShow*/ )
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 )
1011 rReturnedBytes = 1;
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.
1022 @param aFileUrl
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 );
1083 return;
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
1109 public:
1110 WinImeStatus() {}
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()
1134 return NULL;
1137 #ifndef __MINGW32__
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 );
1154 #endif
1156 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */