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