xref: /aoo41x/main/vcl/win/source/window/salobj.cxx (revision cdf0e10c)
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