xref: /AOO41X/main/vcl/os2/source/window/salobj.cxx (revision 8809db7a87f97847b57a57f4cd2b0104b2b83182)
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