bump product version to 5.0.4.1
[LibreOffice.git] / vcl / unx / generic / app / randrwrapper.cxx
blobecdfce34e736bae98477240afd747beb31a3f235
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 #ifdef USE_RANDR
22 #include <prex.h>
23 #include <X11/extensions/Xrandr.h>
24 #include <postx.h>
26 #include "osl/module.h"
27 #include "rtl/ustring.hxx"
29 namespace
32 # ifdef XRANDR_DLOPEN
34 class RandRWrapper
36 oslModule m_pRandRLib;
38 // function pointers
39 Bool(*m_pXRRQueryExtension)(Display*,int*,int*);
40 XRRScreenConfiguration*(*m_pXRRGetScreenInfo)(Display*,Drawable);
41 void(*m_pXRRFreeScreenConfigInfo)(XRRScreenConfiguration*);
42 void(*m_pXRRSelectInput)(Display*,::Window,int);
43 int(*m_pXRRUpdateConfiguration)(XEvent*);
44 XRRScreenSize*(*m_pXRRConfigSizes)(XRRScreenConfiguration*,int*);
45 SizeID(*m_pXRRConfigCurrentConfiguration)(XRRScreenConfiguration*,Rotation*);
46 int(*m_pXRRRootToScreen)(Display*, ::Window);
48 bool m_bValid;
50 void initFromModule();
52 RandRWrapper(Display*);
53 ~RandRWrapper();
54 public:
55 static RandRWrapper& get(Display*);
56 static void releaseWrapper();
58 Bool XRRQueryExtension(Display* i_pDisp, int* o_event_base, int* o_error_base )
60 Bool bRet = False;
61 if( m_bValid )
62 bRet = m_pXRRQueryExtension( i_pDisp, o_event_base, o_error_base );
63 return bRet;
65 XRRScreenConfiguration* XRRGetScreenInfo( Display* i_pDisp, Drawable i_aDrawable )
67 return m_bValid ? m_pXRRGetScreenInfo( i_pDisp, i_aDrawable ) : NULL;
69 void XRRFreeScreenConfigInfo( XRRScreenConfiguration* i_pConfig )
71 if( m_bValid )
72 m_pXRRFreeScreenConfigInfo( i_pConfig );
74 void XRRSelectInput( Display* i_pDisp, ::Window i_window, int i_nMask )
76 if( m_bValid )
77 m_pXRRSelectInput( i_pDisp, i_window, i_nMask );
79 int XRRUpdateConfiguration( XEvent* i_pEvent )
81 return m_bValid ? m_pXRRUpdateConfiguration( i_pEvent ) : 0;
83 XRRScreenSize* XRRConfigSizes( XRRScreenConfiguration* i_pConfig, int* o_nSizes )
85 return m_bValid ? m_pXRRConfigSizes( i_pConfig, o_nSizes ) : NULL;
87 SizeID XRRConfigCurrentConfiguration( XRRScreenConfiguration* i_pConfig, Rotation* o_pRot )
89 return m_bValid ? m_pXRRConfigCurrentConfiguration( i_pConfig, o_pRot ) : 0;
91 int XRRRootToScreen( Display *dpy, ::Window root )
93 return m_bValid ? m_pXRRRootToScreen( dpy, root ) : -1;
97 void RandRWrapper::initFromModule()
99 m_pXRRQueryExtension = (Bool(*)(Display*,int*,int*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRQueryExtension" );
100 m_pXRRGetScreenInfo = (XRRScreenConfiguration*(*)(Display*,Drawable))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRGetScreenInfo" );
101 m_pXRRFreeScreenConfigInfo = (void(*)(XRRScreenConfiguration*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRFreeScreenConfigInfo" );
102 m_pXRRSelectInput = (void(*)(Display*,::Window,int))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRSelectInput" );
103 m_pXRRUpdateConfiguration = (int(*)(XEvent*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRUpdateConfiguration" );
104 m_pXRRConfigSizes = (XRRScreenSize*(*)(XRRScreenConfiguration*,int*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRConfigSizes" );
105 m_pXRRConfigCurrentConfiguration = (SizeID(*)(XRRScreenConfiguration*,Rotation*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRConfigCurrentConfiguration" );
106 m_pXRRRootToScreen = (int(*)(Display*,::Window))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRRootToScreen" );
108 m_bValid = m_pXRRQueryExtension &&
109 m_pXRRGetScreenInfo &&
110 m_pXRRFreeScreenConfigInfo &&
111 m_pXRRSelectInput &&
112 m_pXRRUpdateConfiguration &&
113 m_pXRRConfigSizes &&
114 m_pXRRConfigCurrentConfiguration &&
115 m_pXRRRootToScreen
119 RandRWrapper::RandRWrapper( Display* pDisplay ) :
120 m_pRandRLib( NULL ),
121 m_pXRRQueryExtension( NULL ),
122 m_pXRRGetScreenInfo( NULL ),
123 m_pXRRFreeScreenConfigInfo( NULL ),
124 m_pXRRSelectInput( NULL ),
125 m_pXRRUpdateConfiguration( NULL ),
126 m_pXRRConfigSizes( NULL ),
127 m_pXRRConfigCurrentConfiguration( NULL ),
128 m_pXRRRootToScreen( NULL ),
129 m_bValid( false )
131 // first try in process space (e.g. gtk links that ?)
132 initFromModule();
133 if( ! m_bValid )
135 // load and resolve dependencies immediately
136 // rationale: there are older distributions where libXrandr.so.2 is not linked
137 // with libXext.so, resulting in a missing symbol and terminating the office
138 // obviously they expected libXext to be linked in global symbolspace (that is
139 // linked by the application), which is not the case with us (because we want
140 // to be able to run in headless mode even without an installed X11 library)
141 m_pRandRLib = osl_loadModule( "libXrandr.so.2", SAL_LOADMODULE_DEFAULT | SAL_LOADMODULE_NOW );
142 initFromModule();
144 if( m_bValid )
146 int nEventBase = 0, nErrorBase = 0;
147 if( ! m_pXRRQueryExtension( pDisplay, &nEventBase, &nErrorBase ) )
148 m_bValid = false;
152 RandRWrapper::~RandRWrapper()
154 if( m_pRandRLib )
155 osl_unloadModule( m_pRandRLib );
158 static RandRWrapper* pWrapper = NULL;
160 RandRWrapper& RandRWrapper::get( Display* i_pDisplay )
162 if( ! pWrapper )
163 pWrapper = new RandRWrapper( i_pDisplay );
164 return *pWrapper;
167 void RandRWrapper::releaseWrapper()
169 delete pWrapper;
170 pWrapper = NULL;
173 # else
175 class RandRWrapper
177 bool m_bValid;
179 RandRWrapper(Display*);
180 public:
181 static RandRWrapper& get(Display*);
182 static void releaseWrapper();
184 Bool XRRQueryExtension(Display* i_pDisp, int* o_event_base, int* o_error_base )
186 Bool bRet = False;
187 if( m_bValid )
188 bRet = ::XRRQueryExtension( i_pDisp, o_event_base, o_error_base );
189 return bRet;
191 XRRScreenConfiguration* XRRGetScreenInfo( Display* i_pDisp, Drawable i_aDrawable )
193 return m_bValid ? ::XRRGetScreenInfo( i_pDisp, i_aDrawable ) : NULL;
195 void XRRFreeScreenConfigInfo( XRRScreenConfiguration* i_pConfig )
197 if( m_bValid )
198 ::XRRFreeScreenConfigInfo( i_pConfig );
200 void XRRSelectInput( Display* i_pDisp, ::Window i_window, int i_nMask )
202 if( m_bValid )
203 ::XRRSelectInput( i_pDisp, i_window, i_nMask );
205 int XRRUpdateConfiguration( XEvent* i_pEvent )
207 return m_bValid ? ::XRRUpdateConfiguration( i_pEvent ) : 0;
209 XRRScreenSize* XRRConfigSizes( XRRScreenConfiguration* i_pConfig, int* o_nSizes )
211 return m_bValid ? ::XRRConfigSizes( i_pConfig, o_nSizes ) : NULL;
213 SizeID XRRConfigCurrentConfiguration( XRRScreenConfiguration* i_pConfig, Rotation* o_pRot )
215 return m_bValid ? ::XRRConfigCurrentConfiguration( i_pConfig, o_pRot ) : 0;
217 int XRRRootToScreen( Display *dpy, ::Window root )
219 return m_bValid ? ::XRRRootToScreen( dpy, root ) : -1;
223 RandRWrapper::RandRWrapper( Display* pDisplay ) :
224 m_bValid( true )
226 int nEventBase = 0, nErrorBase = 0;
227 if( !XRRQueryExtension( pDisplay, &nEventBase, &nErrorBase ) )
228 m_bValid = false;
231 static RandRWrapper* pWrapper = NULL;
233 RandRWrapper& RandRWrapper::get( Display* i_pDisplay )
235 if( ! pWrapper )
236 pWrapper = new RandRWrapper( i_pDisplay );
237 return *pWrapper;
240 void RandRWrapper::releaseWrapper()
242 delete pWrapper;
243 pWrapper = NULL;
246 #endif
248 } // namespace
250 #endif
252 #include "unx/saldisp.hxx"
253 #include "unx/salframe.h"
254 #if OSL_DEBUG_LEVEL > 1
255 #include <cstdio>
256 #endif
258 void SalDisplay::InitRandR( ::Window aRoot ) const
260 #ifdef USE_RANDR
261 if( m_bUseRandRWrapper )
262 RandRWrapper::get( GetDisplay() ).XRRSelectInput( GetDisplay(), aRoot, RRScreenChangeNotifyMask );
263 #else
264 (void)aRoot;
265 #endif
268 void SalDisplay::DeInitRandR()
270 #ifdef USE_RANDR
271 if( m_bUseRandRWrapper )
272 RandRWrapper::releaseWrapper();
273 #if OSL_DEBUG_LEVEL > 1
274 fprintf( stderr, "SalDisplay::DeInitRandR()\n" );
275 #endif
276 #endif
279 int SalDisplay::processRandREvent( XEvent* pEvent )
281 int nRet = 0;
282 #ifdef USE_RANDR
283 XConfigureEvent* pCnfEvent=reinterpret_cast<XConfigureEvent*>(pEvent);
284 if( m_bUseRandRWrapper && pWrapper && pWrapper->XRRRootToScreen(GetDisplay(),pCnfEvent->window) != -1 )
286 nRet = pWrapper->XRRUpdateConfiguration( pEvent );
287 if( nRet == 1 && pEvent->type != ConfigureNotify) // this should then be a XRRScreenChangeNotifyEvent
289 // update screens
290 bool bNotify = false;
291 for( size_t i = 0; i < m_aScreens.size(); i++ )
293 if( m_aScreens[i].m_bInit )
295 XRRScreenConfiguration *pConfig = NULL;
296 XRRScreenSize *pSizes = NULL;
297 int nSizes = 0;
298 Rotation nRot = 0;
299 SizeID nId = 0;
301 pConfig = pWrapper->XRRGetScreenInfo( GetDisplay(), m_aScreens[i].m_aRoot );
302 nId = pWrapper->XRRConfigCurrentConfiguration( pConfig, &nRot );
303 pSizes = pWrapper->XRRConfigSizes( pConfig, &nSizes );
304 XRRScreenSize *pTargetSize = pSizes + nId;
306 bNotify = bNotify ||
307 m_aScreens[i].m_aSize.Width() != pTargetSize->width ||
308 m_aScreens[i].m_aSize.Height() != pTargetSize->height;
310 m_aScreens[i].m_aSize = Size( pTargetSize->width, pTargetSize->height );
312 pWrapper->XRRFreeScreenConfigInfo( pConfig );
314 #if OSL_DEBUG_LEVEL > 1
315 fprintf( stderr, "screen %d changed to size %dx%d\n", (int)i, (int)pTargetSize->width, (int)pTargetSize->height );
316 #endif
319 if( bNotify )
320 emitDisplayChanged();
323 #else
324 (void)pEvent;
325 #endif
326 return nRet;
329 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */