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