1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
23 #include <X11/extensions/Xrandr.h>
26 #include "osl/module.h"
27 #include "rtl/ustring.hxx"
36 oslModule m_pRandRLib
;
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
);
50 void initFromModule();
52 RandRWrapper(Display
*);
55 static RandRWrapper
& get(Display
*);
56 static void releaseWrapper();
58 Bool
XRRQueryExtension(Display
* i_pDisp
, int* o_event_base
, int* o_error_base
)
62 bRet
= m_pXRRQueryExtension( i_pDisp
, o_event_base
, o_error_base
);
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
)
72 m_pXRRFreeScreenConfigInfo( i_pConfig
);
74 void XRRSelectInput( Display
* i_pDisp
, ::Window i_window
, int i_nMask
)
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
&&
112 m_pXRRUpdateConfiguration
&&
114 m_pXRRConfigCurrentConfiguration
&&
119 RandRWrapper::RandRWrapper( Display
* pDisplay
) :
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
),
131 // first try in process space (e.g. gtk links that ?)
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
);
146 int nEventBase
= 0, nErrorBase
= 0;
147 if( ! m_pXRRQueryExtension( pDisplay
, &nEventBase
, &nErrorBase
) )
152 RandRWrapper::~RandRWrapper()
155 osl_unloadModule( m_pRandRLib
);
158 static RandRWrapper
* pWrapper
= NULL
;
160 RandRWrapper
& RandRWrapper::get( Display
* i_pDisplay
)
163 pWrapper
= new RandRWrapper( i_pDisplay
);
167 void RandRWrapper::releaseWrapper()
179 RandRWrapper(Display
*);
181 static RandRWrapper
& get(Display
*);
182 static void releaseWrapper();
184 Bool
XRRQueryExtension(Display
* i_pDisp
, int* o_event_base
, int* o_error_base
)
188 bRet
= ::XRRQueryExtension( i_pDisp
, o_event_base
, o_error_base
);
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
)
198 ::XRRFreeScreenConfigInfo( i_pConfig
);
200 void XRRSelectInput( Display
* i_pDisp
, ::Window i_window
, int i_nMask
)
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
) :
226 int nEventBase
= 0, nErrorBase
= 0;
227 if( !XRRQueryExtension( pDisplay
, &nEventBase
, &nErrorBase
) )
231 static RandRWrapper
* pWrapper
= NULL
;
233 RandRWrapper
& RandRWrapper::get( Display
* i_pDisplay
)
236 pWrapper
= new RandRWrapper( i_pDisplay
);
240 void RandRWrapper::releaseWrapper()
252 #include "unx/saldisp.hxx"
253 #include "unx/salframe.h"
254 #if OSL_DEBUG_LEVEL > 1
258 void SalDisplay::InitRandR( ::Window aRoot
) const
261 if( m_bUseRandRWrapper
)
262 RandRWrapper::get( GetDisplay() ).XRRSelectInput( GetDisplay(), aRoot
, RRScreenChangeNotifyMask
);
268 void SalDisplay::DeInitRandR()
271 if( m_bUseRandRWrapper
)
272 RandRWrapper::releaseWrapper();
273 #if OSL_DEBUG_LEVEL > 1
274 fprintf( stderr
, "SalDisplay::DeInitRandR()\n" );
279 int SalDisplay::processRandREvent( XEvent
* pEvent
)
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
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
;
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
;
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
);
320 emitDisplayChanged();
329 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */