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