1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #if OSL_DEBUG_LEVEL > 1
25 #include <X11/Xutil.h>
26 #include <X11/extensions/shape.h>
29 #include <vcl/keycodes.hxx>
30 #include <vcl/event.hxx>
31 #include <sal/log.hxx>
33 #include <unx/salinst.h>
34 #include <unx/saldisp.hxx>
35 #include <unx/salobj.h>
37 #include <salframe.hxx>
38 #include <salwtype.hxx>
40 // SalInstance member to create and destroy a SalObject
42 SalObject
* X11SalInstance::CreateObject( SalFrame
* pParent
, SystemWindowData
* pWindowData
, bool bShow
)
44 return X11SalObject::CreateObject( pParent
, pWindowData
, bShow
);
47 X11SalObject
* X11SalObject::CreateObject( SalFrame
* pParent
, SystemWindowData
* pWindowData
, bool bShow
)
49 int error_base
, event_base
;
50 X11SalObject
* pObject
= new X11SalObject();
51 SystemEnvData
* pObjData
= const_cast<SystemEnvData
*>(pObject
->GetSystemData());
53 if ( ! XShapeQueryExtension( static_cast<Display
*>(pObjData
->pDisplay
),
54 &event_base
, &error_base
) )
60 pObject
->mpParent
= pParent
;
62 SalDisplay
* pSalDisp
= vcl_sal::getSalDisplay(GetGenericUnixSalData());
63 const SystemEnvData
* pEnv
= pParent
->GetSystemData();
64 Display
* pDisp
= pSalDisp
->GetDisplay();
65 ::Window aObjectParent
= static_cast<::Window
>(pEnv
->GetWindowHandle(pParent
));
66 pObject
->maParentWin
= aObjectParent
;
68 // find out on which screen that window is
69 XWindowAttributes aParentAttr
;
70 XGetWindowAttributes( pDisp
, aObjectParent
, &aParentAttr
);
71 SalX11Screen
nXScreen( XScreenNumberOfScreen( aParentAttr
.screen
) );
72 Visual
* pVisual
= (pWindowData
&& pWindowData
->pVisual
) ?
73 static_cast<Visual
*>(pWindowData
->pVisual
) :
74 pSalDisp
->GetVisual( nXScreen
).GetVisual();
76 VisualID aVisID
= XVisualIDFromVisual( pVisual
);
77 XVisualInfo aTemplate
;
78 aTemplate
.visualid
= aVisID
;
80 XVisualInfo
* pInfo
= XGetVisualInfo( pDisp
, VisualIDMask
, &aTemplate
, &nVisuals
);
81 // only one VisualInfo structure can match the visual id
82 SAL_WARN_IF( nVisuals
!= 1, "vcl", "match count for visual id is not 1" );
83 unsigned int nDepth
= pInfo
->depth
;
85 XSetWindowAttributes aAttribs
;
86 aAttribs
.event_mask
= StructureNotifyMask
97 XCreateSimpleWindow( pDisp
,
101 pSalDisp
->GetColormap( nXScreen
).GetBlackPixel(),
102 pSalDisp
->GetColormap( nXScreen
).GetWhitePixel()
104 if( aVisID
== pSalDisp
->GetVisual( nXScreen
).GetVisualId() )
106 pObject
->maSecondary
=
107 XCreateSimpleWindow( pDisp
,
111 pSalDisp
->GetColormap( nXScreen
).GetBlackPixel(),
112 pSalDisp
->GetColormap( nXScreen
).GetWhitePixel()
117 #if OSL_DEBUG_LEVEL > 1
118 SAL_INFO("vcl.window", "visual id of vcl "
120 << static_cast<unsigned int>
121 (pSalDisp
->GetVisual( nXScreen
).GetVisualId())
123 << static_cast<unsigned int>
126 GetGenericUnixSalData()->ErrorTrapPush();
128 // create colormap for visual - there might not be one
129 pObject
->maColormap
= aAttribs
.colormap
= XCreateColormap(
131 pSalDisp
->GetRootWindow( nXScreen
),
135 pObject
->maSecondary
=
136 XCreateWindow( pDisp
,
137 pSalDisp
->GetRootWindow( nXScreen
),
142 CWEventMask
|CWColormap
, &aAttribs
);
143 XSync( pDisp
, False
);
144 if( GetGenericUnixSalData()->ErrorTrapPop( false ) )
146 pObject
->maSecondary
= None
;
150 XReparentWindow( pDisp
, pObject
->maSecondary
, pObject
->maPrimary
, 0, 0 );
153 GetGenericUnixSalData()->ErrorTrapPush();
155 XMapWindow( pDisp
, pObject
->maSecondary
);
156 XMapWindow( pDisp
, pObject
->maPrimary
);
159 pObjData
->pDisplay
= pDisp
;
160 pObjData
->SetWindowHandle(pObject
->maSecondary
);
161 pObjData
->pWidget
= nullptr;
162 pObjData
->pVisual
= pVisual
;
165 if( GetGenericUnixSalData()->ErrorTrapPop( false ) )
174 void X11SalInstance::DestroyObject( SalObject
* pObject
)
179 // SalClipRegion is a member of SalObject
180 // definition of SalClipRegion my be found in vcl/inc/unx/salobj.h
182 SalClipRegion::SalClipRegion()
184 ClipRectangleList
= nullptr;
185 numClipRectangles
= 0;
186 maxClipRectangles
= 0;
189 SalClipRegion::~SalClipRegion()
194 SalClipRegion::BeginSetClipRegion( sal_uInt32 nRects
)
196 ClipRectangleList
.reset( new XRectangle
[nRects
] );
197 numClipRectangles
= 0;
198 maxClipRectangles
= nRects
;
202 SalClipRegion::UnionClipRegion( tools::Long nX
, tools::Long nY
, tools::Long nWidth
, tools::Long nHeight
)
204 if ( nWidth
&& nHeight
&& (numClipRectangles
< maxClipRectangles
) )
206 XRectangle
& aRect
= ClipRectangleList
[numClipRectangles
];
208 aRect
.x
= static_cast<short>(nX
);
209 aRect
.y
= static_cast<short>(nY
);
210 aRect
.width
= static_cast<unsigned short>(nWidth
);
211 aRect
.height
= static_cast<unsigned short>(nHeight
);
217 // SalObject Implementation
218 X11SalObject::X11SalObject()
226 maSystemChildData
.pDisplay
= vcl_sal::getSalDisplay(GetGenericUnixSalData())->GetDisplay();
227 maSystemChildData
.SetWindowHandle(None
);
228 maSystemChildData
.pSalFrame
= nullptr;
229 maSystemChildData
.pWidget
= nullptr;
230 maSystemChildData
.pVisual
= nullptr;
231 maSystemChildData
.aShellWindow
= 0;
232 maSystemChildData
.toolkit
= SystemEnvData::Toolkit::Gen
;
233 maSystemChildData
.platform
= SystemEnvData::Platform::Xcb
;
235 std::list
< SalObject
* >& rObjects
= vcl_sal::getSalDisplay(GetGenericUnixSalData())->getSalObjects();
236 rObjects
.push_back( this );
239 X11SalObject::~X11SalObject()
241 std::list
< SalObject
* >& rObjects
= vcl_sal::getSalDisplay(GetGenericUnixSalData())->getSalObjects();
242 rObjects
.remove( this );
244 GetGenericUnixSalData()->ErrorTrapPush();
245 ::Window aObjectParent
= maParentWin
;
246 XSetWindowBackgroundPixmap(static_cast<Display
*>(maSystemChildData
.pDisplay
), aObjectParent
, None
);
248 XDestroyWindow( static_cast<Display
*>(maSystemChildData
.pDisplay
), maSecondary
);
250 XDestroyWindow( static_cast<Display
*>(maSystemChildData
.pDisplay
), maPrimary
);
252 XFreeColormap(static_cast<Display
*>(maSystemChildData
.pDisplay
), maColormap
);
253 XSync( static_cast<Display
*>(maSystemChildData
.pDisplay
), False
);
254 GetGenericUnixSalData()->ErrorTrapPop();
258 X11SalObject::ResetClipRegion()
260 maClipRegion
.ResetClipRegion();
262 const int dest_kind
= ShapeBounding
;
263 const int op
= ShapeSet
;
264 const int ordering
= YSorted
;
266 XWindowAttributes win_attrib
;
269 ::Window aShapeWindow
= maPrimary
;
271 XGetWindowAttributes ( static_cast<Display
*>(maSystemChildData
.pDisplay
),
277 win_size
.width
= win_attrib
.width
;
278 win_size
.height
= win_attrib
.height
;
280 XShapeCombineRectangles ( static_cast<Display
*>(maSystemChildData
.pDisplay
),
283 0, 0, // x_off, y_off
284 &win_size
, // list of rectangles
285 1, // number of rectangles
290 X11SalObject::BeginSetClipRegion( sal_uInt32 nRectCount
)
292 maClipRegion
.BeginSetClipRegion ( nRectCount
);
296 X11SalObject::UnionClipRegion( tools::Long nX
, tools::Long nY
, tools::Long nWidth
, tools::Long nHeight
)
298 maClipRegion
.UnionClipRegion ( nX
, nY
, nWidth
, nHeight
);
302 X11SalObject::EndSetClipRegion()
304 XRectangle
*pRectangles
= maClipRegion
.EndSetClipRegion ();
305 const int nRectangles
= maClipRegion
.GetRectangleCount();
307 ::Window aShapeWindow
= maPrimary
;
309 XShapeCombineRectangles ( static_cast<Display
*>(maSystemChildData
.pDisplay
),
312 0, 0, // x_off, y_off
319 X11SalObject::SetPosSize( tools::Long nX
, tools::Long nY
, tools::Long nWidth
, tools::Long nHeight
)
321 if ( maPrimary
&& maSecondary
&& nWidth
&& nHeight
)
323 XMoveResizeWindow( static_cast<Display
*>(maSystemChildData
.pDisplay
),
325 nX
, nY
, nWidth
, nHeight
);
326 XMoveResizeWindow( static_cast<Display
*>(maSystemChildData
.pDisplay
),
328 0, 0, nWidth
, nHeight
);
333 X11SalObject::Show( bool bVisible
)
335 if (!maSystemChildData
.GetWindowHandle(mpParent
))
339 XMapWindow( static_cast<Display
*>(maSystemChildData
.pDisplay
),
341 XMapWindow( static_cast<Display
*>(maSystemChildData
.pDisplay
),
344 XUnmapWindow( static_cast<Display
*>(maSystemChildData
.pDisplay
),
346 XUnmapWindow( static_cast<Display
*>(maSystemChildData
.pDisplay
),
349 mbVisible
= bVisible
;
352 void X11SalObject::GrabFocus()
355 XSetInputFocus( static_cast<Display
*>(maSystemChildData
.pDisplay
),
356 maSystemChildData
.GetWindowHandle(mpParent
),
361 const SystemEnvData
* X11SalObject::GetSystemData() const
363 return &maSystemChildData
;
366 static sal_uInt16
sal_GetCode( int state
)
368 sal_uInt16 nCode
= 0;
370 if( state
& Button1Mask
)
372 if( state
& Button2Mask
)
373 nCode
|= MOUSE_MIDDLE
;
374 if( state
& Button3Mask
)
375 nCode
|= MOUSE_RIGHT
;
377 if( state
& ShiftMask
)
379 if( state
& ControlMask
)
381 if( state
& Mod1Mask
)
383 if( state
& Mod3Mask
)
389 bool X11SalObject::Dispatch( XEvent
* pEvent
)
391 std::list
< SalObject
* >& rObjects
= vcl_sal::getSalDisplay(GetGenericUnixSalData())->getSalObjects();
393 for (auto const& elem
: rObjects
)
395 X11SalObject
* pObject
= static_cast<X11SalObject
*>(elem
);
396 if( pEvent
->xany
.window
== pObject
->maPrimary
||
397 pEvent
->xany
.window
== pObject
->maSecondary
)
399 if( pObject
->IsMouseTransparent() && (
400 pEvent
->type
== ButtonPress
||
401 pEvent
->type
== ButtonRelease
||
402 pEvent
->type
== EnterNotify
||
403 pEvent
->type
== LeaveNotify
||
404 pEvent
->type
== MotionNotify
410 ::Window aChild
= None
;
411 XTranslateCoordinates( pEvent
->xbutton
.display
,
412 pEvent
->xbutton
.root
,
413 pObject
->maParentWin
,
414 pEvent
->xbutton
.x_root
,
415 pEvent
->xbutton
.y_root
,
420 aEvt
.mnTime
= pEvent
->xbutton
.time
;
421 aEvt
.mnCode
= sal_GetCode( pEvent
->xbutton
.state
);
423 SalEvent nEvent
= SalEvent::NONE
;
424 if( pEvent
->type
== ButtonPress
||
425 pEvent
->type
== ButtonRelease
)
427 switch( pEvent
->xbutton
.button
)
429 case Button1
: aEvt
.mnButton
= MOUSE_LEFT
;break;
430 case Button2
: aEvt
.mnButton
= MOUSE_MIDDLE
;break;
431 case Button3
: aEvt
.mnButton
= MOUSE_RIGHT
;break;
433 nEvent
= (pEvent
->type
== ButtonPress
) ?
434 SalEvent::MouseButtonDown
:
435 SalEvent::MouseButtonUp
;
437 else if( pEvent
->type
== EnterNotify
)
438 nEvent
= SalEvent::MouseLeave
;
440 nEvent
= SalEvent::MouseMove
;
441 pObject
->mpParent
->CallCallback( nEvent
, &aEvt
);
445 switch( pEvent
->type
)
448 pObject
->mbVisible
= false;
451 pObject
->mbVisible
= true;
454 pObject
->CallCallback( SalObjEvent::ToTop
);
457 pObject
->CallCallback( SalObjEvent::GetFocus
);
460 pObject
->CallCallback( SalObjEvent::LoseFocus
);
471 void X11SalObject::SetLeaveEnterBackgrounds(const css::uno::Sequence
<css::uno::Any
>& rLeaveArgs
, const css::uno::Sequence
<css::uno::Any
>& rEnterArgs
)
473 SalDisplay
* pSalDisp
= vcl_sal::getSalDisplay(GetGenericUnixSalData());
474 Display
* pDisp
= pSalDisp
->GetDisplay();
475 ::Window aObjectParent
= maParentWin
;
477 bool bFreePixmap
= false;
478 Pixmap aPixmap
= None
;
479 if (rEnterArgs
.getLength() == 2)
481 rEnterArgs
[0] >>= bFreePixmap
;
482 sal_Int64 pixmapHandle
= None
;
483 rEnterArgs
[1] >>= pixmapHandle
;
484 aPixmap
= pixmapHandle
;
487 XSetWindowBackgroundPixmap(pDisp
, aObjectParent
, aPixmap
);
489 XFreePixmap(pDisp
, aPixmap
);
493 if (rLeaveArgs
.getLength() == 2)
495 rLeaveArgs
[0] >>= bFreePixmap
;
496 sal_Int64 pixmapHandle
= None
;
497 rLeaveArgs
[1] >>= pixmapHandle
;
498 aPixmap
= pixmapHandle
;
501 XSetWindowBackgroundPixmap(pDisp
, maSecondary
, aPixmap
);
503 XFreePixmap(pDisp
, aPixmap
);
506 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */