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