xref: /trunk/main/vcl/os2/source/window/salobj.cxx (revision dcefce6c)
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 
ImplIsSysWindowOrChild(HWND hWndParent,HWND hWndChild)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 
ImplFindOs2SalObject(HWND hWndChild)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 
SalSysMsgProc(HAB,QMSG * pMsg,ULONG)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 
SalSysObjWndProc(HWND hWnd,ULONG nMsg,MPARAM nMP1,MPARAM nMP2)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 
SalSysObjChildWndProc(HWND hWnd,ULONG nMsg,MPARAM nMP1,MPARAM nMP2)195 MRESULT EXPENTRY SalSysObjChildWndProc( HWND hWnd, ULONG nMsg,
196 										MPARAM nMP1, MPARAM nMP2 )
197 {
198 	MRESULT 	nRet = 0;
199 	int 		bDef = TRUE;
200 
201 #if OSL_DEBUG_LEVEL>0
202 	debug_printf( "SalSysObjChildWndProc hWnd 0x%x nMsg %d\n", hWnd, nMsg);
203 #endif
204 
205 	switch( nMsg )
206 	{
207 		case WM_ERASEBACKGROUND:
208 			// Wegen PlugIn's loeschen wir erstmal den Hintergrund
209 /*
210 			nRet = (MRESULT)FALSE;
211 			bDef = FALSE;
212 */
213 			break;
214 		case WM_PAINT:
215 			{
216 			HPS 	hPS;
217 			RECTL	aRect;
218 			hPS = WinBeginPaint( hWnd, NULLHANDLE, &aRect );
219 			WinEndPaint( hPS );
220 			bDef = FALSE;
221 			}
222 			break;
223 	}
224 
225 	if ( bDef )
226 		nRet = WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 );
227 	return nRet;
228 }
229 
230 // -----------------------------------------------------------------------
231 
SalSysObjClipWndProc(HWND hWnd,ULONG nMsg,MPARAM nMP1,MPARAM nMP2)232 MRESULT EXPENTRY SalSysObjClipWndProc( HWND hWnd, ULONG nMsg,
233 									   MPARAM nMP1, MPARAM nMP2 )
234 {
235 	MRESULT 	nRet = 0;
236 	int 		bDef = TRUE;
237 
238 #if OSL_DEBUG_LEVEL>0
239 	debug_printf( "SalSysObjClipWndProc hWnd 0x%x nMsg %d\n", hWnd, nMsg);
240 #endif
241 
242 	switch( nMsg )
243 	{
244 		case WM_MOUSEMOVE:
245 		case WM_BUTTON1DOWN:
246 		case WM_BUTTON2DOWN:
247 		case WM_BUTTON3DOWN:
248 		case WM_BUTTON1DBLCLK:
249 		case WM_BUTTON2DBLCLK:
250 		case WM_BUTTON3DBLCLK:
251 		case WM_BUTTON1UP:
252 		case WM_BUTTON2UP:
253 		case WM_BUTTON3UP:
254 			{
255 			// Alle Events an den Frame weiterreichen, da diese Bereiche
256 			// dem Frame gehoeren. Dazu muessen die Mouse-Koordinaaten
257 			// entsprechend umgerechnet werden
258 			HWND hWndParent = WinQueryWindow( hWnd, QW_PARENT ); // ergibt SysChild-Fenster
259 			hWndParent = WinQueryWindow( hWndParent, QW_PARENT );
260 			short nX = (short)SHORT1FROMMP( nMP1 );
261 			short nY = (short)SHORT2FROMMP( nMP1 );
262 			POINTL aPos;
263 			aPos.x = nX;
264 			aPos.y = nY;
265 			WinMapWindowPoints( hWnd, hWndParent, &aPos, 1 );
266 			nMP1 = MPFROM2SHORT( (short)aPos.x, (short)aPos.y );
267 			bDef = FALSE;
268 			nRet = WinSendMsg( hWndParent, nMsg, nMP1, nMP2 );
269 			}
270 			break;
271 
272 		case WM_HITTEST:
273 			// Damit im disablten Zustand die MouseKlicks immer noch
274 			// an den Frame geschickt werden
275 			// Dieser Code reicht leider nicht aus, deshalb wir unter
276 			// OS2 immer das Child-Fenster disablen, im Gegensatz
277 			// zu Windows, wo immer der Parent disablte wird, da
278 			// sich das Fenster evtl. anders Darstellen koennte,
279 			// wenn es disablte wird. Da dieser Fall uns bisher
280 			// nicht bekannt ist, ignorieren wir das.
281 			nRet = HT_NORMAL;
282 			bDef = FALSE;
283 			break;
284 
285 		case WM_ERASEBACKGROUND:
286 			nRet = (MRESULT)FALSE;
287 			bDef = FALSE;
288 			break;
289 		case WM_PAINT:
290 			{
291 			HPS 	hPS;
292 			RECTL	aRect;
293 			hPS = WinBeginPaint( hWnd, NULLHANDLE, &aRect );
294 			WinEndPaint( hPS );
295 			bDef = FALSE;
296 			}
297 			break;
298 	}
299 
300 	if ( bDef )
301 		nRet = WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 );
302 	return nRet;
303 }
304 
305 // =======================================================================
306 
ImplDestroyAllClipWindows(HWND hWndLast)307 void ImplDestroyAllClipWindows( HWND hWndLast )
308 {
309 	if ( hWndLast == HWND_TOP )
310 		return;
311 
312 	HWND hWndPrev;
313 	while ( hWndLast )
314 	{
315 		hWndPrev = WinQueryWindow( hWndLast, QW_PREV );
316 		WinDestroyWindow( hWndLast );
317 		hWndLast = hWndPrev;
318 	}
319 }
320 
321 // =======================================================================
322 
ImplSalCreateObject(Os2SalInstance * pInst,Os2SalFrame * pParent)323 SalObject* ImplSalCreateObject( Os2SalInstance* pInst, Os2SalFrame* pParent )
324 {
325 	SalData* pSalData = GetSalData();
326 
327 	if ( !pSalData->mbObjClassInit )
328 	{
329 		if ( WinRegisterClass( pSalData->mhAB, (PSZ)SAL_OBJECT_CLASSNAME,
330 							   (PFNWP)SalSysObjWndProc, CS_MOVENOTIFY,
331 							   SAL_OBJECT_WNDEXTRA ) )
332 		{
333 			if ( WinRegisterClass( pSalData->mhAB, (PSZ)SAL_OBJECT_CLIPCLASSNAME,
334 								   (PFNWP)SalSysObjClipWndProc, CS_HITTEST | CS_MOVENOTIFY, 0 ) )
335 			{
336 				if ( WinRegisterClass( pSalData->mhAB, (PSZ)SAL_OBJECT_CHILDCLASSNAME,
337 									   (PFNWP)SalSysObjChildWndProc, CS_HITTEST | CS_MOVENOTIFY, 32 ) )
338 					pSalData->mbObjClassInit = TRUE;
339 			}
340 		}
341 	}
342 
343 	if ( pSalData->mbObjClassInit )
344 	{
345 		Os2SalObject* pObject = new Os2SalObject;
346 		HWND hWnd = WinCreateWindow( pParent->mhWndClient, SAL_OBJECT_CLASSNAME, "",
347 									 0,
348 									 0, 0, 0, 0,
349 									 pParent->mhWndClient, HWND_TOP,
350 									 0, NULL, (void*)pObject );
351 		HWND hWndChild = WinCreateWindow( hWnd, SAL_OBJECT_CHILDCLASSNAME, "",
352 										  WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE,
353 										  0, 0, 0, 0,
354 										  hWnd, HWND_TOP,
355 										  0, NULL, NULL );
356 
357 		if ( !hWndChild )
358 		{
359 			if ( hWnd )
360 				WinDestroyWindow( hWnd );
361 			delete pObject;
362 			return NULL;
363 		}
364 
365 		if ( hWnd )
366 		{
367 #if OSL_DEBUG_LEVEL>0
368         debug_printf("ImplSalCreateObject hWndChild %x\n", hWndChild);
369         debug_printf("ImplSalCreateObject hWnd %x\n", hWnd);
370 #endif
371 			pObject->mhWnd = hWnd;
372 			pObject->mhWndChild = hWndChild;
373 			pObject->maSysData.hWnd = hWndChild;
374 			return pObject;
375 		}
376 	}
377 
378 	return NULL;
379 }
380 
381 // =======================================================================
382 
ImplSalObjCallbackDummy(void *,SalObject *,USHORT,const void *)383 long ImplSalObjCallbackDummy( void*, SalObject*, USHORT, const void* )
384 {
385 	return 0;
386 }
387 
388 // =======================================================================
389 
Os2SalObject()390 Os2SalObject::Os2SalObject()
391 {
392 	SalData* pSalData = GetSalData();
393 
394 	mhLastClipWnd		= HWND_TOP;
395 
396 	mhWnd				= 0;
397 	mhWndChild 		= 0;
398 	mhLastFocusWnd 	= 0;
399 	maSysData.nSize	= sizeof( SystemEnvData );
400 	mnHeight			= 0;
401 	mpInst 			= NULL;
402 	mpProc 			= ImplSalObjCallbackDummy;
403 
404 	// Hook installieren, wenn es das erste Os2SalObject ist
405 	if ( !pSalData->mpFirstObject )
406 	{
407 		WinSetHook( pSalData->mhAB, pSalData->mhMQ,
408 					HK_INPUT, (PFN)SalSysMsgProc, (HMODULE)0 );
409 	}
410 
411 	// Insert object in objectlist
412 	mpNextObject = pSalData->mpFirstObject;
413 	pSalData->mpFirstObject = this;
414 }
415 
416 // -----------------------------------------------------------------------
417 
~Os2SalObject()418 Os2SalObject::~Os2SalObject()
419 {
420 	SalData* pSalData = GetSalData();
421 
422 	// remove frame from framelist
423 	if ( this == pSalData->mpFirstObject )
424 	{
425 		pSalData->mpFirstObject = mpNextObject;
426 
427 		// Wenn letztes Os2SalObject, dann Hook wieder entfernen
428 		if ( !pSalData->mpFirstObject )
429 		{
430 			WinReleaseHook( pSalData->mhAB, pSalData->mhMQ,
431 							HK_INPUT, (PFN)SalSysMsgProc, (HMODULE)0 );
432 		}
433 	}
434 	else
435 	{
436 		Os2SalObject* pTempObject = pSalData->mpFirstObject;
437 		while ( pTempObject->mpNextObject != this )
438 			pTempObject = pTempObject->mpNextObject;
439 
440 		pTempObject->mpNextObject = mpNextObject;
441 	}
442 
443 	// Cache-Daten zerstoeren
444 	ImplDestroyAllClipWindows( mhLastClipWnd );
445 
446 	if ( mhWndChild )
447 		WinDestroyWindow( mhWndChild );
448 	if ( mhWnd )
449 		WinDestroyWindow( mhWnd );
450 }
451 
452 // -----------------------------------------------------------------------
453 
ResetClipRegion()454 void Os2SalObject::ResetClipRegion()
455 {
456 	ImplDestroyAllClipWindows( mhLastClipWnd );
457 	mhLastClipWnd = HWND_TOP;
458 }
459 
460 // -----------------------------------------------------------------------
461 
GetClipRegionType()462 USHORT Os2SalObject::GetClipRegionType()
463 {
464 	return SAL_OBJECT_CLIP_EXCLUDERECTS;
465 }
466 
467 // -----------------------------------------------------------------------
468 
BeginSetClipRegion(ULONG nRectCount)469 void Os2SalObject::BeginSetClipRegion( ULONG nRectCount )
470 {
471 	mhOldLastClipWnd = mhLastClipWnd;
472 }
473 
474 // -----------------------------------------------------------------------
475 
UnionClipRegion(long nX,long nY,long nWidth,long nHeight)476 void Os2SalObject::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
477 {
478 	HWND hClipWnd = WinCreateWindow( mhWnd, SAL_OBJECT_CLIPCLASSNAME, "",
479 									 WS_VISIBLE,
480 									 nX, mnHeight-(nY+nHeight), nWidth, nHeight,
481 									 mhWnd, mhLastClipWnd,
482 									 0, NULL, NULL );
483 #if OSL_DEBUG_LEVEL>0
484         debug_printf("Os2SalObject::UnionClipRegion hClipWnd %x\n", hClipWnd);
485 #endif
486 	mhLastClipWnd = hClipWnd;
487 }
488 
489 // -----------------------------------------------------------------------
490 
EndSetClipRegion()491 void Os2SalObject::EndSetClipRegion()
492 {
493 	ImplDestroyAllClipWindows( mhOldLastClipWnd );
494 }
495 
496 // -----------------------------------------------------------------------
497 
SetPosSize(long nX,long nY,long nWidth,long nHeight)498 void Os2SalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight )
499 {
500 	ULONG  nStyle = 0;
501 	sal_Bool   bVisible = WinIsWindowVisible( mhWnd );
502 	if ( bVisible )
503 	{
504 		WinShowWindow( mhWnd, FALSE );
505 		nStyle |= SWP_SHOW;
506 	}
507 	SWP aParentSWP;
508 	WinQueryWindowPos( WinQueryWindow( mhWnd, QW_PARENT ), &aParentSWP );
509 	WinSetWindowPos( mhWnd, 0, nX, aParentSWP.cy-(nY+nHeight), nWidth, nHeight,
510 					 SWP_MOVE | SWP_SIZE | nStyle );
511 }
512 
513 // -----------------------------------------------------------------------
514 
Show(sal_Bool bVisible)515 void Os2SalObject::Show( sal_Bool bVisible )
516 {
517 	WinShowWindow( mhWnd, bVisible );
518 }
519 
520 // -----------------------------------------------------------------------
521 
Enable(sal_Bool bEnable)522 void Os2SalObject::Enable( sal_Bool bEnable )
523 {
524 	// Im Gegensatz zu Windows disablen wir das Childfenster,
525 	// da ansonsten unser Clippen nicht mehr funktioniert, da
526 	// wir keine Events mehr bekommen. Dadurch kann sich evtl.
527 	// das Fenster anders darstellen, was wir eigentlich nicht
528 	// wollen. Aber da uns bisher kein Fall bekannt ist,
529 	// ignorieren wir dies. Ansonsten muss ein Fenster dazwischen
530 	// gezogen werden oder getestet werden, wie wir die
531 	// Maustransparenz erreichen, wenn mhWnd
532 	// disablte wird.
533 	WinEnableWindow( mhWndChild, bEnable );
534 }
535 
536 // -----------------------------------------------------------------------
537 
GrabFocus()538 void Os2SalObject::GrabFocus()
539 {
540 	if ( mhLastFocusWnd &&
541 		 WinIsWindow( GetSalData()->mhAB, mhLastFocusWnd ) &&
542 		 ImplIsSysWindowOrChild( mhWndChild, mhLastFocusWnd ) )
543 		WinSetFocus( HWND_DESKTOP, mhLastFocusWnd );
544 	else
545 		WinSetFocus( HWND_DESKTOP, mhWndChild );
546 }
547 
548 // -----------------------------------------------------------------------
549 
SetBackground()550 void Os2SalObject::SetBackground()
551 {
552 }
553 
554 // -----------------------------------------------------------------------
555 
SetBackground(SalColor nSalColor)556 void Os2SalObject::SetBackground( SalColor nSalColor )
557 {
558 }
559 
560 // -----------------------------------------------------------------------
561 
GetSystemData() const562 const SystemChildData* Os2SalObject::GetSystemData() const
563 {
564 	return &maSysData;
565 }
566 
567 // -----------------------------------------------------------------------
568 #if 0
569 void Os2SalObject::SetCallback( void* pInst, SALOBJECTPROC pProc )
570 {
571 	mpInst = pInst;
572 	if ( pProc )
573 		mpProc = pProc;
574 	else
575 		mpProc = ImplSalObjCallbackDummy;
576 }
577 #endif
578 
579 // -----------------------------------------------------------------------
580 
InterceptChildWindowKeyDown(sal_Bool)581 void Os2SalObject::InterceptChildWindowKeyDown( sal_Bool /*bIntercept*/ )
582 {
583 }
584 
585