xref: /AOO41X/main/vcl/unx/generic/window/salobj.cxx (revision 5979ef3c542ac870a02043decc543300c0ec3dfb)
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 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 
31 #if OSL_DEBUG_LEVEL > 1
32 #include <stdio.h>
33 #endif
34 #include <tools/debug.hxx>
35 
36 #include <vcl/keycodes.hxx>
37 
38 #include <tools/prex.h>
39 #include <X11/Xlib.h>
40 #include <X11/extensions/shape.h>
41 #include <tools/postx.h>
42 
43 #include <unx/salunx.h>
44 #include <unx/salstd.hxx>
45 #include <unx/saldata.hxx>
46 #include <unx/salinst.h>
47 #include <unx/saldisp.hxx>
48 #include <unx/salframe.h>
49 #include <unx/salobj.h>
50 
51 #include <salwtype.hxx>
52 
53 
54 // =======================================================================
55 // SalInstance member to create and destroy a SalObject
56 
57 SalObject* X11SalInstance::CreateObject( SalFrame* pParent, SystemWindowData* pWindowData, sal_Bool bShow )
58 {
59     return X11SalObject::CreateObject( pParent, pWindowData, bShow );
60 }
61 
62 X11SalObject* X11SalObject::CreateObject( SalFrame* pParent, SystemWindowData* pWindowData, sal_Bool bShow )
63 {
64     int error_base, event_base;
65     X11SalObject*       pObject  = new X11SalObject();
66     SystemChildData*    pObjData = const_cast<SystemChildData*>(pObject->GetSystemData());
67 
68     if ( ! XShapeQueryExtension( (Display*)pObjData->pDisplay,
69                                   &event_base, &error_base ) )
70     {
71         delete pObject;
72         return NULL;
73     }
74 
75     pObject->mpParent = pParent;
76 
77     SalDisplay* pSalDisp        = GetX11SalData()->GetDisplay();
78     const SystemEnvData* pEnv   = pParent->GetSystemData();
79     Display* pDisp              = pSalDisp->GetDisplay();
80     XLIB_Window aObjectParent   = (XLIB_Window)pEnv->aWindow;
81 
82     // find out on which screen that window is
83     XWindowAttributes aParentAttr;
84     XGetWindowAttributes( pDisp, aObjectParent, &aParentAttr );
85     int nScreen = XScreenNumberOfScreen( aParentAttr.screen );
86     Visual* pVisual = (pWindowData && pWindowData->pVisual) ?
87                       (Visual*)pWindowData->pVisual :
88                       pSalDisp->GetVisual( nScreen ).GetVisual();
89     // get visual info
90     VisualID aVisID = XVisualIDFromVisual( pVisual );
91     XVisualInfo aTemplate;
92     aTemplate.visualid = aVisID;
93     int nVisuals = 0;
94     XVisualInfo* pInfos = XGetVisualInfo( pDisp, VisualIDMask, &aTemplate, &nVisuals );
95     // only one VisualInfo structure can match the visual id
96     DBG_ASSERT( nVisuals == 1, "match count for visual id is not 1" );
97     unsigned int nDepth     = pInfos->depth;
98     XFree( pInfos );
99     XSetWindowAttributes aAttribs;
100     aAttribs.event_mask =   StructureNotifyMask
101                           | ButtonPressMask
102                           | ButtonReleaseMask
103                           | PointerMotionMask
104                           | EnterWindowMask
105                           | LeaveWindowMask
106                           | FocusChangeMask
107                           | ExposureMask
108                           ;
109 
110     pObject->maPrimary =
111         XCreateSimpleWindow( pDisp,
112                              aObjectParent,
113                              0, 0,
114                              1, 1, 0,
115                              pSalDisp->GetColormap( nScreen ).GetBlackPixel(),
116                              pSalDisp->GetColormap( nScreen ).GetWhitePixel()
117                              );
118     if( aVisID == pSalDisp->GetVisual( nScreen ).GetVisualId() )
119     {
120         pObject->maSecondary =
121             XCreateSimpleWindow( pDisp,
122                                  pObject->maPrimary,
123                                  0, 0,
124                                  1, 1, 0,
125                                  pSalDisp->GetColormap( nScreen ).GetBlackPixel(),
126                                  pSalDisp->GetColormap( nScreen ).GetWhitePixel()
127                                  );
128     }
129     else
130     {
131         #if OSL_DEBUG_LEVEL > 1
132         fprintf( stderr, "visual id of vcl %x, of visual %x\n",
133                  static_cast<unsigned int> (pSalDisp->GetVisual( nScreen ).GetVisualId()),
134                  static_cast<unsigned int> (aVisID) );
135         #endif
136         pSalDisp->GetXLib()->PushXErrorLevel( true );
137 
138         // create colormap for visual - there might not be one
139         pObject->maColormap = aAttribs.colormap = XCreateColormap(
140             pDisp,
141             pSalDisp->GetRootWindow( nScreen ),
142             pVisual,
143             AllocNone );
144 
145         pObject->maSecondary =
146             XCreateWindow( pDisp,
147                            pSalDisp->GetRootWindow( nScreen ),
148                            0, 0,
149                            1, 1, 0,
150                            nDepth, InputOutput,
151                            pVisual,
152                            CWEventMask|CWColormap, &aAttribs );
153         XSync( pDisp, False );
154         sal_Bool bWasXError = pSalDisp->GetXLib()->HasXErrorOccured();
155         pSalDisp->GetXLib()->PopXErrorLevel();
156         if( bWasXError )
157         {
158             pObject->maSecondary = None;
159             delete pObject;
160             return NULL;
161         }
162         XReparentWindow( pDisp, pObject->maSecondary, pObject->maPrimary, 0, 0 );
163     }
164 
165     pSalDisp->GetXLib()->PushXErrorLevel( true );
166     if( bShow ) {
167         XMapWindow( pDisp, pObject->maSecondary );
168         XMapWindow( pDisp, pObject->maPrimary );
169     }
170 
171     pObjData->pDisplay      = pDisp;
172     pObjData->aWindow       = pObject->maSecondary;
173     pObjData->pWidget       = NULL;
174     pObjData->pVisual       = pVisual;
175     pObjData->nDepth        = nDepth;
176     pObjData->aColormap     = aVisID == pSalDisp->GetVisual( nScreen ).GetVisualId() ?
177                               pSalDisp->GetColormap( nScreen ).GetXColormap() : None;
178     pObjData->pAppContext   = NULL;
179 
180     XSync(pDisp, False);
181     sal_Bool bWasXError = pSalDisp->GetXLib()->HasXErrorOccured();
182     pSalDisp->GetXLib()->PopXErrorLevel();
183     if( bWasXError )
184     {
185         delete pObject;
186         return NULL;
187     }
188 
189     return pObject;
190 }
191 
192 
193 void X11SalInstance::DestroyObject( SalObject* pObject )
194 {
195     delete pObject;
196 }
197 
198 
199 // ======================================================================
200 // SalClipRegion is a member of SalObject
201 // definition of SalClipRegion my be found in unx/inc/salobj.h
202 
203 
204 SalClipRegion::SalClipRegion()
205 {
206     ClipRectangleList = NULL;
207     numClipRectangles = 0;
208     maxClipRectangles = 0;
209     nClipRegionType   = SAL_OBJECT_CLIP_INCLUDERECTS;
210 }
211 
212 
213 SalClipRegion::~SalClipRegion()
214 {
215     if ( ClipRectangleList )
216         delete [] ClipRectangleList;
217 }
218 
219 
220 void
221 SalClipRegion::BeginSetClipRegion( sal_uLong nRects )
222 {
223     if (ClipRectangleList)
224         delete [] ClipRectangleList;
225 
226     ClipRectangleList = new XRectangle[nRects];
227     numClipRectangles = 0;
228     maxClipRectangles = nRects;
229 }
230 
231 
232 void
233 SalClipRegion::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
234 {
235     if ( nWidth && nHeight && (numClipRectangles < maxClipRectangles) )
236     {
237         XRectangle *aRect = ClipRectangleList + numClipRectangles;
238 
239         aRect->x     = (short) nX;
240         aRect->y     = (short) nY;
241         aRect->width = (unsigned short) nWidth;
242         aRect->height= (unsigned short) nHeight;
243 
244         numClipRectangles++;
245     }
246 }
247 
248 
249 // =======================================================================
250 // SalObject Implementation
251 
252 
253 X11SalObject::X11SalObject()
254 {
255     maSystemChildData.nSize     = sizeof( SystemChildData );
256     maSystemChildData.pDisplay  = GetX11SalData()->GetDisplay()->GetDisplay();
257     maSystemChildData.aWindow       = None;
258     maSystemChildData.pSalFrame = 0;
259     maSystemChildData.pWidget       = 0;
260     maSystemChildData.pVisual       = 0;
261     maSystemChildData.nDepth        = 0;
262     maSystemChildData.aColormap = 0;
263     maSystemChildData.pAppContext   = NULL;
264     maSystemChildData.aShellWindow  = 0;
265     maSystemChildData.pShellWidget  = NULL;
266     maPrimary                       = 0;
267     maSecondary                     = 0;
268     maColormap                      = 0;
269 
270     std::list< SalObject* >& rObjects = GetX11SalData()->GetDisplay()->getSalObjects();
271     rObjects.push_back( this );
272 }
273 
274 
275 X11SalObject::~X11SalObject()
276 {
277     std::list< SalObject* >& rObjects = GetX11SalData()->GetDisplay()->getSalObjects();
278     rObjects.remove( this );
279     SalDisplay* pSalDisp = GetX11SalData()->GetDisplay();
280     pSalDisp->GetXLib()->PushXErrorLevel( true );
281     if ( maSecondary )
282         XDestroyWindow( (Display*)maSystemChildData.pDisplay, maSecondary );
283     if ( maPrimary )
284         XDestroyWindow( (Display*)maSystemChildData.pDisplay, maPrimary );
285     if ( maColormap )
286         XFreeColormap((Display*)maSystemChildData.pDisplay, maColormap);
287     XSync( (Display*)maSystemChildData.pDisplay, False );
288     pSalDisp->GetXLib()->PopXErrorLevel();
289 }
290 
291 
292 void
293 X11SalObject::ResetClipRegion()
294 {
295     maClipRegion.ResetClipRegion();
296 
297     const int   dest_kind   = ShapeBounding;
298     const int   op          = ShapeSet;
299     const int   ordering    = YSorted;
300 
301     XWindowAttributes win_attrib;
302     XRectangle        win_size;
303 
304     XLIB_Window aShapeWindow = maPrimary;
305 
306     XGetWindowAttributes ( (Display*)maSystemChildData.pDisplay,
307                            aShapeWindow,
308                            &win_attrib );
309 
310     win_size.x      = 0;
311     win_size.y      = 0;
312     win_size.width  = win_attrib.width;
313     win_size.height = win_attrib.height;
314 
315     XShapeCombineRectangles ( (Display*)maSystemChildData.pDisplay,
316                               aShapeWindow,
317                               dest_kind,
318                               0, 0,             // x_off, y_off
319                               &win_size,        // list of rectangles
320                               1,                // number of rectangles
321                               op, ordering );
322 }
323 
324 
325 void
326 X11SalObject::BeginSetClipRegion( sal_uLong nRectCount )
327 {
328     maClipRegion.BeginSetClipRegion ( nRectCount );
329 }
330 
331 
332 void
333 X11SalObject::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
334 {
335     maClipRegion.UnionClipRegion ( nX, nY, nWidth, nHeight );
336 }
337 
338 
339 void
340 X11SalObject::EndSetClipRegion()
341 {
342     XRectangle *pRectangles = maClipRegion.EndSetClipRegion ();
343     const int   nType       = maClipRegion.GetClipRegionType();
344     const int   nRectangles = maClipRegion.GetRectangleCount();
345 
346     const int   dest_kind   = ShapeBounding;
347     const int   ordering    = YSorted;
348     int         op;
349 
350     switch ( nType )
351     {
352         case SAL_OBJECT_CLIP_INCLUDERECTS :
353             op = ShapeSet;
354             break;
355         case SAL_OBJECT_CLIP_EXCLUDERECTS :
356             op = ShapeSubtract;
357             break;
358         case SAL_OBJECT_CLIP_ABSOLUTE :
359             op = ShapeSet;
360             break;
361         default :
362             op = ShapeUnion;
363     }
364 
365     XLIB_Window aShapeWindow = maPrimary;
366 
367     XShapeCombineRectangles ( (Display*)maSystemChildData.pDisplay,
368                               aShapeWindow,
369                               dest_kind,
370                               0, 0, // x_off, y_off
371                               pRectangles,
372                               nRectangles,
373                               op, ordering );
374 }
375 
376 
377 sal_uInt16
378 X11SalObject::GetClipRegionType()
379 {
380     return maClipRegion.GetClipRegionType();
381 }
382 
383 // -----------------------------------------------------------------------
384 
385 void
386 X11SalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight )
387 {
388     if ( maPrimary && maSecondary && nWidth && nHeight )
389     {
390         XMoveResizeWindow( (Display*)maSystemChildData.pDisplay,
391                            maPrimary,
392                            nX, nY, nWidth, nHeight );
393         XMoveResizeWindow( (Display*)maSystemChildData.pDisplay,
394                            maSecondary,
395                            0, 0, nWidth, nHeight );
396     }
397 }
398 
399 
400 void
401 X11SalObject::Show( sal_Bool bVisible )
402 {
403     if  ( ! maSystemChildData.aWindow )
404         return;
405 
406     if ( bVisible ) {
407         XMapWindow( (Display*)maSystemChildData.pDisplay,
408                     maSecondary );
409         XMapWindow( (Display*)maSystemChildData.pDisplay,
410                     maPrimary );
411     } else {
412         XUnmapWindow( (Display*)maSystemChildData.pDisplay,
413                       maPrimary );
414         XUnmapWindow( (Display*)maSystemChildData.pDisplay,
415                       maSecondary );
416     }
417     mbVisible = bVisible;
418 }
419 
420 // -----------------------------------------------------------------------
421 
422 void X11SalObject::Enable( sal_Bool )
423 {
424 }
425 
426 // -----------------------------------------------------------------------
427 
428 void X11SalObject::GrabFocus()
429 {
430     if( mbVisible )
431         XSetInputFocus( (Display*)maSystemChildData.pDisplay,
432                         maSystemChildData.aWindow,
433                         RevertToNone,
434                         CurrentTime );
435 }
436 
437 // -----------------------------------------------------------------------
438 
439 void X11SalObject::SetBackground()
440 {
441 }
442 
443 // -----------------------------------------------------------------------
444 
445 void X11SalObject::SetBackground( SalColor )
446 {
447 }
448 
449 // -----------------------------------------------------------------------
450 
451 const SystemChildData* X11SalObject::GetSystemData() const
452 {
453     return &maSystemChildData;
454 }
455 
456 static sal_uInt16 sal_GetCode( int state )
457 {
458     sal_uInt16 nCode = 0;
459 
460     if( state & Button1Mask )
461         nCode |= MOUSE_LEFT;
462     if( state & Button2Mask )
463         nCode |= MOUSE_MIDDLE;
464     if( state & Button3Mask )
465         nCode |= MOUSE_RIGHT;
466 
467     if( state & ShiftMask )
468         nCode |= KEY_SHIFT;
469     if( state & ControlMask )
470         nCode |= KEY_MOD1;
471     if( state & Mod1Mask )
472         nCode |= KEY_MOD2;
473         if( state & Mod3Mask )
474                 nCode |= KEY_MOD3;
475 
476     return nCode;
477 }
478 
479 long X11SalObject::Dispatch( XEvent* pEvent )
480 {
481     std::list< SalObject* >& rObjects = GetX11SalData()->GetDisplay()->getSalObjects();
482 
483     for( std::list< SalObject* >::iterator it = rObjects.begin(); it != rObjects.end(); ++it )
484     {
485         X11SalObject* pObject = static_cast<X11SalObject*>(*it);
486         if( pEvent->xany.window == pObject->maPrimary ||
487             pEvent->xany.window == pObject->maSecondary )
488         {
489             if( pObject->IsMouseTransparent() && (
490                     pEvent->type == ButtonPress     ||
491                     pEvent->type == ButtonRelease   ||
492                     pEvent->type == EnterNotify     ||
493                     pEvent->type == LeaveNotify     ||
494                     pEvent->type == MotionNotify
495                     )
496                )
497             {
498                 SalMouseEvent aEvt;
499                 const SystemEnvData* pParentData = pObject->mpParent->GetSystemData();
500                 int dest_x, dest_y;
501                 XLIB_Window aChild = None;
502                 XTranslateCoordinates( pEvent->xbutton.display,
503                                        pEvent->xbutton.root,
504                                        pParentData->aWindow,
505                                        pEvent->xbutton.x_root,
506                                        pEvent->xbutton.y_root,
507                                        &dest_x, &dest_y,
508                                        &aChild );
509                 aEvt.mnX        = dest_x;
510                 aEvt.mnY        = dest_y;
511                 aEvt.mnTime     = pEvent->xbutton.time;
512                 aEvt.mnCode     = sal_GetCode( pEvent->xbutton.state );
513                 aEvt.mnButton   = 0;
514                 sal_uInt16 nEvent = 0;
515                 if( pEvent->type == ButtonPress ||
516                     pEvent->type == ButtonRelease )
517                 {
518                     switch( pEvent->xbutton.button )
519                     {
520                         case Button1: aEvt.mnButton = MOUSE_LEFT;break;
521                         case Button2: aEvt.mnButton = MOUSE_MIDDLE;break;
522                         case Button3: aEvt.mnButton = MOUSE_RIGHT;break;
523                     }
524                     nEvent = (pEvent->type == ButtonPress) ?
525                              SALEVENT_MOUSEBUTTONDOWN :
526                              SALEVENT_MOUSEBUTTONUP;
527                 }
528                 else if( pEvent->type == EnterNotify )
529                     nEvent = SALEVENT_MOUSELEAVE;
530                 else
531                     nEvent = SALEVENT_MOUSEMOVE;
532                 pObject->mpParent->CallCallback( nEvent, &aEvt );
533             }
534             else
535             {
536                 switch( pEvent->type )
537                 {
538                     case UnmapNotify:
539                     pObject->mbVisible = sal_False;
540                     return 1;
541                     case MapNotify:
542                     pObject->mbVisible = sal_True;
543                     return 1;
544                     case ButtonPress:
545                     pObject->CallCallback( SALOBJ_EVENT_TOTOP, NULL );
546                     return 1;
547                     case FocusIn:
548                     pObject->CallCallback( SALOBJ_EVENT_GETFOCUS, NULL );
549                     return 1;
550                     case FocusOut:
551                     pObject->CallCallback( SALOBJ_EVENT_LOSEFOCUS, NULL );
552                     return 1;
553                     default: break;
554                 }
555             }
556             return 0;
557         }
558     }
559     return 0;
560 }
561 
562 // -----------------------------------------------------------------------
563 
564 void X11SalObject::InterceptChildWindowKeyDown( sal_Bool /*bIntercept*/ )
565 {
566 }
567 
568