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 : Status(*m_pXRRQueryVersion)(Display*,int*,int*);
41 : XRRScreenConfiguration*(*m_pXRRGetScreenInfo)(Display*,Drawable);
42 : void(*m_pXRRFreeScreenConfigInfo)(XRRScreenConfiguration*);
43 : void(*m_pXRRSelectInput)(Display*,XLIB_Window,int);
44 : int(*m_pXRRUpdateConfiguration)(XEvent*);
45 : XRRScreenSize*(*m_pXRRSizes)(Display*,int,int*);
46 : XRRScreenSize*(*m_pXRRConfigSizes)(XRRScreenConfiguration*,int*);
47 : SizeID(*m_pXRRConfigCurrentConfiguration)(XRRScreenConfiguration*,Rotation*);
48 : int(*m_pXRRRootToScreen)(Display*, XLIB_Window);
49 :
50 : bool m_bValid;
51 :
52 : void initFromModule();
53 :
54 : RandRWrapper(Display*);
55 : ~RandRWrapper();
56 : public:
57 : static RandRWrapper& get(Display*);
58 : static void releaseWrapper();
59 :
60 : Bool XRRQueryExtension(Display* i_pDisp, int* o_event_base, int* o_error_base )
61 : {
62 : Bool bRet = False;
63 : if( m_bValid )
64 : bRet = m_pXRRQueryExtension( i_pDisp, o_event_base, o_error_base );
65 : return bRet;
66 : }
67 : Status XRRQueryVersion( Display* i_pDisp, int* o_major, int* o_minor )
68 : {
69 : return m_bValid ? m_pXRRQueryVersion( i_pDisp, o_major, o_minor ) : 0;
70 : }
71 : XRRScreenConfiguration* XRRGetScreenInfo( Display* i_pDisp, Drawable i_aDrawable )
72 : {
73 : return m_bValid ? m_pXRRGetScreenInfo( i_pDisp, i_aDrawable ) : NULL;
74 : }
75 : void XRRFreeScreenConfigInfo( XRRScreenConfiguration* i_pConfig )
76 : {
77 : if( m_bValid )
78 : m_pXRRFreeScreenConfigInfo( i_pConfig );
79 : }
80 : void XRRSelectInput( Display* i_pDisp, XLIB_Window i_window, int i_nMask )
81 : {
82 : if( m_bValid )
83 : m_pXRRSelectInput( i_pDisp, i_window, i_nMask );
84 : }
85 : int XRRUpdateConfiguration( XEvent* i_pEvent )
86 : {
87 : return m_bValid ? m_pXRRUpdateConfiguration( i_pEvent ) : 0;
88 : }
89 : XRRScreenSize* XRRSizes( Display* i_pDisp, int i_screen, int* o_nscreens )
90 : {
91 : return m_bValid ? m_pXRRSizes( i_pDisp, i_screen, o_nscreens ) : NULL;
92 : }
93 : XRRScreenSize* XRRConfigSizes( XRRScreenConfiguration* i_pConfig, int* o_nSizes )
94 : {
95 : return m_bValid ? m_pXRRConfigSizes( i_pConfig, o_nSizes ) : NULL;
96 : }
97 : SizeID XRRConfigCurrentConfiguration( XRRScreenConfiguration* i_pConfig, Rotation* o_pRot )
98 : {
99 : return m_bValid ? m_pXRRConfigCurrentConfiguration( i_pConfig, o_pRot ) : 0;
100 : }
101 : int XRRRootToScreen( Display *dpy, XLIB_Window root )
102 : {
103 : return m_bValid ? m_pXRRRootToScreen( dpy, root ) : -1;
104 : }
105 : };
106 :
107 : void RandRWrapper::initFromModule()
108 : {
109 : m_pXRRQueryExtension = (Bool(*)(Display*,int*,int*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRQueryExtension" );
110 : m_pXRRQueryVersion = (Status(*)(Display*,int*,int*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRQueryVersion" );
111 : m_pXRRGetScreenInfo = (XRRScreenConfiguration*(*)(Display*,Drawable))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRGetScreenInfo" );
112 : m_pXRRFreeScreenConfigInfo = (void(*)(XRRScreenConfiguration*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRFreeScreenConfigInfo" );
113 : m_pXRRSelectInput = (void(*)(Display*,XLIB_Window,int))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRSelectInput" );
114 : m_pXRRUpdateConfiguration = (int(*)(XEvent*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRUpdateConfiguration" );
115 : m_pXRRSizes = (XRRScreenSize*(*)(Display*,int,int*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRSizes" );
116 : m_pXRRConfigSizes = (XRRScreenSize*(*)(XRRScreenConfiguration*,int*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRConfigSizes" );
117 : m_pXRRConfigCurrentConfiguration = (SizeID(*)(XRRScreenConfiguration*,Rotation*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRConfigCurrentConfiguration" );
118 : m_pXRRRootToScreen = (int(*)(Display*,XLIB_Window))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRRootToScreen" );
119 :
120 : m_bValid = m_pXRRQueryExtension &&
121 : m_pXRRQueryVersion &&
122 : m_pXRRGetScreenInfo &&
123 : m_pXRRFreeScreenConfigInfo &&
124 : m_pXRRSelectInput &&
125 : m_pXRRUpdateConfiguration &&
126 : m_pXRRSizes &&
127 : m_pXRRConfigSizes &&
128 : m_pXRRConfigCurrentConfiguration &&
129 : m_pXRRRootToScreen
130 : ;
131 : }
132 :
133 : RandRWrapper::RandRWrapper( Display* pDisplay ) :
134 : m_pRandRLib( NULL ),
135 : m_pXRRQueryExtension( NULL ),
136 : m_pXRRQueryVersion( NULL ),
137 : m_pXRRGetScreenInfo( NULL ),
138 : m_pXRRFreeScreenConfigInfo( NULL ),
139 : m_pXRRSelectInput( NULL ),
140 : m_pXRRUpdateConfiguration( NULL ),
141 : m_pXRRSizes( NULL ),
142 : m_pXRRConfigSizes( NULL ),
143 : m_pXRRConfigCurrentConfiguration( NULL ),
144 : m_pXRRRootToScreen( NULL ),
145 : m_bValid( false )
146 : {
147 : // first try in process space (e.g. gtk links that ?)
148 : initFromModule();
149 : if( ! m_bValid )
150 : {
151 : // load and resolve dependencies immediately
152 : // rationale: there are older distributions where libXrandr.so.2 is not linked
153 : // with libXext.so, resulting in a missing symbol and terminating the office
154 : // obviously they expected libXext to be linked in global symbolspace (that is
155 : // linked by the application), which is not the case with us (because we want
156 : // to be able to run in headless mode even without an installed X11 library)
157 : m_pRandRLib = osl_loadModule( "libXrandr.so.2", SAL_LOADMODULE_DEFAULT | SAL_LOADMODULE_NOW );
158 : initFromModule();
159 : }
160 : if( m_bValid )
161 : {
162 : int nEventBase = 0, nErrorBase = 0;
163 : if( ! m_pXRRQueryExtension( pDisplay, &nEventBase, &nErrorBase ) )
164 : m_bValid = false;
165 : }
166 : }
167 :
168 : RandRWrapper::~RandRWrapper()
169 : {
170 : if( m_pRandRLib )
171 : osl_unloadModule( m_pRandRLib );
172 : }
173 :
174 : static RandRWrapper* pWrapper = NULL;
175 :
176 : RandRWrapper& RandRWrapper::get( Display* i_pDisplay )
177 : {
178 : if( ! pWrapper )
179 : pWrapper = new RandRWrapper( i_pDisplay );
180 : return *pWrapper;
181 : }
182 :
183 : void RandRWrapper::releaseWrapper()
184 : {
185 : delete pWrapper;
186 : pWrapper = NULL;
187 : }
188 :
189 : # else
190 :
191 : class RandRWrapper
192 : {
193 : bool m_bValid;
194 :
195 : RandRWrapper(Display*);
196 : public:
197 : static RandRWrapper& get(Display*);
198 : static void releaseWrapper();
199 :
200 0 : Bool XRRQueryExtension(Display* i_pDisp, int* o_event_base, int* o_error_base )
201 : {
202 0 : Bool bRet = False;
203 0 : if( m_bValid )
204 0 : bRet = ::XRRQueryExtension( i_pDisp, o_event_base, o_error_base );
205 0 : return bRet;
206 : }
207 : Status XRRQueryVersion( Display* i_pDisp, int* o_major, int* o_minor )
208 : {
209 : return m_bValid ? ::XRRQueryVersion( i_pDisp, o_major, o_minor ) : 0;
210 : }
211 0 : XRRScreenConfiguration* XRRGetScreenInfo( Display* i_pDisp, Drawable i_aDrawable )
212 : {
213 0 : return m_bValid ? ::XRRGetScreenInfo( i_pDisp, i_aDrawable ) : NULL;
214 : }
215 0 : void XRRFreeScreenConfigInfo( XRRScreenConfiguration* i_pConfig )
216 : {
217 0 : if( m_bValid )
218 0 : ::XRRFreeScreenConfigInfo( i_pConfig );
219 0 : }
220 0 : void XRRSelectInput( Display* i_pDisp, XLIB_Window i_window, int i_nMask )
221 : {
222 0 : if( m_bValid )
223 0 : ::XRRSelectInput( i_pDisp, i_window, i_nMask );
224 0 : }
225 0 : int XRRUpdateConfiguration( XEvent* i_pEvent )
226 : {
227 0 : return m_bValid ? ::XRRUpdateConfiguration( i_pEvent ) : 0;
228 : }
229 : XRRScreenSize* XRRSizes( Display* i_pDisp, int i_screen, int* o_nscreens )
230 : {
231 : return m_bValid ? ::XRRSizes( i_pDisp, i_screen, o_nscreens ) : NULL;
232 : }
233 0 : XRRScreenSize* XRRConfigSizes( XRRScreenConfiguration* i_pConfig, int* o_nSizes )
234 : {
235 0 : return m_bValid ? ::XRRConfigSizes( i_pConfig, o_nSizes ) : NULL;
236 : }
237 0 : SizeID XRRConfigCurrentConfiguration( XRRScreenConfiguration* i_pConfig, Rotation* o_pRot )
238 : {
239 0 : return m_bValid ? ::XRRConfigCurrentConfiguration( i_pConfig, o_pRot ) : 0;
240 : }
241 0 : int XRRRootToScreen( Display *dpy, XLIB_Window root )
242 : {
243 0 : return m_bValid ? ::XRRRootToScreen( dpy, root ) : -1;
244 : }
245 : };
246 :
247 0 : RandRWrapper::RandRWrapper( Display* pDisplay ) :
248 0 : m_bValid( true )
249 : {
250 0 : int nEventBase = 0, nErrorBase = 0;
251 0 : if( !XRRQueryExtension( pDisplay, &nEventBase, &nErrorBase ) )
252 0 : m_bValid = false;
253 0 : }
254 :
255 : static RandRWrapper* pWrapper = NULL;
256 :
257 0 : RandRWrapper& RandRWrapper::get( Display* i_pDisplay )
258 : {
259 0 : if( ! pWrapper )
260 0 : pWrapper = new RandRWrapper( i_pDisplay );
261 0 : return *pWrapper;
262 : }
263 :
264 0 : void RandRWrapper::releaseWrapper()
265 : {
266 0 : delete pWrapper;
267 0 : pWrapper = NULL;
268 0 : }
269 :
270 : #endif
271 :
272 : } // namespace
273 :
274 : #endif
275 :
276 : #include "unx/saldisp.hxx"
277 : #include "unx/salframe.h"
278 : #if OSL_DEBUG_LEVEL > 1
279 : #include <cstdio>
280 : #endif
281 :
282 0 : void SalDisplay::InitRandR( XLIB_Window aRoot ) const
283 : {
284 : #ifdef USE_RANDR
285 0 : if( m_bUseRandRWrapper )
286 0 : RandRWrapper::get( GetDisplay() ).XRRSelectInput( GetDisplay(), aRoot, RRScreenChangeNotifyMask );
287 : #else
288 : (void)aRoot;
289 : #endif
290 0 : }
291 :
292 0 : void SalDisplay::DeInitRandR()
293 : {
294 : #ifdef USE_RANDR
295 0 : if( m_bUseRandRWrapper )
296 0 : RandRWrapper::releaseWrapper();
297 : #if OSL_DEBUG_LEVEL > 1
298 : fprintf( stderr, "SalDisplay::DeInitRandR()\n" );
299 : #endif
300 : #endif
301 0 : }
302 :
303 0 : int SalDisplay::processRandREvent( XEvent* pEvent )
304 : {
305 0 : int nRet = 0;
306 : #ifdef USE_RANDR
307 0 : XConfigureEvent* pCnfEvent=(XConfigureEvent*)pEvent;
308 0 : if( m_bUseRandRWrapper && pWrapper && pWrapper->XRRRootToScreen(GetDisplay(),pCnfEvent->window) != -1 )
309 : {
310 0 : nRet = pWrapper->XRRUpdateConfiguration( pEvent );
311 0 : if( nRet == 1 && pEvent->type != ConfigureNotify) // this should then be a XRRScreenChangeNotifyEvent
312 : {
313 : // update screens
314 0 : bool bNotify = false;
315 0 : for( size_t i = 0; i < m_aScreens.size(); i++ )
316 : {
317 0 : if( m_aScreens[i].m_bInit )
318 : {
319 0 : XRRScreenConfiguration *pConfig = NULL;
320 0 : XRRScreenSize *pSizes = NULL;
321 0 : int nSizes = 0;
322 0 : Rotation nRot = 0;
323 0 : SizeID nId = 0;
324 :
325 0 : pConfig = pWrapper->XRRGetScreenInfo( GetDisplay(), m_aScreens[i].m_aRoot );
326 0 : nId = pWrapper->XRRConfigCurrentConfiguration( pConfig, &nRot );
327 0 : pSizes = pWrapper->XRRConfigSizes( pConfig, &nSizes );
328 0 : XRRScreenSize *pTargetSize = pSizes + nId;
329 :
330 0 : bNotify = bNotify ||
331 0 : m_aScreens[i].m_aSize.Width() != pTargetSize->width ||
332 0 : m_aScreens[i].m_aSize.Height() != pTargetSize->height;
333 :
334 0 : m_aScreens[i].m_aSize = Size( pTargetSize->width, pTargetSize->height );
335 :
336 0 : pWrapper->XRRFreeScreenConfigInfo( pConfig );
337 :
338 : #if OSL_DEBUG_LEVEL > 1
339 : fprintf( stderr, "screen %d changed to size %dx%d\n", (int)i, (int)pTargetSize->width, (int)pTargetSize->height );
340 : #endif
341 : }
342 : }
343 0 : if( bNotify )
344 0 : emitDisplayChanged();
345 : }
346 : }
347 : #else
348 : (void)pEvent;
349 : #endif
350 0 : return nRet;
351 : }
352 :
353 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|