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