1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26
27 #include <string.h>
28 #include <tools/svwin.h>
29 #ifdef WNT
30 #include <process.h>
31 #endif
32 #ifdef __MINGW32__
33 #include <excpt.h>
34 #endif
35
36 #include <osl/file.hxx>
37
38 #include <vos/mutex.hxx>
39
40 #include <tools/solarmutex.hxx>
41 #include <tools/debug.hxx>
42
43 #include <vcl/timer.hxx>
44 #include <vcl/apptypes.hxx>
45
46 #include <win/wincomp.hxx>
47 #include <win/salids.hrc>
48 #include <win/saldata.hxx>
49 #include <win/salinst.h>
50 #include <win/salframe.h>
51 #include <win/salobj.h>
52 #include <win/saltimer.h>
53 #include <win/salbmp.h>
54
55 #include <salimestatus.hxx>
56 #include <salsys.hxx>
57
58 #ifndef min
59 #define min(a,b) (((a) < (b)) ? (a) : (b))
60 #endif
61 #ifndef max
62 #define max(a,b) (((a) > (b)) ? (a) : (b))
63 #endif
64
65 #if defined _MSC_VER
66 #pragma warning(push, 1)
67 #pragma warning( disable: 4917 )
68 #endif
69
70 #include <GdiPlus.h>
71 #include <GdiPlusEnums.h>
72 #include <GdiPlusColor.h>
73 #include <Shlobj.h>
74
75 #if defined _MSC_VER
76 #pragma warning(pop)
77 #endif
78
79 // =======================================================================
80
SalAbort(const XubString & rErrorText)81 void SalAbort( const XubString& rErrorText )
82 {
83 ImplFreeSalGDI();
84
85 if ( !rErrorText.Len() )
86 {
87 // #112255# make sure crash reporter is triggered
88 RaiseException( 0, EXCEPTION_NONCONTINUABLE, 0, NULL );
89 FatalAppExit( 0, "Application Error" );
90 }
91 else
92 {
93 // #112255# make sure crash reporter is triggered
94 RaiseException( 0, EXCEPTION_NONCONTINUABLE, 0, NULL );
95 ByteString aErrorText( ImplSalGetWinAnsiString( rErrorText ) );
96 FatalAppExit( 0, aErrorText.GetBuffer() );
97 }
98 }
99
100 // =======================================================================
101
102 LRESULT CALLBACK SalComWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam );
103 LRESULT CALLBACK SalComWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam );
104
105 // =======================================================================
106
107 class SalYieldMutex : public vos::OMutex
108 {
109 public: // for ImplSalYield()
110 WinSalInstance* mpInstData;
111 sal_uLong mnCount;
112 DWORD mnThreadId;
113
114 public:
115 SalYieldMutex( WinSalInstance* pInstData );
116
117 virtual void SAL_CALL acquire();
118 virtual void SAL_CALL release();
119 virtual sal_Bool SAL_CALL tryToAcquire();
120
121 sal_uLong GetAcquireCount( sal_uLong nThreadId );
122 };
123
124 // -----------------------------------------------------------------------
125
SalYieldMutex(WinSalInstance * pInstData)126 SalYieldMutex::SalYieldMutex( WinSalInstance* pInstData )
127 {
128 mpInstData = pInstData;
129 mnCount = 0;
130 mnThreadId = 0;
131 }
132
133 // -----------------------------------------------------------------------
134
acquire()135 void SAL_CALL SalYieldMutex::acquire()
136 {
137 OMutex::acquire();
138 mnCount++;
139 mnThreadId = GetCurrentThreadId();
140 }
141
142 // -----------------------------------------------------------------------
143
release()144 void SAL_CALL SalYieldMutex::release()
145 {
146 DWORD nThreadId = GetCurrentThreadId();
147 if ( mnThreadId != nThreadId )
148 OMutex::release();
149 else
150 {
151 SalData* pSalData = GetSalData();
152 if ( pSalData->mnAppThreadId != nThreadId )
153 {
154 if ( mnCount == 1 )
155 {
156 // If we don't call these message, the Output from the
157 // Java clients doesn't come in the right order
158 GdiFlush();
159
160 mpInstData->mpSalWaitMutex->acquire();
161 if ( mpInstData->mnYieldWaitCount )
162 ImplPostMessage( mpInstData->mhComWnd, SAL_MSG_RELEASEWAITYIELD, 0, 0 );
163 mnThreadId = 0;
164 mnCount--;
165 OMutex::release();
166 mpInstData->mpSalWaitMutex->release();
167 }
168 else
169 {
170 mnCount--;
171 OMutex::release();
172 }
173 }
174 else
175 {
176 if ( mnCount == 1 )
177 mnThreadId = 0;
178 mnCount--;
179 OMutex::release();
180 }
181 }
182 }
183
184 // -----------------------------------------------------------------------
185
tryToAcquire()186 sal_Bool SAL_CALL SalYieldMutex::tryToAcquire()
187 {
188 if( OMutex::tryToAcquire() )
189 {
190 mnCount++;
191 mnThreadId = GetCurrentThreadId();
192 return sal_True;
193 }
194 else
195 return sal_False;
196 }
197
198 // -----------------------------------------------------------------------
199
GetAcquireCount(sal_uLong nThreadId)200 sal_uLong SalYieldMutex::GetAcquireCount( sal_uLong nThreadId )
201 {
202 if ( nThreadId == mnThreadId )
203 return mnCount;
204 else
205 return 0;
206 }
207
208 // -----------------------------------------------------------------------
209
ImplSalYieldMutexAcquireWithWait()210 void ImplSalYieldMutexAcquireWithWait()
211 {
212 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
213 if ( !pInst )
214 return;
215
216 // If we are the main thread, then we must wait with wait, because
217 // in if we don't reschedule, then we create deadlocks if a Windows
218 // Function is called from another thread. If we arn't the main thread,
219 // than we call qcquire directly.
220 DWORD nThreadId = GetCurrentThreadId();
221 SalData* pSalData = GetSalData();
222 if ( pSalData->mnAppThreadId == nThreadId )
223 {
224 // Wenn wir den Mutex nicht bekommen, muessen wir solange
225 // warten, bis wir Ihn bekommen
226 sal_Bool bAcquire = FALSE;
227 do
228 {
229 if ( pInst->mpSalYieldMutex->tryToAcquire() )
230 bAcquire = TRUE;
231 else
232 {
233 pInst->mpSalWaitMutex->acquire();
234 if ( pInst->mpSalYieldMutex->tryToAcquire() )
235 {
236 bAcquire = TRUE;
237 pInst->mpSalWaitMutex->release();
238 }
239 else
240 {
241 pInst->mnYieldWaitCount++;
242 pInst->mpSalWaitMutex->release();
243 MSG aTmpMsg;
244 ImplGetMessage( &aTmpMsg, pInst->mhComWnd, SAL_MSG_RELEASEWAITYIELD, SAL_MSG_RELEASEWAITYIELD );
245 pInst->mnYieldWaitCount--;
246 if ( pInst->mnYieldWaitCount )
247 ImplPostMessage( pInst->mhComWnd, SAL_MSG_RELEASEWAITYIELD, 0, 0 );
248 }
249 }
250 }
251 while ( !bAcquire );
252 }
253 else
254 pInst->mpSalYieldMutex->acquire();
255 }
256
257 // -----------------------------------------------------------------------
258
ImplSalYieldMutexTryToAcquire()259 sal_Bool ImplSalYieldMutexTryToAcquire()
260 {
261 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
262 if ( pInst )
263 return pInst->mpSalYieldMutex->tryToAcquire();
264 else
265 return FALSE;
266 }
267
268 // -----------------------------------------------------------------------
269
ImplSalYieldMutexAcquire()270 void ImplSalYieldMutexAcquire()
271 {
272 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
273 if ( pInst )
274 pInst->mpSalYieldMutex->acquire();
275 }
276
277 // -----------------------------------------------------------------------
278
ImplSalYieldMutexRelease()279 void ImplSalYieldMutexRelease()
280 {
281 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
282 if ( pInst )
283 {
284 GdiFlush();
285 pInst->mpSalYieldMutex->release();
286 }
287 }
288
289 // -----------------------------------------------------------------------
290
ImplSalReleaseYieldMutex()291 sal_uLong ImplSalReleaseYieldMutex()
292 {
293 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
294 if ( !pInst )
295 return 0;
296
297 SalYieldMutex* pYieldMutex = pInst->mpSalYieldMutex;
298 sal_uLong nCount = pYieldMutex->GetAcquireCount( GetCurrentThreadId() );
299 sal_uLong n = nCount;
300 while ( n )
301 {
302 pYieldMutex->release();
303 n--;
304 }
305
306 return nCount;
307 }
308
309 // -----------------------------------------------------------------------
310
ImplSalAcquireYieldMutex(sal_uLong nCount)311 void ImplSalAcquireYieldMutex( sal_uLong nCount )
312 {
313 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
314 if ( !pInst )
315 return;
316
317 SalYieldMutex* pYieldMutex = pInst->mpSalYieldMutex;
318 while ( nCount )
319 {
320 pYieldMutex->acquire();
321 nCount--;
322 }
323 }
324
325 // -----------------------------------------------------------------------
326
CheckYieldMutex()327 bool WinSalInstance::CheckYieldMutex()
328 {
329 bool bRet = true;
330 SalData* pSalData = GetSalData();
331 DWORD nCurThreadId = GetCurrentThreadId();
332 if ( pSalData->mnAppThreadId != nCurThreadId )
333 {
334 if ( pSalData->mpFirstInstance )
335 {
336 SalYieldMutex* pYieldMutex = pSalData->mpFirstInstance->mpSalYieldMutex;
337 if ( pYieldMutex->mnThreadId != nCurThreadId )
338 {
339 bRet = false;
340 }
341 }
342 }
343 else
344 {
345 if ( pSalData->mpFirstInstance )
346 {
347 SalYieldMutex* pYieldMutex = pSalData->mpFirstInstance->mpSalYieldMutex;
348 if ( pYieldMutex->mnThreadId != nCurThreadId )
349 {
350 bRet = false;
351 }
352 }
353 }
354 return bRet;
355 }
356
357 // =======================================================================
358
initKeyCodeMap()359 void SalData::initKeyCodeMap()
360 {
361 UINT nKey = 0xffffffff;
362 #define initKey( a, b )\
363 nKey = LOWORD( VkKeyScan( a ) );\
364 if( nKey < 0xffff )\
365 maVKMap[ nKey ] = b;
366
367 initKey( '+', KEY_ADD );
368 initKey( '-', KEY_SUBTRACT );
369 initKey( '*', KEY_MULTIPLY );
370 initKey( '/', KEY_DIVIDE );
371 initKey( '.', KEY_POINT );
372 initKey( ',', KEY_COMMA );
373 initKey( '<', KEY_LESS );
374 initKey( '>', KEY_GREATER );
375 initKey( '=', KEY_EQUAL );
376 initKey( '~', KEY_TILDE );
377 initKey( '`', KEY_QUOTELEFT );
378 }
379
380 // =======================================================================
381 // -------
382 // SalData
383 // -------
384
SalData()385 SalData::SalData()
386 {
387 mhInst = 0; // default instance handle
388 mhPrevInst = 0; // previous instance handle
389 mnCmdShow = 0; // default frame show style
390 mhDitherPal = 0; // dither palette
391 mhDitherDIB = 0; // dither memory handle
392 mpDitherDIB = 0; // dither memory
393 mpDitherDIBData = 0; // beginning of DIB data
394 mpDitherDiff = 0; // Dither mapping table
395 mpDitherLow = 0; // Dither mapping table
396 mpDitherHigh = 0; // Dither mapping table
397 mnTimerMS = 0; // Current Time (in MS) of the Timer
398 mnTimerOrgMS = 0; // Current Original Time (in MS)
399 mnNextTimerTime = 0;
400 mnLastEventTime = 0;
401 mnTimerId = 0; // windows timer id
402 mbInTimerProc = FALSE; // timer event is currently being dispatched
403 mhSalObjMsgHook = 0; // hook to get interesting msg for SalObject
404 mhWantLeaveMsg = 0; // window handle, that want a MOUSELEAVE message
405 mpMouseLeaveTimer = 0; // Timer for MouseLeave Test
406 mpFirstInstance = 0; // pointer of first instance
407 mpFirstFrame = 0; // pointer of first frame
408 mpFirstObject = 0; // pointer of first object window
409 mpFirstVD = 0; // first VirDev
410 mpFirstPrinter = 0; // first printing printer
411 mpHDCCache = 0; // Cache for three DC's
412 mh50Bmp = 0; // 50% Bitmap
413 mh50Brush = 0; // 50% Brush
414 int i;
415 for(i=0; i<MAX_STOCKPEN; i++)
416 {
417 maStockPenColorAry[i] = 0;
418 mhStockPenAry[i] = 0;
419 }
420 for(i=0; i<MAX_STOCKBRUSH; i++)
421 {
422 maStockBrushColorAry[i] = 0;
423 mhStockBrushAry[i] = 0;
424 }
425 mnStockPenCount = 0; // count of static pens
426 mnStockBrushCount = 0; // count of static brushes
427 mnSalObjWantKeyEvt = 0; // KeyEvent, welcher vom SalObj-Hook verarbeitet werden soll
428 mnCacheDCInUse = 0; // count of CacheDC in use
429 mbObjClassInit = FALSE; // is SALOBJECTCLASS initialised
430 mbInPalChange = FALSE; // is in WM_QUERYNEWPALETTE
431 mnAppThreadId = 0; // Id from Applikation-Thread
432 mbScrSvrEnabled = FALSE; // ScreenSaver enabled
433 mnSageStatus = 0; // status of Sage-DLL (DISABLE_AGENT == nicht vorhanden)
434 mpSageEnableProc = 0; // funktion to deactivate the system agent
435 mpFirstIcon = 0; // icon cache, points to first icon, NULL if none
436 mpTempFontItem = 0;
437 mbThemeChanged = FALSE; // true if visual theme was changed: throw away theme handles
438 mbThemeMenuSupport = FALSE;
439
440 // init with NULL
441 gdiplusToken = 0;
442 maDwmLib = 0;
443 mpDwmIsCompositionEnabled = 0;
444
445 initKeyCodeMap();
446
447 SetSalData( this );
448 initNWF();
449 }
450
~SalData()451 SalData::~SalData()
452 {
453 deInitNWF();
454 SetSalData( NULL );
455 }
456
InitSalData()457 void InitSalData()
458 {
459 SalData* pSalData = new SalData;
460 CoInitialize(0);
461
462 // init GDIPlus
463 static Gdiplus::GdiplusStartupInput gdiplusStartupInput;
464 Gdiplus::GdiplusStartup(&pSalData->gdiplusToken, &gdiplusStartupInput, NULL);
465 }
466
467
DeInitSalData()468 void DeInitSalData()
469 {
470 CoUninitialize();
471 SalData* pSalData = GetSalData();
472
473 // deinit GDIPlus
474 if(pSalData)
475 {
476 Gdiplus::GdiplusShutdown(pSalData->gdiplusToken);
477 }
478
479 delete pSalData;
480 }
481
482 // -----------------------------------------------------------------------
483
InitSalMain()484 void InitSalMain()
485 {
486 // remember data, copied from WinMain
487 SalData* pData = GetAppSalData();
488 if ( pData ) // Im AppServer NULL
489 {
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;
496 }
497 }
498
DeInitSalMain()499 void DeInitSalMain()
500 {
501 }
502
503 // -----------------------------------------------------------------------
504
CreateSalInstance()505 SalInstance* CreateSalInstance()
506 {
507 SalData* pSalData = GetSalData();
508
509 // determine the windows version
510 aSalShlData.mbWXP = 0;
511 aSalShlData.mbWPrinter = 0;
512 WORD nVer = (WORD)GetVersion();
513 aSalShlData.mnVersion = (((WORD)LOBYTE(nVer)) * 100) + HIBYTE(nVer);
514 if ( aSalShlData.mnVersion >= 400 )
515 aSalShlData.mbW40 = 1;
516 rtl_zeroMemory( &aSalShlData.maVersionInfo, sizeof(aSalShlData.maVersionInfo) );
517 aSalShlData.maVersionInfo.dwOSVersionInfoSize = sizeof( aSalShlData.maVersionInfo );
518 if ( GetVersionEx( &aSalShlData.maVersionInfo ) )
519 {
520 if ( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
521 {
522 // Windows XP ?
523 if ( aSalShlData.maVersionInfo.dwMajorVersion > 5 ||
524 ( aSalShlData.maVersionInfo.dwMajorVersion == 5 && aSalShlData.maVersionInfo.dwMinorVersion >= 1 ) )
525 aSalShlData.mbWXP = 1;
526 if( aSalShlData.maVersionInfo.dwMajorVersion >= 5 )
527 aSalShlData.mbWPrinter = 1;
528 }
529 }
530
531 pSalData->mnAppThreadId = GetCurrentThreadId();
532
533 // register frame class
534 if ( !pSalData->mhPrevInst )
535 {
536 WNDCLASSEXW aWndClassEx;
537 aWndClassEx.cbSize = sizeof( aWndClassEx );
538 aWndClassEx.style = CS_OWNDC;
539 aWndClassEx.lpfnWndProc = SalFrameWndProcW;
540 aWndClassEx.cbClsExtra = 0;
541 aWndClassEx.cbWndExtra = SAL_FRAME_WNDEXTRA;
542 aWndClassEx.hInstance = pSalData->mhInst;
543 aWndClassEx.hCursor = 0;
544 aWndClassEx.hbrBackground = 0;
545 aWndClassEx.lpszMenuName = 0;
546 aWndClassEx.lpszClassName = SAL_FRAME_CLASSNAMEW;
547 ImplLoadSalIcon( SAL_RESID_ICON_DEFAULT, aWndClassEx.hIcon, aWndClassEx.hIconSm );
548 if ( !RegisterClassExW( &aWndClassEx ) )
549 return NULL;
550
551 aWndClassEx.hIcon = 0;
552 aWndClassEx.hIconSm = 0;
553 aWndClassEx.style |= CS_SAVEBITS;
554 aWndClassEx.lpszClassName = SAL_SUBFRAME_CLASSNAMEW;
555 if ( !RegisterClassExW( &aWndClassEx ) )
556 return NULL;
557
558 // shadow effect for popups on XP
559 if( aSalShlData.mbWXP )
560 aWndClassEx.style |= CS_DROPSHADOW;
561 aWndClassEx.lpszClassName = SAL_TMPSUBFRAME_CLASSNAMEW;
562 if ( !RegisterClassExW( &aWndClassEx ) )
563 return NULL;
564
565 aWndClassEx.style = 0;
566 aWndClassEx.lpfnWndProc = SalComWndProcW;
567 aWndClassEx.cbWndExtra = 0;
568 aWndClassEx.lpszClassName = SAL_COM_CLASSNAMEW;
569 if ( !RegisterClassExW( &aWndClassEx ) )
570 return NULL;
571 }
572
573 HWND hComWnd = CreateWindowExW( WS_EX_TOOLWINDOW, SAL_COM_CLASSNAMEW,
574 L"", WS_POPUP, 0, 0, 0, 0, 0, 0,
575 pSalData->mhInst, NULL );
576 if ( !hComWnd )
577 return NULL;
578
579 WinSalInstance* pInst = new WinSalInstance;
580
581 // init instance (only one instance in this version !!!)
582 pSalData->mpFirstInstance = pInst;
583 pInst->mhInst = pSalData->mhInst;
584 pInst->mhComWnd = hComWnd;
585
586 // init static GDI Data
587 ImplInitSalGDI();
588
589 return pInst;
590 }
591
592 // -----------------------------------------------------------------------
593
DestroySalInstance(SalInstance * pInst)594 void DestroySalInstance( SalInstance* pInst )
595 {
596 SalData* pSalData = GetSalData();
597
598 // (only one instance in this version !!!)
599
600 ImplFreeSalGDI();
601
602 // reset instance
603 if ( pSalData->mpFirstInstance == pInst )
604 pSalData->mpFirstInstance = NULL;
605
606 delete pInst;
607 }
608
609 // -----------------------------------------------------------------------
610
WinSalInstance()611 WinSalInstance::WinSalInstance()
612 {
613 mhComWnd = 0;
614 mpSalYieldMutex = new SalYieldMutex( this );
615 mpSalWaitMutex = new vos::OMutex;
616 mnYieldWaitCount = 0;
617 mpSalYieldMutex->acquire();
618 ::tools::SolarMutex::SetSolarMutex( mpSalYieldMutex );
619 }
620
621 // -----------------------------------------------------------------------
622
~WinSalInstance()623 WinSalInstance::~WinSalInstance()
624 {
625 ::tools::SolarMutex::SetSolarMutex( 0 );
626 mpSalYieldMutex->release();
627 delete mpSalYieldMutex;
628 delete mpSalWaitMutex;
629 DestroyWindow( mhComWnd );
630 }
631
632 // -----------------------------------------------------------------------
633
GetYieldMutex()634 vos::IMutex* WinSalInstance::GetYieldMutex()
635 {
636 return mpSalYieldMutex;
637 }
638
639 // -----------------------------------------------------------------------
640
ReleaseYieldMutex()641 sal_uLong WinSalInstance::ReleaseYieldMutex()
642 {
643 return ImplSalReleaseYieldMutex();
644 }
645
646 // -----------------------------------------------------------------------
647
AcquireYieldMutex(sal_uLong nCount)648 void WinSalInstance::AcquireYieldMutex( sal_uLong nCount )
649 {
650 ImplSalAcquireYieldMutex( nCount );
651 }
652
653 // -----------------------------------------------------------------------
654
ImplSalDispatchMessage(MSG * pMsg)655 static void ImplSalDispatchMessage( MSG* pMsg )
656 {
657 SalData* pSalData = GetSalData();
658 if ( pSalData->mpFirstObject )
659 {
660 if ( ImplSalPreDispatchMsg( pMsg ) )
661 return;
662 }
663 LRESULT lResult = ImplDispatchMessage( pMsg );
664 if ( pSalData->mpFirstObject )
665 ImplSalPostDispatchMsg( pMsg, lResult );
666 }
667
668 // -----------------------------------------------------------------------
669
ImplSalYield(sal_Bool bWait,sal_Bool bHandleAllCurrentEvents)670 void ImplSalYield( sal_Bool bWait, sal_Bool bHandleAllCurrentEvents )
671 {
672 MSG aMsg;
673 bool bWasMsg = false, bOneEvent = false;
674
675 int nMaxEvents = bHandleAllCurrentEvents ? 100 : 1;
676 do
677 {
678 if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) )
679 {
680 if ( !ImplInterceptChildWindowKeyDown( aMsg ) )
681 {
682 TranslateMessage( &aMsg );
683 ImplSalDispatchMessage( &aMsg );
684 }
685
686 bOneEvent = bWasMsg = true;
687 }
688 else
689 bOneEvent = false;
690 } while( --nMaxEvents && bOneEvent );
691
692 if ( bWait && ! bWasMsg )
693 {
694 if ( ImplGetMessage( &aMsg, 0, 0, 0 ) )
695 {
696 if ( !ImplInterceptChildWindowKeyDown( aMsg ) )
697 {
698 TranslateMessage( &aMsg );
699 ImplSalDispatchMessage( &aMsg );
700 }
701 }
702 }
703 }
704
705 // -----------------------------------------------------------------------
706
Yield(bool bWait,bool bHandleAllCurrentEvents)707 void WinSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents )
708 {
709 SalYieldMutex* pYieldMutex = mpSalYieldMutex;
710 SalData* pSalData = GetSalData();
711 DWORD nCurThreadId = GetCurrentThreadId();
712 sal_uLong nCount = pYieldMutex->GetAcquireCount( nCurThreadId );
713 sal_uLong n = nCount;
714 while ( n )
715 {
716 pYieldMutex->release();
717 n--;
718 }
719 if ( pSalData->mnAppThreadId != nCurThreadId )
720 {
721 // #97739# A SendMessage call blocks until the called thread (here: the main thread)
722 // returns. During a yield however, messages are processed in the main thread that might
723 // result in a new message loop due to opening a dialog. Thus, SendMessage would not
724 // return which will block this thread!
725 // Solution: just give up the time slice and hope that messages are processed
726 // by the main thread anyway (where all windows are created)
727 // If the mainthread is not currently handling messages, then our SendMessage would
728 // also do nothing, so this seems to be reasonable.
729
730 // #i18883# only sleep if potential deadlock scenario, ie, when a dialog is open
731 if( ImplGetSVData()->maAppData.mnModalMode )
732 Sleep(1);
733 else
734 ImplSendMessage( mhComWnd, SAL_MSG_THREADYIELD, (WPARAM)bWait, (LPARAM)bHandleAllCurrentEvents );
735
736 n = nCount;
737 while ( n )
738 {
739 pYieldMutex->acquire();
740 n--;
741 }
742 }
743 else
744 {
745 ImplSalYield( bWait, bHandleAllCurrentEvents );
746
747 n = nCount;
748 while ( n )
749 {
750 ImplSalYieldMutexAcquireWithWait();
751 n--;
752 }
753 }
754 }
755
756 // -----------------------------------------------------------------------
757
SalComWndProc(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam,int & rDef)758 LRESULT CALLBACK SalComWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef )
759 {
760 LRESULT nRet = 0;
761
762
763 switch ( nMsg )
764 {
765 case SAL_MSG_PRINTABORTJOB:
766 ImplSalPrinterAbortJobAsync( (HDC)wParam );
767 rDef = FALSE;
768 break;
769 case SAL_MSG_THREADYIELD:
770 ImplSalYield( (sal_Bool)wParam, (sal_Bool)lParam );
771 rDef = FALSE;
772 break;
773 // If we get this message, because another GetMessage() call
774 // has recieved this message, we must post this message to
775 // us again, because in the other case we wait forever.
776 case SAL_MSG_RELEASEWAITYIELD:
777 {
778 WinSalInstance* pInst = GetSalData()->mpFirstInstance;
779 if ( pInst && pInst->mnYieldWaitCount )
780 ImplPostMessage( hWnd, SAL_MSG_RELEASEWAITYIELD, wParam, lParam );
781 }
782 rDef = FALSE;
783 break;
784 case SAL_MSG_STARTTIMER:
785 ImplSalStartTimer( (sal_uLong) lParam, FALSE );
786 rDef = FALSE;
787 break;
788 case SAL_MSG_CREATEFRAME:
789 nRet = (LRESULT)ImplSalCreateFrame( GetSalData()->mpFirstInstance, (HWND)lParam, (sal_uLong)wParam );
790 rDef = FALSE;
791 break;
792 case SAL_MSG_RECREATEHWND:
793 nRet = (LRESULT)ImplSalReCreateHWND( (HWND)wParam, (HWND)lParam, FALSE );
794 rDef = FALSE;
795 break;
796 case SAL_MSG_RECREATECHILDHWND:
797 nRet = (LRESULT)ImplSalReCreateHWND( (HWND)wParam, (HWND)lParam, TRUE );
798 rDef = FALSE;
799 break;
800 case SAL_MSG_DESTROYFRAME:
801 delete (SalFrame*)lParam;
802 rDef = FALSE;
803 break;
804 case SAL_MSG_DESTROYHWND:
805 //We only destroy the native window here. We do NOT destroy the SalFrame contained
806 //in the structure (GetWindowPtr()).
807 if (DestroyWindow((HWND)lParam) == 0)
808 {
809 OSL_ENSURE(0, "DestroyWindow failed!");
810 //Failure: We remove the SalFrame from the window structure. So we avoid that
811 // the window structure may contain an invalid pointer, once the SalFrame is deleted.
812 SetWindowPtr((HWND)lParam, 0);
813 }
814 rDef = FALSE;
815 break;
816 case SAL_MSG_CREATEOBJECT:
817 nRet = (LRESULT)ImplSalCreateObject( GetSalData()->mpFirstInstance, (WinSalFrame*)lParam );
818 rDef = FALSE;
819 break;
820 case SAL_MSG_DESTROYOBJECT:
821 delete (SalObject*)lParam;
822 rDef = FALSE;
823 break;
824 case SAL_MSG_GETDC:
825 nRet = (LRESULT)GetDCEx( (HWND)wParam, 0, DCX_CACHE );
826 rDef = FALSE;
827 break;
828 case SAL_MSG_RELEASEDC:
829 ReleaseDC( (HWND)wParam, (HDC)lParam );
830 rDef = FALSE;
831 break;
832 case SAL_MSG_POSTTIMER:
833 SalTimerProc( 0, 0, SALTIMERPROC_RECURSIVE, lParam );
834 break;
835 }
836
837 return nRet;
838 }
839
SalComWndProcA(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam)840 LRESULT CALLBACK SalComWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
841 {
842 int bDef = TRUE;
843 LRESULT nRet = 0;
844 #ifdef __MINGW32__
845 jmp_buf jmpbuf;
846 __SEHandler han;
847 if (__builtin_setjmp(jmpbuf) == 0)
848 {
849 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
850 #else
851 __try
852 {
853 #endif
854 nRet = SalComWndProc( hWnd, nMsg, wParam, lParam, bDef );
855 }
856 #ifdef __MINGW32__
857 han.Reset();
858 #else
859 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
860 {
861 }
862 #endif
863 if ( bDef )
864 {
865 if ( !ImplHandleGlobalMsg( hWnd, nMsg, wParam, lParam, nRet ) )
866 nRet = DefWindowProcA( hWnd, nMsg, wParam, lParam );
867 }
868 return nRet;
869 }
870
871 LRESULT CALLBACK SalComWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
872 {
873 int bDef = TRUE;
874 LRESULT nRet = 0;
875 #ifdef __MINGW32__
876 jmp_buf jmpbuf;
877 __SEHandler han;
878 if (__builtin_setjmp(jmpbuf) == 0)
879 {
880 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
881 #else
882 __try
883 {
884 #endif
885 nRet = SalComWndProc( hWnd, nMsg, wParam, lParam, bDef );
886 }
887 #ifdef __MINGW32__
888 han.Reset();
889 #else
890 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
891 {
892 }
893 #endif
894 if ( bDef )
895 {
896 if ( !ImplHandleGlobalMsg( hWnd, nMsg, wParam, lParam, nRet ) )
897 nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam );
898 }
899 return nRet;
900 }
901
902 // -----------------------------------------------------------------------
903
904 bool WinSalInstance::AnyInput( sal_uInt16 nType )
905 {
906 MSG aMsg;
907
908 if ( (nType & (INPUT_ANY)) == (INPUT_ANY) )
909 {
910 // revert bugfix for #108919# which never reported timeouts when called from the timer handler
911 // which made the application completely unresponsive during background formatting
912 if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_NOREMOVE | PM_NOYIELD ) )
913 return true;
914 }
915 else
916 {
917 if ( nType & INPUT_MOUSE )
918 {
919 // Test for mouse input
920 if ( ImplPeekMessage( &aMsg, 0, WM_MOUSEFIRST, WM_MOUSELAST,
921 PM_NOREMOVE | PM_NOYIELD ) )
922 return true;
923 }
924
925 if ( nType & INPUT_KEYBOARD )
926 {
927 // Test for key input
928 if ( ImplPeekMessage( &aMsg, 0, WM_KEYDOWN, WM_KEYDOWN,
929 PM_NOREMOVE | PM_NOYIELD ) )
930 {
931 if ( (aMsg.wParam == VK_SHIFT) ||
932 (aMsg.wParam == VK_CONTROL) ||
933 (aMsg.wParam == VK_MENU) )
934 return false;
935 else
936 return true;
937 }
938 }
939
940 if ( nType & INPUT_PAINT )
941 {
942 // Test for paint input
943 if ( ImplPeekMessage( &aMsg, 0, WM_PAINT, WM_PAINT,
944 PM_NOREMOVE | PM_NOYIELD ) )
945 return true;
946
947 if ( ImplPeekMessage( &aMsg, 0, WM_SIZE, WM_SIZE,
948 PM_NOREMOVE | PM_NOYIELD ) )
949 return true;
950
951 if ( ImplPeekMessage( &aMsg, 0, SAL_MSG_POSTCALLSIZE, SAL_MSG_POSTCALLSIZE,
952 PM_NOREMOVE | PM_NOYIELD ) )
953 return true;
954
955 if ( ImplPeekMessage( &aMsg, 0, WM_MOVE, WM_MOVE,
956 PM_NOREMOVE | PM_NOYIELD ) )
957 return true;
958
959 if ( ImplPeekMessage( &aMsg, 0, SAL_MSG_POSTMOVE, SAL_MSG_POSTMOVE,
960 PM_NOREMOVE | PM_NOYIELD ) )
961 return true;
962 }
963
964 if ( nType & INPUT_TIMER )
965 {
966 // Test for timer input
967 if ( ImplPeekMessage( &aMsg, 0, WM_TIMER, WM_TIMER,
968 PM_NOREMOVE | PM_NOYIELD ) )
969 return true;
970
971 }
972
973 if ( nType & INPUT_OTHER )
974 {
975 // Test for any input
976 if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_NOREMOVE | PM_NOYIELD ) )
977 return true;
978 }
979 }
980
981 return FALSE;
982 }
983
984 // -----------------------------------------------------------------------
985
986 void SalTimer::Start( sal_uLong nMS )
987 {
988 // Um auf Main-Thread umzuschalten
989 SalData* pSalData = GetSalData();
990 if ( pSalData->mpFirstInstance )
991 {
992 if ( pSalData->mnAppThreadId != GetCurrentThreadId() )
993 ImplPostMessage( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS );
994 else
995 ImplSendMessage( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS );
996 }
997 else
998 ImplSalStartTimer( nMS, FALSE );
999 }
1000
1001 // -----------------------------------------------------------------------
1002
1003 SalFrame* WinSalInstance::CreateChildFrame( SystemParentData* pSystemParentData, sal_uLong nSalFrameStyle )
1004 {
1005 // Um auf Main-Thread umzuschalten
1006 return (SalFrame*)ImplSendMessage( mhComWnd, SAL_MSG_CREATEFRAME, nSalFrameStyle, (LPARAM)pSystemParentData->hWnd );
1007 }
1008
1009 // -----------------------------------------------------------------------
1010
1011 SalFrame* WinSalInstance::CreateFrame( SalFrame* pParent, sal_uLong nSalFrameStyle )
1012 {
1013 // Um auf Main-Thread umzuschalten
1014 HWND hWndParent;
1015 if ( pParent )
1016 hWndParent = static_cast<WinSalFrame*>(pParent)->mhWnd;
1017 else
1018 hWndParent = 0;
1019 return (SalFrame*)ImplSendMessage( mhComWnd, SAL_MSG_CREATEFRAME, nSalFrameStyle, (LPARAM)hWndParent );
1020 }
1021
1022 // -----------------------------------------------------------------------
1023
1024 void WinSalInstance::DestroyFrame( SalFrame* pFrame )
1025 {
1026 ImplSendMessage( mhComWnd, SAL_MSG_DESTROYFRAME, 0, (LPARAM)pFrame );
1027 }
1028
1029 // -----------------------------------------------------------------------
1030
1031 SalObject* WinSalInstance::CreateObject( SalFrame* pParent,
1032 SystemWindowData* /*pWindowData*/, // SystemWindowData meaningless on Windows
1033 sal_Bool /*bShow*/ )
1034 {
1035 // Um auf Main-Thread umzuschalten
1036 return (SalObject*)ImplSendMessage( mhComWnd, SAL_MSG_CREATEOBJECT, 0, (LPARAM)static_cast<WinSalFrame*>(pParent) );
1037 }
1038
1039 // -----------------------------------------------------------------------
1040
1041 void WinSalInstance::DestroyObject( SalObject* pObject )
1042 {
1043 ImplSendMessage( mhComWnd, SAL_MSG_DESTROYOBJECT, 0, (LPARAM)pObject );
1044 }
1045
1046 // -----------------------------------------------------------------------
1047
1048 void* WinSalInstance::GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes )
1049 {
1050 rReturnedBytes = 1;
1051 rReturnedType = AsciiCString;
1052 return const_cast<char *>("");
1053 }
1054
1055 // -----------------------------------------------------------------------
1056
1057 /** Add a file to the system shells recent document list if there is any.
1058 This function may have no effect under Unix because there is no
1059 standard API among the different desktop managers.
1060
1061 @param aFileUrl
1062 The file url of the document.
1063 */
1064 void WinSalInstance::AddToRecentDocumentList(const rtl::OUString& rFileUrl, const rtl::OUString& /*rMimeType*/)
1065 {
1066 rtl::OUString system_path;
1067 osl::FileBase::RC rc = osl::FileBase::getSystemPathFromFileURL(rFileUrl, system_path);
1068
1069 OSL_ENSURE(osl::FileBase::E_None == rc, "Invalid file url");
1070
1071 if (osl::FileBase::E_None == rc)
1072 SHAddToRecentDocs(SHARD_PATHW, system_path.getStr());
1073 }
1074
1075 // -----------------------------------------------------------------------
1076
1077 SalTimer* WinSalInstance::CreateSalTimer()
1078 {
1079 return new WinSalTimer();
1080 }
1081
1082 // -----------------------------------------------------------------------
1083
1084 SalBitmap* WinSalInstance::CreateSalBitmap()
1085 {
1086 return new WinSalBitmap();
1087 }
1088
1089 class WinImeStatus : public SalI18NImeStatus
1090 {
1091 public:
1092 WinImeStatus() {}
1093 virtual ~WinImeStatus() {}
1094
1095 // asks whether there is a status window available
1096 // to toggle into menubar
1097 virtual bool canToggle() { return false; }
1098 virtual void toggle() {}
1099 };
1100
1101 SalI18NImeStatus* WinSalInstance::CreateI18NImeStatus()
1102 {
1103 return new WinImeStatus();
1104 }
1105
1106 // -----------------------------------------------------------------------
1107
1108 const ::rtl::OUString& SalGetDesktopEnvironment()
1109 {
1110 static ::rtl::OUString aDesktopEnvironment( RTL_CONSTASCII_USTRINGPARAM( "Windows" ) );
1111 return aDesktopEnvironment;
1112 }
1113
1114 SalSession* WinSalInstance::CreateSalSession()
1115 {
1116 return NULL;
1117 }
1118
1119 #ifndef __MINGW32__
1120 // -----------------------------------------------------------------------
1121 int WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(int, LPEXCEPTION_POINTERS pExceptionInfo)
1122 {
1123 // Decide if an exception is a c++ (mostly UNO) exception or a process violation.
1124 // Depending on this information we pass process violations directly to our signal handler ...
1125 // and c++ (UNO) exceptions are sended to the following code on the current stack.
1126 // Problem behind: user32.dll sometime consumes exceptions/process violations .-)
1127 // see also #112221#
1128
1129 static DWORD EXCEPTION_MSC_CPP_EXCEPTION = 0xE06D7363;
1130
1131 if (pExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_MSC_CPP_EXCEPTION)
1132 return EXCEPTION_CONTINUE_SEARCH;
1133
1134 return UnhandledExceptionFilter( pExceptionInfo );
1135 }
1136 #endif
1137