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