xref: /trunk/main/vcl/os2/source/window/salobj.cxx (revision 9f62ea84a806e17e6f2bbff75724a7257a0eb5d9)
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