xref: /trunk/main/vcl/unx/generic/window/salobj.cxx (revision c82f2877)
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