xref: /aoo41x/main/vcl/os2/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 #include <svpm.h>
29 
30 #define _SV_SALOBJ_CXX
31 #include <saldata.hxx>
32 #include <salinst.h>
33 #include <salframe.h>
34 #include <salobj.h>
35 
36 // =======================================================================
37 
38 static BOOL ImplIsSysWindowOrChild( HWND hWndParent, HWND hWndChild )
39 {
40 	if ( hWndParent == hWndChild )
41 		return TRUE;
42 
43 	HWND hTempWnd = WinQueryWindow( hWndChild, QW_PARENT );
44 	while ( hTempWnd )
45 	{
46 		if ( hTempWnd == hWndParent )
47 			return TRUE;
48 		hTempWnd = WinQueryWindow( hTempWnd, QW_PARENT );
49 	}
50 
51 	return FALSE;
52 }
53 
54 // -----------------------------------------------------------------------
55 
56 static Os2SalObject* ImplFindOs2SalObject( HWND hWndChild )
57 {
58 	SalData*	pSalData = GetSalData();
59 	Os2SalObject*	pObject = pSalData->mpFirstObject;
60 	while ( pObject )
61 	{
62 		if ( ImplIsSysWindowOrChild( pObject->mhWndChild, hWndChild ) )
63 			return pObject;
64 
65 		pObject = pObject->mpNextObject;
66 	}
67 
68 	return NULL;
69 }
70 
71 // =======================================================================
72 
73 BOOL EXPENTRY SalSysMsgProc( HAB /* hAB */, QMSG* pMsg, ULONG /* fs */ )
74 {
75 	if ( (pMsg->msg == WM_BUTTON1DOWN) ||
76 		 (pMsg->msg == WM_BUTTON2DOWN) ||
77 		 (pMsg->msg == WM_BUTTON3DOWN) )
78 	{
79 		SalData*	pSalData = GetSalData();
80 		Os2SalObject*	pObject = ImplFindOs2SalObject( pMsg->hwnd );
81 		if ( pObject )
82 			WinPostMsg( pObject->mhWnd, SALOBJ_MSG_TOTOP, 0, 0 );
83 	}
84 
85 	// Focus fangen wir hier nicht ab, da wir erstmal davon ausgehen,
86 	// das unser Os2SalObject-Fenster immer eine WM_FOCUSCHANGE-Message
87 	// bekommt.
88 
89 	return FALSE;
90 }
91 
92 // -----------------------------------------------------------------------
93 
94 MRESULT EXPENTRY SalSysObjWndProc( HWND hWnd, ULONG nMsg,
95 								   MPARAM nMP1, MPARAM nMP2 )
96 {
97 	Os2SalObject*	pSysObj;
98 	MRESULT 	nRet = 0;
99 	int 		bDef = TRUE;
100 
101 #if OSL_DEBUG_LEVEL>0
102 	debug_printf( "SalSysObjWndProc hWnd 0x%x nMsg %d\n", hWnd, nMsg);
103 #endif
104 
105 	switch( nMsg )
106 	{
107 		case WM_ERASEBACKGROUND:
108 			nRet = (MRESULT)FALSE;
109 			bDef = FALSE;
110 			break;
111 		case WM_PAINT:
112 			{
113 			HPS 	hPS;
114 			RECTL	aRect;
115 			hPS = WinBeginPaint( hWnd, NULLHANDLE, &aRect );
116 			WinEndPaint( hPS );
117 			bDef = FALSE;
118 			}
119 			bDef = FALSE;
120 			break;
121 
122 		case WM_BUTTON1DOWN:
123 		case WM_BUTTON2DOWN:
124 		case WM_BUTTON3DOWN:
125 		case SALOBJ_MSG_TOTOP:
126 			if ( ImplSalYieldMutexTryToAcquire() )
127 			{
128 				pSysObj = GetSalObjWindowPtr( hWnd );
129 				pSysObj->mpProc( pSysObj->mpInst, pSysObj,
130 											  SALOBJ_EVENT_TOTOP, 0 );
131 				ImplSalYieldMutexRelease();
132 			}
133 			else
134 				WinPostMsg( hWnd, SALOBJ_MSG_TOTOP, 0, 0 );
135 			break;
136 
137 		case WM_FOCUSCHANGE:
138 		case SALOBJ_MSG_POSTFOCUS:
139 			if ( ImplSalYieldMutexTryToAcquire() )
140 			{
141 				pSysObj = GetSalObjWindowPtr( hWnd );
142 				if ( SHORT1FROMMP( nMP2 ) )
143 				{
144 					pSysObj->mhLastFocusWnd = WinQueryFocus( HWND_DESKTOP );
145 					pSysObj->mpProc( pSysObj->mpInst, pSysObj,
146 												  SALOBJ_EVENT_GETFOCUS, 0 );
147 				}
148 				else
149 				{
150 					HWND hWndFocus = HWNDFROMMP( nMP1 );
151 					if ( !hWndFocus || !ImplIsSysWindowOrChild( hWnd, hWndFocus ) )
152 					{
153 						pSysObj->mpProc( pSysObj->mpInst, pSysObj,
154 													  SALOBJ_EVENT_LOSEFOCUS, 0 );
155 					}
156 				}
157 				ImplSalYieldMutexRelease();
158 			}
159 			else
160 				WinPostMsg( hWnd, SALOBJ_MSG_POSTFOCUS, nMP1, nMP2 );
161 			break;
162 
163 		case WM_SIZE:
164 			{
165 			pSysObj = GetSalObjWindowPtr( hWnd );
166 			pSysObj->mnHeight = (short)SHORT2FROMMP( nMP2 );
167 			WinSetWindowPos( pSysObj->mhWndChild, 0,
168 							 0, 0,
169 							 (short)SHORT1FROMMP( nMP2 ), (short)SHORT2FROMMP( nMP2 ),
170 							 SWP_SIZE | SWP_MOVE );
171 			bDef = FALSE;
172 			}
173 			break;
174 
175 		case WM_CREATE:
176 			{
177 			// Window-Instanz am Windowhandle speichern
178 			CREATESTRUCT* pStruct = (CREATESTRUCT*)nMP2;
179 			pSysObj = (Os2SalObject*)pStruct->pPresParams;
180 			SetSalObjWindowPtr( hWnd, pSysObj );
181 			bDef = FALSE;
182 			}
183 			break;
184 	}
185 
186 	if ( bDef )
187 		nRet = WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 );
188 	return nRet;
189 }
190 
191 // -----------------------------------------------------------------------
192 
193 MRESULT EXPENTRY SalSysObjChildWndProc( HWND hWnd, ULONG nMsg,
194 										MPARAM nMP1, MPARAM nMP2 )
195 {
196 	MRESULT 	nRet = 0;
197 	int 		bDef = TRUE;
198 
199 	debug_printf( "SalSysObjChildWndProc hWnd 0x%x nMsg %d\n", hWnd, nMsg);
200 
201 	switch( nMsg )
202 	{
203 		case WM_ERASEBACKGROUND:
204 			// Wegen PlugIn's loeschen wir erstmal den Hintergrund
205 /*
206 			nRet = (MRESULT)FALSE;
207 			bDef = FALSE;
208 */
209 			break;
210 		case WM_PAINT:
211 			{
212 			HPS 	hPS;
213 			RECTL	aRect;
214 			hPS = WinBeginPaint( hWnd, NULLHANDLE, &aRect );
215 			WinEndPaint( hPS );
216 			bDef = FALSE;
217 			}
218 			break;
219 	}
220 
221 	if ( bDef )
222 		nRet = WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 );
223 	return nRet;
224 }
225 
226 // -----------------------------------------------------------------------
227 
228 MRESULT EXPENTRY SalSysObjClipWndProc( HWND hWnd, ULONG nMsg,
229 									   MPARAM nMP1, MPARAM nMP2 )
230 {
231 	MRESULT 	nRet = 0;
232 	int 		bDef = TRUE;
233 
234 	debug_printf( "SalSysObjClipWndProc hWnd 0x%x nMsg %d\n", hWnd, nMsg);
235 
236 	switch( nMsg )
237 	{
238 		case WM_MOUSEMOVE:
239 		case WM_BUTTON1DOWN:
240 		case WM_BUTTON2DOWN:
241 		case WM_BUTTON3DOWN:
242 		case WM_BUTTON1DBLCLK:
243 		case WM_BUTTON2DBLCLK:
244 		case WM_BUTTON3DBLCLK:
245 		case WM_BUTTON1UP:
246 		case WM_BUTTON2UP:
247 		case WM_BUTTON3UP:
248 			{
249 			// Alle Events an den Frame weiterreichen, da diese Bereiche
250 			// dem Frame gehoeren. Dazu muessen die Mouse-Koordinaaten
251 			// entsprechend umgerechnet werden
252 			HWND hWndParent = WinQueryWindow( hWnd, QW_PARENT ); // ergibt SysChild-Fenster
253 			hWndParent = WinQueryWindow( hWndParent, QW_PARENT );
254 			short nX = (short)SHORT1FROMMP( nMP1 );
255 			short nY = (short)SHORT2FROMMP( nMP1 );
256 			POINTL aPos;
257 			aPos.x = nX;
258 			aPos.y = nY;
259 			WinMapWindowPoints( hWnd, hWndParent, &aPos, 1 );
260 			nMP1 = MPFROM2SHORT( (short)aPos.x, (short)aPos.y );
261 			bDef = FALSE;
262 			nRet = WinSendMsg( hWndParent, nMsg, nMP1, nMP2 );
263 			}
264 			break;
265 
266 		case WM_HITTEST:
267 			// Damit im disablten Zustand die MouseKlicks immer noch
268 			// an den Frame geschickt werden
269 			// Dieser Code reicht leider nicht aus, deshalb wir unter
270 			// OS2 immer das Child-Fenster disablen, im Gegensatz
271 			// zu Windows, wo immer der Parent disablte wird, da
272 			// sich das Fenster evtl. anders Darstellen koennte,
273 			// wenn es disablte wird. Da dieser Fall uns bisher
274 			// nicht bekannt ist, ignorieren wir das.
275 			nRet = HT_NORMAL;
276 			bDef = FALSE;
277 			break;
278 
279 		case WM_ERASEBACKGROUND:
280 			nRet = (MRESULT)FALSE;
281 			bDef = FALSE;
282 			break;
283 		case WM_PAINT:
284 			{
285 			HPS 	hPS;
286 			RECTL	aRect;
287 			hPS = WinBeginPaint( hWnd, NULLHANDLE, &aRect );
288 			WinEndPaint( hPS );
289 			bDef = FALSE;
290 			}
291 			break;
292 	}
293 
294 	if ( bDef )
295 		nRet = WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 );
296 	return nRet;
297 }
298 
299 // =======================================================================
300 
301 void ImplDestroyAllClipWindows( HWND hWndLast )
302 {
303 	if ( hWndLast == HWND_TOP )
304 		return;
305 
306 	HWND hWndPrev;
307 	while ( hWndLast )
308 	{
309 		hWndPrev = WinQueryWindow( hWndLast, QW_PREV );
310 		WinDestroyWindow( hWndLast );
311 		hWndLast = hWndPrev;
312 	}
313 }
314 
315 // =======================================================================
316 
317 SalObject* ImplSalCreateObject( Os2SalInstance* pInst, Os2SalFrame* pParent )
318 {
319 	SalData* pSalData = GetSalData();
320 
321 	if ( !pSalData->mbObjClassInit )
322 	{
323 		if ( WinRegisterClass( pSalData->mhAB, (PSZ)SAL_OBJECT_CLASSNAME,
324 							   (PFNWP)SalSysObjWndProc, CS_MOVENOTIFY,
325 							   SAL_OBJECT_WNDEXTRA ) )
326 		{
327 			if ( WinRegisterClass( pSalData->mhAB, (PSZ)SAL_OBJECT_CLIPCLASSNAME,
328 								   (PFNWP)SalSysObjClipWndProc, CS_HITTEST | CS_MOVENOTIFY, 0 ) )
329 			{
330 				if ( WinRegisterClass( pSalData->mhAB, (PSZ)SAL_OBJECT_CHILDCLASSNAME,
331 									   (PFNWP)SalSysObjChildWndProc, CS_HITTEST | CS_MOVENOTIFY, 32 ) )
332 					pSalData->mbObjClassInit = TRUE;
333 			}
334 		}
335 	}
336 
337 	if ( pSalData->mbObjClassInit )
338 	{
339 		Os2SalObject* pObject = new Os2SalObject;
340 		HWND hWnd = WinCreateWindow( pParent->mhWndClient, SAL_OBJECT_CLASSNAME, "",
341 									 0,
342 									 0, 0, 0, 0,
343 									 pParent->mhWndClient, HWND_TOP,
344 									 0, NULL, (void*)pObject );
345 		HWND hWndChild = WinCreateWindow( hWnd, SAL_OBJECT_CHILDCLASSNAME, "",
346 										  WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE,
347 										  0, 0, 0, 0,
348 										  hWnd, HWND_TOP,
349 										  0, NULL, NULL );
350 
351 		if ( !hWndChild )
352 		{
353 			if ( hWnd )
354 				WinDestroyWindow( hWnd );
355 			delete pObject;
356 			return NULL;
357 		}
358 
359 		if ( hWnd )
360 		{
361         debug_printf("ImplSalCreateObject hWndChild %x\n", hWndChild);
362         debug_printf("ImplSalCreateObject hWnd %x\n", hWnd);
363 			pObject->mhWnd = hWnd;
364 			pObject->mhWndChild = hWndChild;
365 			pObject->maSysData.hWnd = hWndChild;
366 			return pObject;
367 		}
368 	}
369 
370 	return NULL;
371 }
372 
373 // =======================================================================
374 
375 long ImplSalObjCallbackDummy( void*, SalObject*, USHORT, const void* )
376 {
377 	return 0;
378 }
379 
380 // =======================================================================
381 
382 Os2SalObject::Os2SalObject()
383 {
384 	SalData* pSalData = GetSalData();
385 
386 	mhLastClipWnd		= HWND_TOP;
387 
388 	mhWnd				= 0;
389 	mhWndChild 		= 0;
390 	mhLastFocusWnd 	= 0;
391 	maSysData.nSize	= sizeof( SystemEnvData );
392 	mnHeight			= 0;
393 	mpInst 			= NULL;
394 	mpProc 			= ImplSalObjCallbackDummy;
395 
396 	// Hook installieren, wenn es das erste Os2SalObject ist
397 	if ( !pSalData->mpFirstObject )
398 	{
399 		WinSetHook( pSalData->mhAB, pSalData->mhMQ,
400 					HK_INPUT, (PFN)SalSysMsgProc, (HMODULE)0 );
401 	}
402 
403 	// Insert object in objectlist
404 	mpNextObject = pSalData->mpFirstObject;
405 	pSalData->mpFirstObject = this;
406 }
407 
408 // -----------------------------------------------------------------------
409 
410 Os2SalObject::~Os2SalObject()
411 {
412 	SalData* pSalData = GetSalData();
413 
414 	// remove frame from framelist
415 	if ( this == pSalData->mpFirstObject )
416 	{
417 		pSalData->mpFirstObject = mpNextObject;
418 
419 		// Wenn letztes Os2SalObject, dann Hook wieder entfernen
420 		if ( !pSalData->mpFirstObject )
421 		{
422 			WinReleaseHook( pSalData->mhAB, pSalData->mhMQ,
423 							HK_INPUT, (PFN)SalSysMsgProc, (HMODULE)0 );
424 		}
425 	}
426 	else
427 	{
428 		Os2SalObject* pTempObject = pSalData->mpFirstObject;
429 		while ( pTempObject->mpNextObject != this )
430 			pTempObject = pTempObject->mpNextObject;
431 
432 		pTempObject->mpNextObject = mpNextObject;
433 	}
434 
435 	// Cache-Daten zerstoeren
436 	ImplDestroyAllClipWindows( mhLastClipWnd );
437 
438 	if ( mhWndChild )
439 		WinDestroyWindow( mhWndChild );
440 	if ( mhWnd )
441 		WinDestroyWindow( mhWnd );
442 }
443 
444 // -----------------------------------------------------------------------
445 
446 void Os2SalObject::ResetClipRegion()
447 {
448 	ImplDestroyAllClipWindows( mhLastClipWnd );
449 	mhLastClipWnd = HWND_TOP;
450 }
451 
452 // -----------------------------------------------------------------------
453 
454 USHORT Os2SalObject::GetClipRegionType()
455 {
456 	return SAL_OBJECT_CLIP_EXCLUDERECTS;
457 }
458 
459 // -----------------------------------------------------------------------
460 
461 void Os2SalObject::BeginSetClipRegion( ULONG nRectCount )
462 {
463 	mhOldLastClipWnd = mhLastClipWnd;
464 }
465 
466 // -----------------------------------------------------------------------
467 
468 void Os2SalObject::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
469 {
470 	HWND hClipWnd = WinCreateWindow( mhWnd, SAL_OBJECT_CLIPCLASSNAME, "",
471 									 WS_VISIBLE,
472 									 nX, mnHeight-(nY+nHeight), nWidth, nHeight,
473 									 mhWnd, mhLastClipWnd,
474 									 0, NULL, NULL );
475         debug_printf("Os2SalObject::UnionClipRegion hClipWnd %x\n", hClipWnd);
476 	mhLastClipWnd = hClipWnd;
477 }
478 
479 // -----------------------------------------------------------------------
480 
481 void Os2SalObject::EndSetClipRegion()
482 {
483 	ImplDestroyAllClipWindows( mhOldLastClipWnd );
484 }
485 
486 // -----------------------------------------------------------------------
487 
488 void Os2SalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight )
489 {
490 	ULONG  nStyle = 0;
491 	BOOL   bVisible = WinIsWindowVisible( mhWnd );
492 	if ( bVisible )
493 	{
494 		WinShowWindow( mhWnd, FALSE );
495 		nStyle |= SWP_SHOW;
496 	}
497 	SWP aParentSWP;
498 	WinQueryWindowPos( WinQueryWindow( mhWnd, QW_PARENT ), &aParentSWP );
499 	WinSetWindowPos( mhWnd, 0, nX, aParentSWP.cy-(nY+nHeight), nWidth, nHeight,
500 					 SWP_MOVE | SWP_SIZE | nStyle );
501 }
502 
503 // -----------------------------------------------------------------------
504 
505 void Os2SalObject::Show( BOOL bVisible )
506 {
507 	WinShowWindow( mhWnd, bVisible );
508 }
509 
510 // -----------------------------------------------------------------------
511 
512 void Os2SalObject::Enable( BOOL bEnable )
513 {
514 	// Im Gegensatz zu Windows disablen wir das Childfenster,
515 	// da ansonsten unser Clippen nicht mehr funktioniert, da
516 	// wir keine Events mehr bekommen. Dadurch kann sich evtl.
517 	// das Fenster anders darstellen, was wir eigentlich nicht
518 	// wollen. Aber da uns bisher kein Fall bekannt ist,
519 	// ignorieren wir dies. Ansonsten muss ein Fenster dazwischen
520 	// gezogen werden oder getestet werden, wie wir die
521 	// Maustransparenz erreichen, wenn mhWnd
522 	// disablte wird.
523 	WinEnableWindow( mhWndChild, bEnable );
524 }
525 
526 // -----------------------------------------------------------------------
527 
528 void Os2SalObject::GrabFocus()
529 {
530 	if ( mhLastFocusWnd &&
531 		 WinIsWindow( GetSalData()->mhAB, mhLastFocusWnd ) &&
532 		 ImplIsSysWindowOrChild( mhWndChild, mhLastFocusWnd ) )
533 		WinSetFocus( HWND_DESKTOP, mhLastFocusWnd );
534 	else
535 		WinSetFocus( HWND_DESKTOP, mhWndChild );
536 }
537 
538 // -----------------------------------------------------------------------
539 
540 void Os2SalObject::SetBackground()
541 {
542 }
543 
544 // -----------------------------------------------------------------------
545 
546 void Os2SalObject::SetBackground( SalColor nSalColor )
547 {
548 }
549 
550 // -----------------------------------------------------------------------
551 
552 const SystemChildData* Os2SalObject::GetSystemData() const
553 {
554 	return &maSysData;
555 }
556 
557 // -----------------------------------------------------------------------
558 #if 0
559 void Os2SalObject::SetCallback( void* pInst, SALOBJECTPROC pProc )
560 {
561 	mpInst = pInst;
562 	if ( pProc )
563 		mpProc = pProc;
564 	else
565 		mpProc = ImplSalObjCallbackDummy;
566 }
567 #endif
568 
569 // -----------------------------------------------------------------------
570 
571 void Os2SalObject::InterceptChildWindowKeyDown( sal_Bool /*bIntercept*/ )
572 {
573 }
574 
575