Update git submodules
[LibreOffice.git] / vcl / unx / generic / window / salobj.cxx
blobe2571c7911a2c4e20d009d846b41c3cb2e8761bf
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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
21 #include <stdio.h>
22 #endif
24 #include <X11/Xlib.h>
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 ) )
56 delete pObject;
57 return nullptr;
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();
75 // get visual info
76 VisualID aVisID = XVisualIDFromVisual( pVisual );
77 XVisualInfo aTemplate;
78 aTemplate.visualid = aVisID;
79 int nVisuals = 0;
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;
84 XFree( pInfo );
85 XSetWindowAttributes aAttribs;
86 aAttribs.event_mask = StructureNotifyMask
87 | ButtonPressMask
88 | ButtonReleaseMask
89 | PointerMotionMask
90 | EnterWindowMask
91 | LeaveWindowMask
92 | FocusChangeMask
93 | ExposureMask
96 pObject->maPrimary =
97 XCreateSimpleWindow( pDisp,
98 aObjectParent,
99 0, 0,
100 1, 1, 0,
101 pSalDisp->GetColormap( nXScreen ).GetBlackPixel(),
102 pSalDisp->GetColormap( nXScreen ).GetWhitePixel()
104 if( aVisID == pSalDisp->GetVisual( nXScreen ).GetVisualId() )
106 pObject->maSecondary =
107 XCreateSimpleWindow( pDisp,
108 pObject->maPrimary,
109 0, 0,
110 1, 1, 0,
111 pSalDisp->GetColormap( nXScreen ).GetBlackPixel(),
112 pSalDisp->GetColormap( nXScreen ).GetWhitePixel()
115 else
117 #if OSL_DEBUG_LEVEL > 1
118 SAL_INFO("vcl.window", "visual id of vcl "
119 << std::hex
120 << static_cast<unsigned int>
121 (pSalDisp->GetVisual( nXScreen ).GetVisualId())
122 << ", of visual "
123 << static_cast<unsigned int>
124 (aVisID));
125 #endif
126 GetGenericUnixSalData()->ErrorTrapPush();
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 AllocNone );
135 pObject->maSecondary =
136 XCreateWindow( pDisp,
137 pSalDisp->GetRootWindow( nXScreen ),
138 0, 0,
139 1, 1, 0,
140 nDepth, InputOutput,
141 pVisual,
142 CWEventMask|CWColormap, &aAttribs );
143 XSync( pDisp, False );
144 if( GetGenericUnixSalData()->ErrorTrapPop( false ) )
146 pObject->maSecondary = None;
147 delete pObject;
148 return nullptr;
150 XReparentWindow( pDisp, pObject->maSecondary, pObject->maPrimary, 0, 0 );
153 GetGenericUnixSalData()->ErrorTrapPush();
154 if( bShow ) {
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;
164 XSync(pDisp, False);
165 if( GetGenericUnixSalData()->ErrorTrapPop( false ) )
167 delete pObject;
168 return nullptr;
171 return pObject;
174 void X11SalInstance::DestroyObject( SalObject* pObject )
176 delete 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()
193 void
194 SalClipRegion::BeginSetClipRegion( sal_uInt32 nRects )
196 ClipRectangleList.reset( new XRectangle[nRects] );
197 numClipRectangles = 0;
198 maxClipRectangles = nRects;
201 void
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);
213 numClipRectangles++;
217 // SalObject Implementation
218 X11SalObject::X11SalObject()
219 : mpParent(nullptr)
220 , maParentWin(0)
221 , maPrimary(0)
222 , maSecondary(0)
223 , maColormap(0)
224 , mbVisible(false)
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);
247 if ( maSecondary )
248 XDestroyWindow( static_cast<Display*>(maSystemChildData.pDisplay), maSecondary );
249 if ( maPrimary )
250 XDestroyWindow( static_cast<Display*>(maSystemChildData.pDisplay), maPrimary );
251 if ( maColormap )
252 XFreeColormap(static_cast<Display*>(maSystemChildData.pDisplay), maColormap);
253 XSync( static_cast<Display*>(maSystemChildData.pDisplay), False );
254 GetGenericUnixSalData()->ErrorTrapPop();
257 void
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;
267 XRectangle win_size;
269 ::Window aShapeWindow = maPrimary;
271 XGetWindowAttributes ( static_cast<Display*>(maSystemChildData.pDisplay),
272 aShapeWindow,
273 &win_attrib );
275 win_size.x = 0;
276 win_size.y = 0;
277 win_size.width = win_attrib.width;
278 win_size.height = win_attrib.height;
280 XShapeCombineRectangles ( static_cast<Display*>(maSystemChildData.pDisplay),
281 aShapeWindow,
282 dest_kind,
283 0, 0, // x_off, y_off
284 &win_size, // list of rectangles
285 1, // number of rectangles
286 op, ordering );
289 void
290 X11SalObject::BeginSetClipRegion( sal_uInt32 nRectCount )
292 maClipRegion.BeginSetClipRegion ( nRectCount );
295 void
296 X11SalObject::UnionClipRegion( tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight )
298 maClipRegion.UnionClipRegion ( nX, nY, nWidth, nHeight );
301 void
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),
310 aShapeWindow,
311 ShapeBounding,
312 0, 0, // x_off, y_off
313 pRectangles,
314 nRectangles,
315 ShapeSet, YSorted );
318 void
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),
324 maPrimary,
325 nX, nY, nWidth, nHeight );
326 XMoveResizeWindow( static_cast<Display*>(maSystemChildData.pDisplay),
327 maSecondary,
328 0, 0, nWidth, nHeight );
332 void
333 X11SalObject::Show( bool bVisible )
335 if (!maSystemChildData.GetWindowHandle(mpParent))
336 return;
338 if ( bVisible ) {
339 XMapWindow( static_cast<Display*>(maSystemChildData.pDisplay),
340 maSecondary );
341 XMapWindow( static_cast<Display*>(maSystemChildData.pDisplay),
342 maPrimary );
343 } else {
344 XUnmapWindow( static_cast<Display*>(maSystemChildData.pDisplay),
345 maPrimary );
346 XUnmapWindow( static_cast<Display*>(maSystemChildData.pDisplay),
347 maSecondary );
349 mbVisible = bVisible;
352 void X11SalObject::GrabFocus()
354 if( mbVisible )
355 XSetInputFocus( static_cast<Display*>(maSystemChildData.pDisplay),
356 maSystemChildData.GetWindowHandle(mpParent),
357 RevertToNone,
358 CurrentTime );
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 )
371 nCode |= MOUSE_LEFT;
372 if( state & Button2Mask )
373 nCode |= MOUSE_MIDDLE;
374 if( state & Button3Mask )
375 nCode |= MOUSE_RIGHT;
377 if( state & ShiftMask )
378 nCode |= KEY_SHIFT;
379 if( state & ControlMask )
380 nCode |= KEY_MOD1;
381 if( state & Mod1Mask )
382 nCode |= KEY_MOD2;
383 if( state & Mod3Mask )
384 nCode |= KEY_MOD3;
386 return nCode;
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
408 SalMouseEvent aEvt;
409 int dest_x, dest_y;
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,
416 &dest_x, &dest_y,
417 &aChild );
418 aEvt.mnX = dest_x;
419 aEvt.mnY = dest_y;
420 aEvt.mnTime = pEvent->xbutton.time;
421 aEvt.mnCode = sal_GetCode( pEvent->xbutton.state );
422 aEvt.mnButton = 0;
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;
439 else
440 nEvent = SalEvent::MouseMove;
441 pObject->mpParent->CallCallback( nEvent, &aEvt );
443 else
445 switch( pEvent->type )
447 case UnmapNotify:
448 pObject->mbVisible = false;
449 return true;
450 case MapNotify:
451 pObject->mbVisible = true;
452 return true;
453 case ButtonPress:
454 pObject->CallCallback( SalObjEvent::ToTop );
455 return true;
456 case FocusIn:
457 pObject->CallCallback( SalObjEvent::GetFocus );
458 return true;
459 case FocusOut:
460 pObject->CallCallback( SalObjEvent::LoseFocus );
461 return true;
462 default: break;
465 return false;
468 return false;
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);
488 if (bFreePixmap)
489 XFreePixmap(pDisp, aPixmap);
491 bFreePixmap = false;
492 aPixmap = None;
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);
502 if (bFreePixmap)
503 XFreePixmap(pDisp, aPixmap);
506 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */