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