Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #ifdef USE_RANDR
30 : :
31 : : #include <tools/prex.h>
32 : : #include <X11/extensions/Xrandr.h>
33 : : #include <tools/postx.h>
34 : :
35 : : #include "osl/module.h"
36 : : #include "rtl/ustring.hxx"
37 : :
38 : : namespace
39 : : {
40 : :
41 : : # ifdef XRANDR_DLOPEN
42 : :
43 : : class RandRWrapper
44 : : {
45 : : oslModule m_pRandRLib;
46 : :
47 : : // function pointers
48 : : Bool(*m_pXRRQueryExtension)(Display*,int*,int*);
49 : : Status(*m_pXRRQueryVersion)(Display*,int*,int*);
50 : : XRRScreenConfiguration*(*m_pXRRGetScreenInfo)(Display*,Drawable);
51 : : void(*m_pXRRFreeScreenConfigInfo)(XRRScreenConfiguration*);
52 : : void(*m_pXRRSelectInput)(Display*,XLIB_Window,int);
53 : : int(*m_pXRRUpdateConfiguration)(XEvent*);
54 : : XRRScreenSize*(*m_pXRRSizes)(Display*,int,int*);
55 : : XRRScreenSize*(*m_pXRRConfigSizes)(XRRScreenConfiguration*,int*);
56 : : SizeID(*m_pXRRConfigCurrentConfiguration)(XRRScreenConfiguration*,Rotation*);
57 : : int(*m_pXRRRootToScreen)(Display*, XLIB_Window);
58 : :
59 : : bool m_bValid;
60 : :
61 : : void initFromModule();
62 : :
63 : : RandRWrapper(Display*);
64 : : ~RandRWrapper();
65 : : public:
66 : : static RandRWrapper& get(Display*);
67 : : static void releaseWrapper();
68 : :
69 : : Bool XRRQueryExtension(Display* i_pDisp, int* o_event_base, int* o_error_base )
70 : : {
71 : : Bool bRet = False;
72 : : if( m_bValid )
73 : : bRet = m_pXRRQueryExtension( i_pDisp, o_event_base, o_error_base );
74 : : return bRet;
75 : : }
76 : : Status XRRQueryVersion( Display* i_pDisp, int* o_major, int* o_minor )
77 : : {
78 : : return m_bValid ? m_pXRRQueryVersion( i_pDisp, o_major, o_minor ) : 0;
79 : : }
80 : : XRRScreenConfiguration* XRRGetScreenInfo( Display* i_pDisp, Drawable i_aDrawable )
81 : : {
82 : : return m_bValid ? m_pXRRGetScreenInfo( i_pDisp, i_aDrawable ) : NULL;
83 : : }
84 : : void XRRFreeScreenConfigInfo( XRRScreenConfiguration* i_pConfig )
85 : : {
86 : : if( m_bValid )
87 : : m_pXRRFreeScreenConfigInfo( i_pConfig );
88 : : }
89 : : void XRRSelectInput( Display* i_pDisp, XLIB_Window i_window, int i_nMask )
90 : : {
91 : : if( m_bValid )
92 : : m_pXRRSelectInput( i_pDisp, i_window, i_nMask );
93 : : }
94 : : int XRRUpdateConfiguration( XEvent* i_pEvent )
95 : : {
96 : : return m_bValid ? m_pXRRUpdateConfiguration( i_pEvent ) : 0;
97 : : }
98 : : XRRScreenSize* XRRSizes( Display* i_pDisp, int i_screen, int* o_nscreens )
99 : : {
100 : : return m_bValid ? m_pXRRSizes( i_pDisp, i_screen, o_nscreens ) : NULL;
101 : : }
102 : : XRRScreenSize* XRRConfigSizes( XRRScreenConfiguration* i_pConfig, int* o_nSizes )
103 : : {
104 : : return m_bValid ? m_pXRRConfigSizes( i_pConfig, o_nSizes ) : NULL;
105 : : }
106 : : SizeID XRRConfigCurrentConfiguration( XRRScreenConfiguration* i_pConfig, Rotation* o_pRot )
107 : : {
108 : : return m_bValid ? m_pXRRConfigCurrentConfiguration( i_pConfig, o_pRot ) : 0;
109 : : }
110 : : int XRRRootToScreen( Display *dpy, XLIB_Window root )
111 : : {
112 : : return m_bValid ? m_pXRRRootToScreen( dpy, root ) : -1;
113 : : }
114 : : };
115 : :
116 : : void RandRWrapper::initFromModule()
117 : : {
118 : : m_pXRRQueryExtension = (Bool(*)(Display*,int*,int*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRQueryExtension" );
119 : : m_pXRRQueryVersion = (Status(*)(Display*,int*,int*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRQueryVersion" );
120 : : m_pXRRGetScreenInfo = (XRRScreenConfiguration*(*)(Display*,Drawable))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRGetScreenInfo" );
121 : : m_pXRRFreeScreenConfigInfo = (void(*)(XRRScreenConfiguration*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRFreeScreenConfigInfo" );
122 : : m_pXRRSelectInput = (void(*)(Display*,XLIB_Window,int))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRSelectInput" );
123 : : m_pXRRUpdateConfiguration = (int(*)(XEvent*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRUpdateConfiguration" );
124 : : m_pXRRSizes = (XRRScreenSize*(*)(Display*,int,int*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRSizes" );
125 : : m_pXRRConfigSizes = (XRRScreenSize*(*)(XRRScreenConfiguration*,int*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRConfigSizes" );
126 : : m_pXRRConfigCurrentConfiguration = (SizeID(*)(XRRScreenConfiguration*,Rotation*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRConfigCurrentConfiguration" );
127 : : m_pXRRRootToScreen = (int(*)(Display*,XLIB_Window))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRRootToScreen" );
128 : :
129 : : m_bValid = m_pXRRQueryExtension &&
130 : : m_pXRRQueryVersion &&
131 : : m_pXRRGetScreenInfo &&
132 : : m_pXRRFreeScreenConfigInfo &&
133 : : m_pXRRSelectInput &&
134 : : m_pXRRUpdateConfiguration &&
135 : : m_pXRRSizes &&
136 : : m_pXRRConfigSizes &&
137 : : m_pXRRConfigCurrentConfiguration &&
138 : : m_pXRRRootToScreen
139 : : ;
140 : : }
141 : :
142 : : RandRWrapper::RandRWrapper( Display* pDisplay ) :
143 : : m_pRandRLib( NULL ),
144 : : m_pXRRQueryExtension( NULL ),
145 : : m_pXRRQueryVersion( NULL ),
146 : : m_pXRRGetScreenInfo( NULL ),
147 : : m_pXRRFreeScreenConfigInfo( NULL ),
148 : : m_pXRRSelectInput( NULL ),
149 : : m_pXRRUpdateConfiguration( NULL ),
150 : : m_pXRRSizes( NULL ),
151 : : m_pXRRConfigSizes( NULL ),
152 : : m_pXRRConfigCurrentConfiguration( NULL ),
153 : : m_pXRRRootToScreen( NULL ),
154 : : m_bValid( false )
155 : : {
156 : : // first try in process space (e.g. gtk links that ?)
157 : : initFromModule();
158 : : if( ! m_bValid )
159 : : {
160 : : rtl::OUString aLibName( RTL_CONSTASCII_USTRINGPARAM( "libXrandr.so.2" ) );
161 : : // load and resolve dependencies immediately
162 : : // rationale: there are older distributions where libXrandr.so.2 is not linked
163 : : // with libXext.so, resulting in a missing symbol and terminating the office
164 : : // obviously they expected libXext to be linked in global symbolspace (that is
165 : : // linked by the application), which is not the case with us (because we want
166 : : // to be able to run in headless mode even without an installed X11 library)
167 : : m_pRandRLib = osl_loadModule( aLibName.pData, SAL_LOADMODULE_DEFAULT | SAL_LOADMODULE_NOW );
168 : : initFromModule();
169 : : }
170 : : if( m_bValid )
171 : : {
172 : : int nEventBase = 0, nErrorBase = 0;
173 : : if( ! m_pXRRQueryExtension( pDisplay, &nEventBase, &nErrorBase ) )
174 : : m_bValid = false;
175 : : }
176 : : }
177 : :
178 : : RandRWrapper::~RandRWrapper()
179 : : {
180 : : if( m_pRandRLib )
181 : : osl_unloadModule( m_pRandRLib );
182 : : }
183 : :
184 : : static RandRWrapper* pWrapper = NULL;
185 : :
186 : : RandRWrapper& RandRWrapper::get( Display* i_pDisplay )
187 : : {
188 : : if( ! pWrapper )
189 : : pWrapper = new RandRWrapper( i_pDisplay );
190 : : return *pWrapper;
191 : : }
192 : :
193 : : void RandRWrapper::releaseWrapper()
194 : : {
195 : : delete pWrapper;
196 : : pWrapper = NULL;
197 : : }
198 : :
199 : : # else
200 : :
201 : : class RandRWrapper
202 : : {
203 : : bool m_bValid;
204 : :
205 : : RandRWrapper(Display*);
206 : : public:
207 : : static RandRWrapper& get(Display*);
208 : : static void releaseWrapper();
209 : :
210 : 0 : Bool XRRQueryExtension(Display* i_pDisp, int* o_event_base, int* o_error_base )
211 : : {
212 : 0 : Bool bRet = False;
213 : 0 : if( m_bValid )
214 : 0 : bRet = ::XRRQueryExtension( i_pDisp, o_event_base, o_error_base );
215 : 0 : return bRet;
216 : : }
217 : : Status XRRQueryVersion( Display* i_pDisp, int* o_major, int* o_minor )
218 : : {
219 : : return m_bValid ? ::XRRQueryVersion( i_pDisp, o_major, o_minor ) : 0;
220 : : }
221 : 0 : XRRScreenConfiguration* XRRGetScreenInfo( Display* i_pDisp, Drawable i_aDrawable )
222 : : {
223 : 0 : return m_bValid ? ::XRRGetScreenInfo( i_pDisp, i_aDrawable ) : NULL;
224 : : }
225 : 0 : void XRRFreeScreenConfigInfo( XRRScreenConfiguration* i_pConfig )
226 : : {
227 : 0 : if( m_bValid )
228 : 0 : ::XRRFreeScreenConfigInfo( i_pConfig );
229 : 0 : }
230 : 0 : void XRRSelectInput( Display* i_pDisp, XLIB_Window i_window, int i_nMask )
231 : : {
232 : 0 : if( m_bValid )
233 : 0 : ::XRRSelectInput( i_pDisp, i_window, i_nMask );
234 : 0 : }
235 : 0 : int XRRUpdateConfiguration( XEvent* i_pEvent )
236 : : {
237 : 0 : return m_bValid ? ::XRRUpdateConfiguration( i_pEvent ) : 0;
238 : : }
239 : : XRRScreenSize* XRRSizes( Display* i_pDisp, int i_screen, int* o_nscreens )
240 : : {
241 : : return m_bValid ? ::XRRSizes( i_pDisp, i_screen, o_nscreens ) : NULL;
242 : : }
243 : 0 : XRRScreenSize* XRRConfigSizes( XRRScreenConfiguration* i_pConfig, int* o_nSizes )
244 : : {
245 : 0 : return m_bValid ? ::XRRConfigSizes( i_pConfig, o_nSizes ) : NULL;
246 : : }
247 : 0 : SizeID XRRConfigCurrentConfiguration( XRRScreenConfiguration* i_pConfig, Rotation* o_pRot )
248 : : {
249 : 0 : return m_bValid ? ::XRRConfigCurrentConfiguration( i_pConfig, o_pRot ) : 0;
250 : : }
251 : 0 : int XRRRootToScreen( Display *dpy, XLIB_Window root )
252 : : {
253 : 0 : return m_bValid ? ::XRRRootToScreen( dpy, root ) : -1;
254 : : }
255 : : };
256 : :
257 : 0 : RandRWrapper::RandRWrapper( Display* pDisplay ) :
258 : 0 : m_bValid( true )
259 : : {
260 : 0 : int nEventBase = 0, nErrorBase = 0;
261 : 0 : if( !XRRQueryExtension( pDisplay, &nEventBase, &nErrorBase ) )
262 : 0 : m_bValid = false;
263 : 0 : }
264 : :
265 : : static RandRWrapper* pWrapper = NULL;
266 : :
267 : 0 : RandRWrapper& RandRWrapper::get( Display* i_pDisplay )
268 : : {
269 : 0 : if( ! pWrapper )
270 : 0 : pWrapper = new RandRWrapper( i_pDisplay );
271 : 0 : return *pWrapper;
272 : : }
273 : :
274 : 0 : void RandRWrapper::releaseWrapper()
275 : : {
276 : 0 : delete pWrapper;
277 : 0 : pWrapper = NULL;
278 : 0 : }
279 : :
280 : : #endif
281 : :
282 : : } // namespace
283 : :
284 : : #endif
285 : :
286 : : #include "unx/saldisp.hxx"
287 : : #include "unx/salframe.h"
288 : : #if OSL_DEBUG_LEVEL > 1
289 : : #include <cstdio>
290 : : #endif
291 : :
292 : 0 : void SalDisplay::InitRandR( XLIB_Window aRoot ) const
293 : : {
294 : : #ifdef USE_RANDR
295 : 0 : if( m_bUseRandRWrapper )
296 : 0 : RandRWrapper::get( GetDisplay() ).XRRSelectInput( GetDisplay(), aRoot, RRScreenChangeNotifyMask );
297 : : #else
298 : : (void)aRoot;
299 : : #endif
300 : 0 : }
301 : :
302 : 0 : void SalDisplay::DeInitRandR()
303 : : {
304 : : #ifdef USE_RANDR
305 : 0 : if( m_bUseRandRWrapper )
306 : 0 : RandRWrapper::releaseWrapper();
307 : : #if OSL_DEBUG_LEVEL > 1
308 : : fprintf( stderr, "SalDisplay::DeInitRandR()\n" );
309 : : #endif
310 : : #endif
311 : 0 : }
312 : :
313 : 0 : int SalDisplay::processRandREvent( XEvent* pEvent )
314 : : {
315 : 0 : int nRet = 0;
316 : : #ifdef USE_RANDR
317 : 0 : XConfigureEvent* pCnfEvent=(XConfigureEvent*)pEvent;
318 : 0 : if( m_bUseRandRWrapper && pWrapper && pWrapper->XRRRootToScreen(GetDisplay(),pCnfEvent->window) != -1 )
319 : : {
320 : 0 : nRet = pWrapper->XRRUpdateConfiguration( pEvent );
321 : 0 : if( nRet == 1 && pEvent->type != ConfigureNotify) // this should then be a XRRScreenChangeNotifyEvent
322 : : {
323 : : // update screens
324 : 0 : bool bNotify = false;
325 : 0 : for( size_t i = 0; i < m_aScreens.size(); i++ )
326 : : {
327 : 0 : if( m_aScreens[i].m_bInit )
328 : : {
329 : 0 : XRRScreenConfiguration *pConfig = NULL;
330 : 0 : XRRScreenSize *pSizes = NULL;
331 : 0 : int nSizes = 0;
332 : 0 : Rotation nRot = 0;
333 : 0 : SizeID nId = 0;
334 : :
335 : 0 : pConfig = pWrapper->XRRGetScreenInfo( GetDisplay(), m_aScreens[i].m_aRoot );
336 : 0 : nId = pWrapper->XRRConfigCurrentConfiguration( pConfig, &nRot );
337 : 0 : pSizes = pWrapper->XRRConfigSizes( pConfig, &nSizes );
338 : 0 : XRRScreenSize *pTargetSize = pSizes + nId;
339 : :
340 : : bNotify = bNotify ||
341 : 0 : m_aScreens[i].m_aSize.Width() != pTargetSize->width ||
342 : 0 : m_aScreens[i].m_aSize.Height() != pTargetSize->height;
343 : :
344 : 0 : m_aScreens[i].m_aSize = Size( pTargetSize->width, pTargetSize->height );
345 : :
346 : 0 : pWrapper->XRRFreeScreenConfigInfo( pConfig );
347 : :
348 : : #if OSL_DEBUG_LEVEL > 1
349 : : fprintf( stderr, "screen %d changed to size %dx%d\n", (int)i, (int)pTargetSize->width, (int)pTargetSize->height );
350 : : #endif
351 : : }
352 : : }
353 : 0 : if( bNotify )
354 : 0 : emitDisplayChanged();
355 : : }
356 : : }
357 : : #else
358 : : (void)pEvent;
359 : : #endif
360 : 0 : return nRet;
361 : : }
362 : :
363 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|