xref: /trunk/main/vcl/win/source/window/salobj.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 
31 #include <string.h>
32 
33 #include <tools/debug.hxx>
34 #include <tools/svwin.h>
35 
36 #include <vcl/svapp.hxx>
37 
38 #include <win/wincomp.hxx>
39 #include <win/saldata.hxx>
40 #include <win/salinst.h>
41 #include <win/salframe.h>
42 #include <win/salobj.h>
43 
44 // =======================================================================
45 
46 static sal_Bool ImplIsSysWindowOrChild( HWND hWndParent, HWND hWndChild )
47 {
48     if ( hWndParent == hWndChild )
49         return TRUE;
50 
51     HWND hTempWnd = ::GetParent( hWndChild );
52     while ( hTempWnd )
53     {
54         // Ab nicht Child-Fenstern hoeren wir auf zu suchen
55         if ( !(GetWindowStyle( hTempWnd ) & WS_CHILD) )
56             return FALSE;
57         if ( hTempWnd == hWndParent )
58             return TRUE;
59         hTempWnd = ::GetParent( hTempWnd );
60     }
61 
62     return FALSE;
63 }
64 
65 // -----------------------------------------------------------------------
66 
67 WinSalObject* ImplFindSalObject( HWND hWndChild )
68 {
69     SalData*        pSalData = GetSalData();
70     WinSalObject*   pObject = pSalData->mpFirstObject;
71     while ( pObject )
72     {
73         if ( ImplIsSysWindowOrChild( pObject->mhWndChild, hWndChild ) )
74             return pObject;
75 
76         pObject = pObject->mpNextObject;
77     }
78 
79     return NULL;
80 }
81 
82 // -----------------------------------------------------------------------
83 
84 WinSalFrame* ImplFindSalObjectFrame( HWND hWnd )
85 {
86     WinSalFrame* pFrame = NULL;
87     WinSalObject* pObject = ImplFindSalObject( hWnd );
88     if ( pObject )
89     {
90         // Dazugehoerenden Frame suchen
91         HWND hWnd = ::GetParent( pObject->mhWnd );
92         pFrame = GetSalData()->mpFirstFrame;
93         while ( pFrame )
94         {
95             if ( pFrame->mhWnd == hWnd )
96                 break;
97 
98             pFrame = pFrame->mpNextFrame;
99         }
100     }
101 
102     return pFrame;
103 }
104 
105 // -----------------------------------------------------------------------
106 
107 sal_Bool ImplInterceptChildWindowKeyDown( MSG& rMsg )
108 {
109     sal_Bool bResult = sal_False;
110     if ( rMsg.message == WM_KEYDOWN )
111     {
112         wchar_t pClassName[10];
113         sal_Int32 nLen = GetClassNameW( rMsg.hwnd, pClassName, 10 );
114         if ( !( nLen == 9 && wcsncmp( pClassName, SAL_OBJECT_CLASSNAMEW, nLen ) == 0 ) )
115         {
116             // look for the first SalObject in the parent hierarchy
117             HWND hWin = rMsg.hwnd;
118             HWND hLastOLEWindow = hWin;
119             WinSalObject* pSalObj = NULL;
120             do
121             {
122                 hLastOLEWindow = hWin;
123                 hWin = ::GetParent( hWin );
124                 if ( hWin )
125                 {
126                     nLen = GetClassNameW( hWin, pClassName, 10 );
127                     if ( nLen == 9 && wcsncmp( pClassName, SAL_OBJECT_CLASSNAMEW, nLen ) == 0 )
128                         pSalObj = GetSalObjWindowPtr( hWin );
129                 }
130             } while( hWin && !pSalObj );
131 
132             if ( pSalObj && pSalObj->mbInterceptChildWindowKeyDown && pSalObj->maSysData.hWnd )
133             {
134                 bResult = ( 1 == ImplSendMessage( pSalObj->maSysData.hWnd, rMsg.message, rMsg.wParam, rMsg.lParam ) );
135             }
136         }
137     }
138 
139     return bResult;
140 }
141 
142 // -----------------------------------------------------------------------
143 
144 
145 // -----------------------------------------------------------------------
146 
147 LRESULT CALLBACK SalSysMsgProc( int nCode, WPARAM wParam, LPARAM lParam )
148 {
149     // Used for Unicode and none Unicode
150     SalData* pSalData = GetSalData();
151 
152     if ( (nCode >= 0) && lParam )
153     {
154         CWPSTRUCT* pData = (CWPSTRUCT*)lParam;
155         if ( (pData->message != WM_KEYDOWN) &&
156              (pData->message != WM_KEYUP) )
157             pSalData->mnSalObjWantKeyEvt = 0;
158 
159         // Testen, ob wir Daten fuer ein SalObject-Fenster behandeln
160         // muessen
161         WinSalObject* pObject;
162         if ( pData->message == WM_SETFOCUS )
163         {
164             pObject = ImplFindSalObject( pData->hwnd );
165             if ( pObject )
166             {
167                 pObject->mhLastFocusWnd = pData->hwnd;
168                 if ( ImplSalYieldMutexTryToAcquire() )
169                 {
170                     pObject->CallCallback( SALOBJ_EVENT_GETFOCUS, 0 );
171                     ImplSalYieldMutexRelease();
172                 }
173                 else
174                     ImplPostMessage( pObject->mhWnd, SALOBJ_MSG_POSTFOCUS, 0, 0 );
175             }
176         }
177         else if ( pData->message == WM_KILLFOCUS )
178         {
179             pObject = ImplFindSalObject( pData->hwnd );
180             if ( pObject && !ImplFindSalObject( (HWND)pData->wParam ) )
181             {
182                 // LoseFocus nur rufen, wenn wirklich kein ChildFenster
183                 // den Focus bekommt
184                 if ( !pData->wParam || !ImplFindSalObject( (HWND)pData->wParam ) )
185                 {
186                     if ( ImplSalYieldMutexTryToAcquire() )
187                     {
188                         pObject->CallCallback( SALOBJ_EVENT_LOSEFOCUS, 0 );
189                         ImplSalYieldMutexRelease();
190                     }
191                     else
192                         ImplPostMessage( pObject->mhWnd, SALOBJ_MSG_POSTFOCUS, 0, 0 );
193                 }
194                 else
195                     pObject->mhLastFocusWnd = (HWND)pData->wParam;
196             }
197         }
198     }
199 
200     return CallNextHookEx( pSalData->mhSalObjMsgHook, nCode, wParam, lParam );
201 }
202 
203 // -----------------------------------------------------------------------
204 
205 sal_Bool ImplSalPreDispatchMsg( MSG* pMsg )
206 {
207     // Used for Unicode and none Unicode
208     SalData*        pSalData = GetSalData();
209     WinSalObject*   pObject;
210 
211     if ( (pMsg->message == WM_LBUTTONDOWN) ||
212          (pMsg->message == WM_RBUTTONDOWN) ||
213          (pMsg->message == WM_MBUTTONDOWN) )
214     {
215         ImplSalYieldMutexAcquireWithWait();
216         pObject = ImplFindSalObject( pMsg->hwnd );
217         if ( pObject && !pObject->IsMouseTransparent() )
218             ImplPostMessage( pObject->mhWnd, SALOBJ_MSG_TOTOP, 0, 0 );
219         ImplSalYieldMutexRelease();
220     }
221 
222     if ( (pMsg->message == WM_KEYDOWN) ||
223          (pMsg->message == WM_KEYUP) )
224     {
225         // KeyEvents wollen wir nach Moeglichkeit auch abarbeiten,
226         // wenn das Control diese nicht selber auswertet
227         // SysKeys werden als WM_SYSCOMMAND verarbeitet
228         // Char-Events verarbeiten wir nicht, da wir nur
229         // Accelerator relevante Keys verarbeiten wollen
230         sal_Bool bWantedKeyCode = FALSE;
231         // A-Z, 0-9 nur in Verbindung mit Control-Taste
232         if ( ((pMsg->wParam >= 65) && (pMsg->wParam <= 90)) ||
233              ((pMsg->wParam >= 48) && (pMsg->wParam <= 57)) )
234         {
235             if ( GetKeyState( VK_CONTROL ) & 0x8000 )
236                 bWantedKeyCode = TRUE;
237         }
238         else if ( ((pMsg->wParam >= VK_F1) && (pMsg->wParam <= VK_F24)) ||
239                   ((pMsg->wParam >= VK_SPACE) && (pMsg->wParam <= VK_HELP)) ||
240                   (pMsg->wParam == VK_BACK) || (pMsg->wParam == VK_TAB) ||
241                   (pMsg->wParam == VK_CLEAR) || (pMsg->wParam == VK_RETURN) ||
242                   (pMsg->wParam == VK_ESCAPE) )
243             bWantedKeyCode = TRUE;
244         if ( bWantedKeyCode )
245         {
246             ImplSalYieldMutexAcquireWithWait();
247             pObject = ImplFindSalObject( pMsg->hwnd );
248             if ( pObject )
249                 pSalData->mnSalObjWantKeyEvt = pMsg->wParam;
250             ImplSalYieldMutexRelease();
251         }
252     }
253     // Hier WM_SYSCHAR abfangen, um mit Alt+Taste evtl. Menu zu aktivieren
254     else if ( pMsg->message == WM_SYSCHAR )
255     {
256         pSalData->mnSalObjWantKeyEvt = 0;
257 
258         sal_uInt16 nKeyCode = LOWORD( pMsg->wParam );
259         // Nur 0-9 und A-Z
260         if ( ((nKeyCode >= 48) && (nKeyCode <= 57)) ||
261              ((nKeyCode >= 65) && (nKeyCode <= 90)) ||
262              ((nKeyCode >= 97) && (nKeyCode <= 122)) )
263         {
264             sal_Bool bRet = FALSE;
265             ImplSalYieldMutexAcquireWithWait();
266             pObject = ImplFindSalObject( pMsg->hwnd );
267             if ( pObject )
268             {
269                 if ( pMsg->hwnd == ::GetFocus() )
270                 {
271                     WinSalFrame* pFrame = ImplFindSalObjectFrame( pMsg->hwnd );
272                     if ( pFrame )
273                     {
274                         if ( ImplHandleSalObjSysCharMsg( pFrame->mhWnd, pMsg->wParam, pMsg->lParam ) )
275                             bRet = TRUE;
276                     }
277                 }
278             }
279             ImplSalYieldMutexRelease();
280             if ( bRet )
281                 return TRUE;
282         }
283     }
284     else
285         pSalData->mnSalObjWantKeyEvt = 0;
286 
287     return FALSE;
288 }
289 
290 // -----------------------------------------------------------------------
291 
292 void ImplSalPostDispatchMsg( MSG* pMsg, LRESULT /* nDispatchResult */ )
293 {
294     // Used for Unicode and none Unicode
295     SalData*        pSalData = GetSalData();
296     WinSalFrame*    pFrame;
297 
298     if ( (pMsg->message == WM_KEYDOWN) || (pMsg->message == WM_KEYUP) )
299     {
300         if ( pSalData->mnSalObjWantKeyEvt == pMsg->wParam )
301         {
302             pSalData->mnSalObjWantKeyEvt = 0;
303             if ( pMsg->hwnd == ::GetFocus() )
304             {
305                 ImplSalYieldMutexAcquireWithWait();
306                 pFrame = ImplFindSalObjectFrame( pMsg->hwnd );
307                 if ( pFrame )
308                     ImplHandleSalObjKeyMsg( pFrame->mhWnd, pMsg->message, pMsg->wParam, pMsg->lParam );
309                 ImplSalYieldMutexRelease();
310             }
311         }
312     }
313 
314     pSalData->mnSalObjWantKeyEvt = 0;
315 }
316 
317 // =======================================================================
318 
319 LRESULT CALLBACK SalSysObjWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef )
320 {
321     WinSalObject*   pSysObj;
322     LRESULT         nRet = 0;
323 
324     switch( nMsg )
325     {
326         case WM_ERASEBKGND:
327             nRet = 1;
328             rDef = FALSE;
329             break;
330         case WM_PAINT:
331             {
332             PAINTSTRUCT aPs;
333             BeginPaint( hWnd, &aPs );
334             EndPaint( hWnd, &aPs );
335             rDef = FALSE;
336             }
337             break;
338 
339         case WM_PARENTNOTIFY:
340             {
341             UINT nNotifyMsg = LOWORD( wParam );
342             if ( (nNotifyMsg == WM_LBUTTONDOWN) ||
343                  (nNotifyMsg == WM_RBUTTONDOWN) ||
344                  (nNotifyMsg == WM_MBUTTONDOWN) )
345             {
346                 ImplSalYieldMutexAcquireWithWait();
347                 pSysObj = GetSalObjWindowPtr( hWnd );
348                 if ( pSysObj && !pSysObj->IsMouseTransparent() )
349                     pSysObj->CallCallback( SALOBJ_EVENT_TOTOP, 0 );
350                 ImplSalYieldMutexRelease();
351             }
352             }
353             break;
354 
355         case WM_MOUSEACTIVATE:
356             {
357             ImplSalYieldMutexAcquireWithWait();
358             pSysObj = GetSalObjWindowPtr( hWnd );
359             if ( pSysObj && !pSysObj->IsMouseTransparent() )
360                 ImplPostMessage( hWnd, SALOBJ_MSG_TOTOP, 0, 0 );
361             ImplSalYieldMutexRelease();
362             }
363             break;
364 
365         case SALOBJ_MSG_TOTOP:
366             if ( ImplSalYieldMutexTryToAcquire() )
367             {
368                 pSysObj = GetSalObjWindowPtr( hWnd );
369                 pSysObj->CallCallback( SALOBJ_EVENT_TOTOP, 0 );
370                 ImplSalYieldMutexRelease();
371                 rDef = FALSE;
372             }
373             else
374                 ImplPostMessage( hWnd, SALOBJ_MSG_TOTOP, 0, 0 );
375             break;
376 
377         case SALOBJ_MSG_POSTFOCUS:
378             if ( ImplSalYieldMutexTryToAcquire() )
379             {
380                 pSysObj = GetSalObjWindowPtr( hWnd );
381                 HWND    hFocusWnd = ::GetFocus();
382                 sal_uInt16 nEvent;
383                 if ( hFocusWnd && ImplIsSysWindowOrChild( hWnd, hFocusWnd ) )
384                     nEvent = SALOBJ_EVENT_GETFOCUS;
385                 else
386                     nEvent = SALOBJ_EVENT_LOSEFOCUS;
387                 pSysObj->CallCallback( nEvent, 0 );
388                 ImplSalYieldMutexRelease();
389             }
390             else
391                 ImplPostMessage( hWnd, SALOBJ_MSG_POSTFOCUS, 0, 0 );
392             rDef = FALSE;
393             break;
394 
395         case WM_SIZE:
396             {
397             HWND hWndChild = GetWindow( hWnd, GW_CHILD );
398             if ( hWndChild )
399             {
400                 SetWindowPos( hWndChild,
401                               0, 0,  0, (int)LOWORD( lParam ), (int)HIWORD( lParam ),
402                               SWP_NOZORDER | SWP_NOACTIVATE );
403             }
404             }
405             rDef = FALSE;
406             break;
407 
408         case WM_CREATE:
409             {
410             // Window-Instanz am Windowhandle speichern
411             // Can also be used for the W-Version, because the struct
412             // to access lpCreateParams is the same structure
413             CREATESTRUCTA* pStruct = (CREATESTRUCTA*)lParam;
414             pSysObj = (WinSalObject*)pStruct->lpCreateParams;
415             SetSalObjWindowPtr( hWnd, pSysObj );
416             // HWND schon hier setzen, da schon auf den Instanzdaten
417             // gearbeitet werden kann, wenn Messages waehrend
418             // CreateWindow() gesendet werden
419             pSysObj->mhWnd = hWnd;
420             rDef = FALSE;
421             }
422             break;
423     }
424 
425     return nRet;
426 }
427 
428 LRESULT CALLBACK SalSysObjWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
429 {
430     int bDef = TRUE;
431     LRESULT nRet = SalSysObjWndProc( hWnd, nMsg, wParam, lParam, bDef );
432     if ( bDef )
433         nRet = DefWindowProcA( hWnd, nMsg, wParam, lParam );
434     return nRet;
435 }
436 
437 LRESULT CALLBACK SalSysObjWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
438 {
439     int bDef = TRUE;
440     LRESULT nRet = SalSysObjWndProc( hWnd, nMsg, wParam, lParam, bDef );
441     if ( bDef )
442         nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam );
443     return nRet;
444 }
445 
446 // -----------------------------------------------------------------------
447 
448 LRESULT CALLBACK SalSysObjChildWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef )
449 {
450     LRESULT nRet = 0;
451 
452     switch( nMsg )
453     {
454         // Wegen PlugIn's loeschen wir erstmal den Hintergrund
455         case WM_ERASEBKGND:
456             {
457                 WinSalObject* pSysObj = GetSalObjWindowPtr( ::GetParent( hWnd ) );
458 
459                 if( pSysObj && !pSysObj->IsEraseBackgroundEnabled() )
460                 {
461                     // do not erase background
462                     nRet = 1;
463                     rDef = FALSE;
464                 }
465             }
466             break;
467 
468         case WM_PAINT:
469             {
470             PAINTSTRUCT aPs;
471             BeginPaint( hWnd, &aPs );
472             EndPaint( hWnd, &aPs );
473             rDef = FALSE;
474             }
475             break;
476 
477         case WM_MOUSEMOVE:
478         case WM_LBUTTONDOWN:
479         case WM_MBUTTONDOWN:
480         case WM_RBUTTONDOWN:
481         case WM_LBUTTONUP:
482         case WM_MBUTTONUP:
483         case WM_RBUTTONUP:
484             {
485                 WinSalObject* pSysObj;
486                 pSysObj = GetSalObjWindowPtr( ::GetParent( hWnd ) );
487 
488                 if( pSysObj && pSysObj->IsMouseTransparent() )
489                 {
490                     // forward mouse events to parent frame
491                     HWND hWndParent = ::GetParent( pSysObj->mhWnd );
492 
493                     // transform coordinates
494                     POINT pt;
495                     pt.x = (long) LOWORD( lParam );
496                     pt.y = (long) HIWORD( lParam );
497                     MapWindowPoints( hWnd, hWndParent, &pt, 1 );
498                     lParam = MAKELPARAM( (WORD) pt.x, (WORD) pt.y );
499 
500                     nRet = ImplSendMessage( hWndParent, nMsg, wParam, lParam );
501                     rDef = FALSE;
502                 }
503             }
504             break;
505     }
506 
507     return nRet;
508 }
509 
510 LRESULT CALLBACK SalSysObjChildWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
511 {
512     int bDef = TRUE;
513     LRESULT nRet = SalSysObjChildWndProc( hWnd, nMsg, wParam, lParam, bDef );
514     if ( bDef )
515         nRet = DefWindowProcA( hWnd, nMsg, wParam, lParam );
516     return nRet;
517 }
518 
519 LRESULT CALLBACK SalSysObjChildWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
520 {
521     int bDef = TRUE;
522     LRESULT nRet = SalSysObjChildWndProc( hWnd, nMsg, wParam, lParam, bDef );
523     if ( bDef )
524         nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam );
525     return nRet;
526 }
527 
528 // =======================================================================
529 
530 SalObject* ImplSalCreateObject( WinSalInstance* pInst, WinSalFrame* pParent )
531 {
532     SalData* pSalData = GetSalData();
533 
534     // Hook installieren, wenn es das erste SalObject ist
535     if ( !pSalData->mpFirstObject )
536     {
537         pSalData->mhSalObjMsgHook = SetWindowsHookExW( WH_CALLWNDPROC,
538                                                            SalSysMsgProc,
539                                                            pSalData->mhInst,
540                                                            pSalData->mnAppThreadId );
541     }
542 
543     if ( !pSalData->mbObjClassInit )
544     {
545         // #95301# shockwave plugin has bug; expects ASCII functions to be used
546         if ( false )//aSalShlData.mbWNT )
547         {
548             WNDCLASSEXW aWndClassEx;
549             aWndClassEx.cbSize          = sizeof( aWndClassEx );
550             aWndClassEx.style           = 0;
551             aWndClassEx.lpfnWndProc     = SalSysObjWndProcW;
552             aWndClassEx.cbClsExtra      = 0;
553             aWndClassEx.cbWndExtra      = SAL_OBJECT_WNDEXTRA;
554             aWndClassEx.hInstance       = pSalData->mhInst;
555             aWndClassEx.hIcon           = 0;
556             aWndClassEx.hIconSm         = 0;
557             aWndClassEx.hCursor         = LoadCursor( 0, IDC_ARROW );
558             aWndClassEx.hbrBackground   = 0;
559             aWndClassEx.lpszMenuName    = 0;
560             aWndClassEx.lpszClassName   = SAL_OBJECT_CLASSNAMEW;
561             if ( RegisterClassExW( &aWndClassEx ) )
562             {
563                 // Wegen PlugIn's loeschen wir erstmal den Hintergrund
564                 aWndClassEx.cbWndExtra      = 0;
565                 aWndClassEx.hbrBackground   = (HBRUSH)(COLOR_WINDOW+1);
566                 aWndClassEx.lpfnWndProc     = SalSysObjChildWndProcW;
567                 aWndClassEx.lpszClassName   = SAL_OBJECT_CHILDCLASSNAMEW;
568                 if ( RegisterClassExW( &aWndClassEx ) )
569                     pSalData->mbObjClassInit = TRUE;
570             }
571         }
572         else
573         {
574             WNDCLASSEXA aWndClassEx;
575             aWndClassEx.cbSize          = sizeof( aWndClassEx );
576             aWndClassEx.style           = 0;
577             aWndClassEx.lpfnWndProc     = SalSysObjWndProcA;
578             aWndClassEx.cbClsExtra      = 0;
579             aWndClassEx.cbWndExtra      = SAL_OBJECT_WNDEXTRA;
580             aWndClassEx.hInstance       = pSalData->mhInst;
581             aWndClassEx.hIcon           = 0;
582             aWndClassEx.hIconSm         = 0;
583             aWndClassEx.hCursor         = LoadCursor( 0, IDC_ARROW );
584             aWndClassEx.hbrBackground   = 0;
585             aWndClassEx.lpszMenuName    = 0;
586             aWndClassEx.lpszClassName   = SAL_OBJECT_CLASSNAMEA;
587             if ( RegisterClassExA( &aWndClassEx ) )
588             {
589                 // Wegen PlugIn's loeschen wir erstmal den Hintergrund
590                 aWndClassEx.cbWndExtra      = 0;
591                 aWndClassEx.hbrBackground   = (HBRUSH)(COLOR_WINDOW+1);
592                 aWndClassEx.lpfnWndProc     = SalSysObjChildWndProcA;
593                 aWndClassEx.lpszClassName   = SAL_OBJECT_CHILDCLASSNAMEA;
594                 if ( RegisterClassExA( &aWndClassEx ) )
595                     pSalData->mbObjClassInit = TRUE;
596             }
597         }
598     }
599 
600     if ( pSalData->mbObjClassInit )
601     {
602         WinSalObject* pObject = new WinSalObject;
603 
604         // #135235# Clip siblings of this
605         // SystemChildWindow. Otherwise, DXCanvas (using a hidden
606         // SystemChildWindow) clobbers applets/plugins during
607         // animations .
608         HWND hWnd = CreateWindowExA( 0, SAL_OBJECT_CLASSNAMEA, "",
609                                      WS_CHILD | WS_CLIPSIBLINGS, 0, 0, 0, 0,
610                                      pParent->mhWnd, 0,
611                                      pInst->mhInst, (void*)pObject );
612 
613         HWND hWndChild = 0;
614         if ( hWnd )
615         {
616             // #135235# Explicitely stack SystemChildWindows in
617             // the order they're created - since there's no notion
618             // of zorder.
619             SetWindowPos(hWnd,HWND_TOP,0,0,0,0,
620                          SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOSIZE);
621             hWndChild = CreateWindowExA( 0, SAL_OBJECT_CHILDCLASSNAMEA, "",
622                                          WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE,
623                                          0, 0, 0, 0,
624                                          hWnd, 0,
625                                          pInst->mhInst, NULL );
626         }
627 
628         if ( !hWndChild )
629         {
630             delete pObject;
631             return NULL;
632         }
633 
634         if ( hWnd )
635         {
636             pObject->mhWnd          = hWnd;
637             pObject->mhWndChild     = hWndChild;
638             pObject->maSysData.hWnd = hWndChild;
639             return pObject;
640         }
641     }
642 
643     return NULL;
644 }
645 
646 // =======================================================================
647 
648 WinSalObject::WinSalObject()
649 {
650     SalData* pSalData = GetSalData();
651 
652     mhWnd           = 0;
653     mhWndChild      = 0;
654     mhLastFocusWnd  = 0;
655     maSysData.nSize = sizeof( SystemEnvData );
656     mpStdClipRgnData    = NULL;
657     mbInterceptChildWindowKeyDown = sal_False;
658 
659     // Insert object in objectlist
660     mpNextObject = pSalData->mpFirstObject;
661     pSalData->mpFirstObject = this;
662 }
663 
664 // -----------------------------------------------------------------------
665 
666 WinSalObject::~WinSalObject()
667 {
668     SalData* pSalData = GetSalData();
669 
670     // remove frame from framelist
671     if ( this == pSalData->mpFirstObject )
672     {
673         pSalData->mpFirstObject = mpNextObject;
674 
675         // Wenn letztes SalObject, dann Hook wieder entfernen
676         if ( !pSalData->mpFirstObject )
677             UnhookWindowsHookEx( pSalData->mhSalObjMsgHook );
678     }
679     else
680     {
681         WinSalObject* pTempObject = pSalData->mpFirstObject;
682         while ( pTempObject->mpNextObject != this )
683             pTempObject = pTempObject->mpNextObject;
684 
685         pTempObject->mpNextObject = mpNextObject;
686     }
687 
688     // Cache-Daten zerstoeren
689     if ( mpStdClipRgnData )
690         delete mpStdClipRgnData;
691 
692     HWND hWndParent = ::GetParent( mhWnd );
693 
694     if ( mhWndChild )
695         DestroyWindow( mhWndChild );
696     if ( mhWnd )
697         DestroyWindow( mhWnd );
698 
699     // Palette wieder zuruecksetzen, wenn kein externes Child-Fenster
700     // mehr vorhanden ist, da diese unsere Palette ueberschrieben haben
701     // koennen
702     if ( hWndParent &&
703          ::GetActiveWindow() == hWndParent &&
704          !GetWindow( hWndParent, GW_CHILD ) )
705         ImplSendMessage( hWndParent, SAL_MSG_FORCEPALETTE, 0, 0 );
706 }
707 
708 // -----------------------------------------------------------------------
709 
710 void WinSalObject::ResetClipRegion()
711 {
712     SetWindowRgn( mhWnd, 0, TRUE );
713 }
714 
715 // -----------------------------------------------------------------------
716 
717 sal_uInt16 WinSalObject::GetClipRegionType()
718 {
719     return SAL_OBJECT_CLIP_INCLUDERECTS;
720 }
721 
722 // -----------------------------------------------------------------------
723 
724 void WinSalObject::BeginSetClipRegion( sal_uLong nRectCount )
725 {
726     sal_uLong nRectBufSize = sizeof(RECT)*nRectCount;
727     if ( nRectCount < SAL_CLIPRECT_COUNT )
728     {
729         if ( !mpStdClipRgnData )
730             mpStdClipRgnData = (RGNDATA*)new BYTE[sizeof(RGNDATA)-1+(SAL_CLIPRECT_COUNT*sizeof(RECT))];
731         mpClipRgnData = mpStdClipRgnData;
732     }
733     else
734         mpClipRgnData = (RGNDATA*)new BYTE[sizeof(RGNDATA)-1+nRectBufSize];
735     mpClipRgnData->rdh.dwSize     = sizeof( RGNDATAHEADER );
736     mpClipRgnData->rdh.iType      = RDH_RECTANGLES;
737     mpClipRgnData->rdh.nCount     = nRectCount;
738     mpClipRgnData->rdh.nRgnSize  = nRectBufSize;
739     SetRectEmpty( &(mpClipRgnData->rdh.rcBound) );
740     mpNextClipRect        = (RECT*)(&(mpClipRgnData->Buffer));
741     mbFirstClipRect       = TRUE;
742 }
743 
744 // -----------------------------------------------------------------------
745 
746 void WinSalObject::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
747 {
748     RECT*       pRect = mpNextClipRect;
749     RECT*       pBoundRect = &(mpClipRgnData->rdh.rcBound);
750     long        nRight = nX + nWidth;
751     long        nBottom = nY + nHeight;
752 
753     if ( mbFirstClipRect )
754     {
755         pBoundRect->left    = nX;
756         pBoundRect->top     = nY;
757         pBoundRect->right   = nRight;
758         pBoundRect->bottom  = nBottom;
759         mbFirstClipRect = FALSE;
760     }
761     else
762     {
763         if ( nX < pBoundRect->left )
764             pBoundRect->left = (int)nX;
765 
766         if ( nY < pBoundRect->top )
767             pBoundRect->top = (int)nY;
768 
769         if ( nRight > pBoundRect->right )
770             pBoundRect->right = (int)nRight;
771 
772         if ( nBottom > pBoundRect->bottom )
773             pBoundRect->bottom = (int)nBottom;
774     }
775 
776     pRect->left     = (int)nX;
777     pRect->top      = (int)nY;
778     pRect->right    = (int)nRight;
779     pRect->bottom   = (int)nBottom;
780     mpNextClipRect++;
781 }
782 
783 // -----------------------------------------------------------------------
784 
785 void WinSalObject::EndSetClipRegion()
786 {
787     HRGN hRegion;
788 
789     // Aus den Region-Daten muessen wir jetzt eine ClipRegion erzeugen
790     if ( mpClipRgnData->rdh.nCount == 1 )
791     {
792         RECT* pRect = &(mpClipRgnData->rdh.rcBound);
793         hRegion = CreateRectRgn( pRect->left, pRect->top,
794                                  pRect->right, pRect->bottom );
795     }
796     else
797     {
798         sal_uLong nSize = mpClipRgnData->rdh.nRgnSize+sizeof(RGNDATAHEADER);
799         hRegion = ExtCreateRegion( NULL, nSize, mpClipRgnData );
800         if ( mpClipRgnData != mpStdClipRgnData )
801             delete [] (BYTE*)mpClipRgnData;
802     }
803 
804     DBG_ASSERT( hRegion, "SalObject::EndSetClipRegion() - Can't create ClipRegion" );
805     SetWindowRgn( mhWnd, hRegion, TRUE );
806 }
807 
808 // -----------------------------------------------------------------------
809 
810 void WinSalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight )
811 {
812     sal_uLong nStyle = 0;
813     sal_Bool bVisible = (GetWindowStyle( mhWnd ) & WS_VISIBLE) != 0;
814     if ( bVisible )
815     {
816         ShowWindow( mhWnd, SW_HIDE );
817         nStyle |= SWP_SHOWWINDOW;
818     }
819     SetWindowPos( mhWnd, 0,
820                   (int)nX, (int)nY, (int)nWidth, (int)nHeight,
821                   SWP_NOZORDER | SWP_NOACTIVATE | nStyle );
822 }
823 
824 // -----------------------------------------------------------------------
825 
826 void WinSalObject::Show( sal_Bool bVisible )
827 {
828     if ( bVisible )
829         ShowWindow( mhWnd, SW_SHOWNORMAL );
830     else
831         ShowWindow( mhWnd, SW_HIDE );
832 }
833 
834 // -----------------------------------------------------------------------
835 
836 void WinSalObject::Enable( sal_Bool bEnable )
837 {
838     EnableWindow( mhWnd, bEnable );
839 }
840 
841 // -----------------------------------------------------------------------
842 
843 void WinSalObject::GrabFocus()
844 {
845     if ( mhLastFocusWnd &&
846          IsWindow( mhLastFocusWnd ) &&
847          ImplIsSysWindowOrChild( mhWndChild, mhLastFocusWnd ) )
848         ::SetFocus( mhLastFocusWnd );
849     else
850         ::SetFocus( mhWndChild );
851 }
852 
853 // -----------------------------------------------------------------------
854 
855 void WinSalObject::SetBackground()
856 {
857 }
858 
859 // -----------------------------------------------------------------------
860 
861 void WinSalObject::SetBackground( SalColor )
862 {
863 }
864 
865 // -----------------------------------------------------------------------
866 
867 const SystemEnvData* WinSalObject::GetSystemData() const
868 {
869     return &maSysData;
870 }
871 
872 // -----------------------------------------------------------------------
873 
874 void WinSalObject::InterceptChildWindowKeyDown( sal_Bool bIntercept )
875 {
876     mbInterceptChildWindowKeyDown = bIntercept;
877 }
878 
879