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 : #ifdef USE_RANDR
21 :
22 : #include <prex.h>
23 : #include <X11/extensions/Xrandr.h>
24 : #include <postx.h>
25 :
26 : #include "osl/module.h"
27 : #include "rtl/ustring.hxx"
28 :
29 : namespace
30 : {
31 :
32 : # ifdef XRANDR_DLOPEN
33 :
34 : class RandRWrapper
35 : {
36 : oslModule m_pRandRLib;
37 :
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);
47 :
48 : bool m_bValid;
49 :
50 : void initFromModule();
51 :
52 : explicit RandRWrapper(Display*);
53 : ~RandRWrapper();
54 : public:
55 : static RandRWrapper& get(Display*);
56 : static void releaseWrapper();
57 :
58 : Bool XRRQueryExtension(Display* i_pDisp, int* o_event_base, int* o_error_base )
59 : {
60 : Bool bRet = False;
61 : if( m_bValid )
62 : bRet = m_pXRRQueryExtension( i_pDisp, o_event_base, o_error_base );
63 : return bRet;
64 : }
65 : XRRScreenConfiguration* XRRGetScreenInfo( Display* i_pDisp, Drawable i_aDrawable )
66 : {
67 : return m_bValid ? m_pXRRGetScreenInfo( i_pDisp, i_aDrawable ) : NULL;
68 : }
69 : void XRRFreeScreenConfigInfo( XRRScreenConfiguration* i_pConfig )
70 : {
71 : if( m_bValid )
72 : m_pXRRFreeScreenConfigInfo( i_pConfig );
73 : }
74 : void XRRSelectInput( Display* i_pDisp, ::Window i_window, int i_nMask )
75 : {
76 : if( m_bValid )
77 : m_pXRRSelectInput( i_pDisp, i_window, i_nMask );
78 : }
79 : int XRRUpdateConfiguration( XEvent* i_pEvent )
80 : {
81 : return m_bValid ? m_pXRRUpdateConfiguration( i_pEvent ) : 0;
82 : }
83 : XRRScreenSize* XRRConfigSizes( XRRScreenConfiguration* i_pConfig, int* o_nSizes )
84 : {
85 : return m_bValid ? m_pXRRConfigSizes( i_pConfig, o_nSizes ) : NULL;
86 : }
87 : SizeID XRRConfigCurrentConfiguration( XRRScreenConfiguration* i_pConfig, Rotation* o_pRot )
88 : {
89 : return m_bValid ? m_pXRRConfigCurrentConfiguration( i_pConfig, o_pRot ) : 0;
90 : }
91 : int XRRRootToScreen( Display *dpy, ::Window root )
92 : {
93 : return m_bValid ? m_pXRRRootToScreen( dpy, root ) : -1;
94 : }
95 : };
96 :
97 : void RandRWrapper::initFromModule()
98 : {
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" );
107 :
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
116 : ;
117 : }
118 :
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 )
130 : {
131 : // first try in process space (e.g. gtk links that ?)
132 : initFromModule();
133 : if( ! m_bValid )
134 : {
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();
143 : }
144 : if( m_bValid )
145 : {
146 : int nEventBase = 0, nErrorBase = 0;
147 : if( ! m_pXRRQueryExtension( pDisplay, &nEventBase, &nErrorBase ) )
148 : m_bValid = false;
149 : }
150 : }
151 :
152 : RandRWrapper::~RandRWrapper()
153 : {
154 : if( m_pRandRLib )
155 : osl_unloadModule( m_pRandRLib );
156 : }
157 :
158 : static RandRWrapper* pWrapper = NULL;
159 :
160 : RandRWrapper& RandRWrapper::get( Display* i_pDisplay )
161 : {
162 : if( ! pWrapper )
163 : pWrapper = new RandRWrapper( i_pDisplay );
164 : return *pWrapper;
165 : }
166 :
167 : void RandRWrapper::releaseWrapper()
168 : {
169 : delete pWrapper;
170 : pWrapper = NULL;
171 : }
172 :
173 : # else
174 :
175 : class RandRWrapper
176 : {
177 : bool m_bValid;
178 :
179 : explicit RandRWrapper(Display*);
180 : public:
181 : static RandRWrapper& get(Display*);
182 : static void releaseWrapper();
183 :
184 0 : Bool XRRQueryExtension(Display* i_pDisp, int* o_event_base, int* o_error_base )
185 : {
186 0 : Bool bRet = False;
187 0 : if( m_bValid )
188 0 : bRet = ::XRRQueryExtension( i_pDisp, o_event_base, o_error_base );
189 0 : return bRet;
190 : }
191 0 : XRRScreenConfiguration* XRRGetScreenInfo( Display* i_pDisp, Drawable i_aDrawable )
192 : {
193 0 : return m_bValid ? ::XRRGetScreenInfo( i_pDisp, i_aDrawable ) : NULL;
194 : }
195 0 : void XRRFreeScreenConfigInfo( XRRScreenConfiguration* i_pConfig )
196 : {
197 0 : if( m_bValid )
198 0 : ::XRRFreeScreenConfigInfo( i_pConfig );
199 0 : }
200 0 : void XRRSelectInput( Display* i_pDisp, ::Window i_window, int i_nMask )
201 : {
202 0 : if( m_bValid )
203 0 : ::XRRSelectInput( i_pDisp, i_window, i_nMask );
204 0 : }
205 0 : int XRRUpdateConfiguration( XEvent* i_pEvent )
206 : {
207 0 : return m_bValid ? ::XRRUpdateConfiguration( i_pEvent ) : 0;
208 : }
209 0 : XRRScreenSize* XRRConfigSizes( XRRScreenConfiguration* i_pConfig, int* o_nSizes )
210 : {
211 0 : return m_bValid ? ::XRRConfigSizes( i_pConfig, o_nSizes ) : NULL;
212 : }
213 0 : SizeID XRRConfigCurrentConfiguration( XRRScreenConfiguration* i_pConfig, Rotation* o_pRot )
214 : {
215 0 : return m_bValid ? ::XRRConfigCurrentConfiguration( i_pConfig, o_pRot ) : 0;
216 : }
217 0 : int XRRRootToScreen( Display *dpy, ::Window root )
218 : {
219 0 : return m_bValid ? ::XRRRootToScreen( dpy, root ) : -1;
220 : }
221 : };
222 :
223 0 : RandRWrapper::RandRWrapper( Display* pDisplay ) :
224 0 : m_bValid( true )
225 : {
226 0 : int nEventBase = 0, nErrorBase = 0;
227 0 : if( !XRRQueryExtension( pDisplay, &nEventBase, &nErrorBase ) )
228 0 : m_bValid = false;
229 0 : }
230 :
231 : static RandRWrapper* pWrapper = NULL;
232 :
233 0 : RandRWrapper& RandRWrapper::get( Display* i_pDisplay )
234 : {
235 0 : if( ! pWrapper )
236 0 : pWrapper = new RandRWrapper( i_pDisplay );
237 0 : return *pWrapper;
238 : }
239 :
240 0 : void RandRWrapper::releaseWrapper()
241 : {
242 0 : delete pWrapper;
243 0 : pWrapper = NULL;
244 0 : }
245 :
246 : #endif
247 :
248 : } // namespace
249 :
250 : #endif
251 :
252 : #include "unx/saldisp.hxx"
253 : #include "unx/salframe.h"
254 : #if OSL_DEBUG_LEVEL > 1
255 : #include <cstdio>
256 : #endif
257 :
258 3 : void SalDisplay::InitRandR( ::Window aRoot ) const
259 : {
260 : #ifdef USE_RANDR
261 3 : if( m_bUseRandRWrapper )
262 0 : RandRWrapper::get( GetDisplay() ).XRRSelectInput( GetDisplay(), aRoot, RRScreenChangeNotifyMask );
263 : #else
264 : (void)aRoot;
265 : #endif
266 3 : }
267 :
268 0 : void SalDisplay::DeInitRandR()
269 : {
270 : #ifdef USE_RANDR
271 0 : if( m_bUseRandRWrapper )
272 0 : RandRWrapper::releaseWrapper();
273 : #if OSL_DEBUG_LEVEL > 1
274 : fprintf( stderr, "SalDisplay::DeInitRandR()\n" );
275 : #endif
276 : #endif
277 0 : }
278 :
279 0 : int SalDisplay::processRandREvent( XEvent* pEvent )
280 : {
281 0 : int nRet = 0;
282 : #ifdef USE_RANDR
283 0 : XConfigureEvent* pCnfEvent=reinterpret_cast<XConfigureEvent*>(pEvent);
284 0 : if( m_bUseRandRWrapper && pWrapper && pWrapper->XRRRootToScreen(GetDisplay(),pCnfEvent->window) != -1 )
285 : {
286 0 : nRet = pWrapper->XRRUpdateConfiguration( pEvent );
287 0 : if( nRet == 1 && pEvent->type != ConfigureNotify) // this should then be a XRRScreenChangeNotifyEvent
288 : {
289 : // update screens
290 0 : bool bNotify = false;
291 0 : for( size_t i = 0; i < m_aScreens.size(); i++ )
292 : {
293 0 : if( m_aScreens[i].m_bInit )
294 : {
295 0 : XRRScreenConfiguration *pConfig = NULL;
296 0 : XRRScreenSize *pSizes = NULL;
297 0 : int nSizes = 0;
298 0 : Rotation nRot = 0;
299 0 : SizeID nId = 0;
300 :
301 0 : pConfig = pWrapper->XRRGetScreenInfo( GetDisplay(), m_aScreens[i].m_aRoot );
302 0 : nId = pWrapper->XRRConfigCurrentConfiguration( pConfig, &nRot );
303 0 : pSizes = pWrapper->XRRConfigSizes( pConfig, &nSizes );
304 0 : XRRScreenSize *pTargetSize = pSizes + nId;
305 :
306 0 : bNotify = bNotify ||
307 0 : m_aScreens[i].m_aSize.Width() != pTargetSize->width ||
308 0 : m_aScreens[i].m_aSize.Height() != pTargetSize->height;
309 :
310 0 : m_aScreens[i].m_aSize = Size( pTargetSize->width, pTargetSize->height );
311 :
312 0 : pWrapper->XRRFreeScreenConfigInfo( pConfig );
313 :
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
317 : }
318 : }
319 0 : if( bNotify )
320 0 : emitDisplayChanged();
321 : }
322 : }
323 : #else
324 : (void)pEvent;
325 : #endif
326 0 : return nRet;
327 : }
328 :
329 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|