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 <tools/prex.h>
23 : #include <X11/extensions/Xrandr.h>
24 : #include <tools/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 : rtl::OUString aLibName( RTL_CONSTASCII_USTRINGPARAM( "libXrandr.so.2" ) );
152 : // load and resolve dependencies immediately
153 : // rationale: there are older distributions where libXrandr.so.2 is not linked
154 : // with libXext.so, resulting in a missing symbol and terminating the office
155 : // obviously they expected libXext to be linked in global symbolspace (that is
156 : // linked by the application), which is not the case with us (because we want
157 : // to be able to run in headless mode even without an installed X11 library)
158 : m_pRandRLib = osl_loadModule( aLibName.pData, SAL_LOADMODULE_DEFAULT | SAL_LOADMODULE_NOW );
159 : initFromModule();
160 : }
161 : if( m_bValid )
162 : {
163 : int nEventBase = 0, nErrorBase = 0;
164 : if( ! m_pXRRQueryExtension( pDisplay, &nEventBase, &nErrorBase ) )
165 : m_bValid = false;
166 : }
167 : }
168 :
169 : RandRWrapper::~RandRWrapper()
170 : {
171 : if( m_pRandRLib )
172 : osl_unloadModule( m_pRandRLib );
173 : }
174 :
175 : static RandRWrapper* pWrapper = NULL;
176 :
177 : RandRWrapper& RandRWrapper::get( Display* i_pDisplay )
178 : {
179 : if( ! pWrapper )
180 : pWrapper = new RandRWrapper( i_pDisplay );
181 : return *pWrapper;
182 : }
183 :
184 : void RandRWrapper::releaseWrapper()
185 : {
186 : delete pWrapper;
187 : pWrapper = NULL;
188 : }
189 :
190 : # else
191 :
192 : class RandRWrapper
193 : {
194 : bool m_bValid;
195 :
196 : RandRWrapper(Display*);
197 : public:
198 : static RandRWrapper& get(Display*);
199 : static void releaseWrapper();
200 :
201 0 : Bool XRRQueryExtension(Display* i_pDisp, int* o_event_base, int* o_error_base )
202 : {
203 0 : Bool bRet = False;
204 0 : if( m_bValid )
205 0 : bRet = ::XRRQueryExtension( i_pDisp, o_event_base, o_error_base );
206 0 : return bRet;
207 : }
208 : Status XRRQueryVersion( Display* i_pDisp, int* o_major, int* o_minor )
209 : {
210 : return m_bValid ? ::XRRQueryVersion( i_pDisp, o_major, o_minor ) : 0;
211 : }
212 0 : XRRScreenConfiguration* XRRGetScreenInfo( Display* i_pDisp, Drawable i_aDrawable )
213 : {
214 0 : return m_bValid ? ::XRRGetScreenInfo( i_pDisp, i_aDrawable ) : NULL;
215 : }
216 0 : void XRRFreeScreenConfigInfo( XRRScreenConfiguration* i_pConfig )
217 : {
218 0 : if( m_bValid )
219 0 : ::XRRFreeScreenConfigInfo( i_pConfig );
220 0 : }
221 0 : void XRRSelectInput( Display* i_pDisp, XLIB_Window i_window, int i_nMask )
222 : {
223 0 : if( m_bValid )
224 0 : ::XRRSelectInput( i_pDisp, i_window, i_nMask );
225 0 : }
226 0 : int XRRUpdateConfiguration( XEvent* i_pEvent )
227 : {
228 0 : return m_bValid ? ::XRRUpdateConfiguration( i_pEvent ) : 0;
229 : }
230 : XRRScreenSize* XRRSizes( Display* i_pDisp, int i_screen, int* o_nscreens )
231 : {
232 : return m_bValid ? ::XRRSizes( i_pDisp, i_screen, o_nscreens ) : NULL;
233 : }
234 0 : XRRScreenSize* XRRConfigSizes( XRRScreenConfiguration* i_pConfig, int* o_nSizes )
235 : {
236 0 : return m_bValid ? ::XRRConfigSizes( i_pConfig, o_nSizes ) : NULL;
237 : }
238 0 : SizeID XRRConfigCurrentConfiguration( XRRScreenConfiguration* i_pConfig, Rotation* o_pRot )
239 : {
240 0 : return m_bValid ? ::XRRConfigCurrentConfiguration( i_pConfig, o_pRot ) : 0;
241 : }
242 0 : int XRRRootToScreen( Display *dpy, XLIB_Window root )
243 : {
244 0 : return m_bValid ? ::XRRRootToScreen( dpy, root ) : -1;
245 : }
246 : };
247 :
248 0 : RandRWrapper::RandRWrapper( Display* pDisplay ) :
249 0 : m_bValid( true )
250 : {
251 0 : int nEventBase = 0, nErrorBase = 0;
252 0 : if( !XRRQueryExtension( pDisplay, &nEventBase, &nErrorBase ) )
253 0 : m_bValid = false;
254 0 : }
255 :
256 : static RandRWrapper* pWrapper = NULL;
257 :
258 0 : RandRWrapper& RandRWrapper::get( Display* i_pDisplay )
259 : {
260 0 : if( ! pWrapper )
261 0 : pWrapper = new RandRWrapper( i_pDisplay );
262 0 : return *pWrapper;
263 : }
264 :
265 0 : void RandRWrapper::releaseWrapper()
266 : {
267 0 : delete pWrapper;
268 0 : pWrapper = NULL;
269 0 : }
270 :
271 : #endif
272 :
273 : } // namespace
274 :
275 : #endif
276 :
277 : #include "unx/saldisp.hxx"
278 : #include "unx/salframe.h"
279 : #if OSL_DEBUG_LEVEL > 1
280 : #include <cstdio>
281 : #endif
282 :
283 0 : void SalDisplay::InitRandR( XLIB_Window aRoot ) const
284 : {
285 : #ifdef USE_RANDR
286 0 : if( m_bUseRandRWrapper )
287 0 : RandRWrapper::get( GetDisplay() ).XRRSelectInput( GetDisplay(), aRoot, RRScreenChangeNotifyMask );
288 : #else
289 : (void)aRoot;
290 : #endif
291 0 : }
292 :
293 0 : void SalDisplay::DeInitRandR()
294 : {
295 : #ifdef USE_RANDR
296 0 : if( m_bUseRandRWrapper )
297 0 : RandRWrapper::releaseWrapper();
298 : #if OSL_DEBUG_LEVEL > 1
299 : fprintf( stderr, "SalDisplay::DeInitRandR()\n" );
300 : #endif
301 : #endif
302 0 : }
303 :
304 0 : int SalDisplay::processRandREvent( XEvent* pEvent )
305 : {
306 0 : int nRet = 0;
307 : #ifdef USE_RANDR
308 0 : XConfigureEvent* pCnfEvent=(XConfigureEvent*)pEvent;
309 0 : if( m_bUseRandRWrapper && pWrapper && pWrapper->XRRRootToScreen(GetDisplay(),pCnfEvent->window) != -1 )
310 : {
311 0 : nRet = pWrapper->XRRUpdateConfiguration( pEvent );
312 0 : if( nRet == 1 && pEvent->type != ConfigureNotify) // this should then be a XRRScreenChangeNotifyEvent
313 : {
314 : // update screens
315 0 : bool bNotify = false;
316 0 : for( size_t i = 0; i < m_aScreens.size(); i++ )
317 : {
318 0 : if( m_aScreens[i].m_bInit )
319 : {
320 0 : XRRScreenConfiguration *pConfig = NULL;
321 0 : XRRScreenSize *pSizes = NULL;
322 0 : int nSizes = 0;
323 0 : Rotation nRot = 0;
324 0 : SizeID nId = 0;
325 :
326 0 : pConfig = pWrapper->XRRGetScreenInfo( GetDisplay(), m_aScreens[i].m_aRoot );
327 0 : nId = pWrapper->XRRConfigCurrentConfiguration( pConfig, &nRot );
328 0 : pSizes = pWrapper->XRRConfigSizes( pConfig, &nSizes );
329 0 : XRRScreenSize *pTargetSize = pSizes + nId;
330 :
331 : bNotify = bNotify ||
332 0 : m_aScreens[i].m_aSize.Width() != pTargetSize->width ||
333 0 : m_aScreens[i].m_aSize.Height() != pTargetSize->height;
334 :
335 0 : m_aScreens[i].m_aSize = Size( pTargetSize->width, pTargetSize->height );
336 :
337 0 : pWrapper->XRRFreeScreenConfigInfo( pConfig );
338 :
339 : #if OSL_DEBUG_LEVEL > 1
340 : fprintf( stderr, "screen %d changed to size %dx%d\n", (int)i, (int)pTargetSize->width, (int)pTargetSize->height );
341 : #endif
342 : }
343 : }
344 0 : if( bNotify )
345 0 : emitDisplayChanged();
346 : }
347 : }
348 : #else
349 : (void)pEvent;
350 : #endif
351 0 : return nRet;
352 : }
353 :
354 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|