3 * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of Keith Packard not be used in
10 * advertising or publicity pertaining to distribution of the software without
11 * specific, written prior permission. Keith Packard makes no
12 * representations about the suitability of this software for any purpose. It
13 * is provided "as is" without express or implied warranty.
15 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21 * PERFORMANCE OF THIS SOFTWARE.
24 #ifdef HAVE_XORG_CONFIG_H
25 #include <xorg-config.h>
35 #include "mipointer.h"
39 typedef struct _xf86RandRInfo
{
40 CreateScreenResourcesProcPtr CreateScreenResources
;
41 CloseScreenProcPtr CloseScreen
;
47 } XF86RandRInfoRec
, *XF86RandRInfoPtr
;
49 static DevPrivateKeyRec xf86RandRKeyRec
;
50 static DevPrivateKey xf86RandRKey
;
52 #define XF86RANDRINFO(p) ((XF86RandRInfoPtr)dixLookupPrivate(&(p)->devPrivates, xf86RandRKey))
55 xf86RandRModeRefresh(DisplayModePtr mode
)
58 return (int) (mode
->VRefresh
+ 0.5);
59 else if (mode
->Clock
== 0)
62 return (int) (mode
->Clock
* 1000.0 / mode
->HTotal
/ mode
->VTotal
+ 0.5);
66 xf86RandRGetInfo(ScreenPtr pScreen
, Rotation
* rotations
)
68 RRScreenSizePtr pSize
;
69 ScrnInfoPtr scrp
= xf86ScreenToScrn(pScreen
);
70 XF86RandRInfoPtr randrp
= XF86RANDRINFO(pScreen
);
73 xorgRRModeMM RRModeMM
;
75 *rotations
= RR_Rotate_0
;
77 for (mode
= scrp
->modes
; mode
!= NULL
; mode
= mode
->next
) {
78 int refresh
= xf86RandRModeRefresh(mode
);
80 if (mode
== scrp
->modes
)
84 RRModeMM
.virtX
= randrp
->virtualX
;
85 RRModeMM
.virtY
= randrp
->virtualY
;
86 RRModeMM
.mmWidth
= randrp
->mmWidth
;
87 RRModeMM
.mmHeight
= randrp
->mmHeight
;
89 if (scrp
->DriverFunc
) {
90 (*scrp
->DriverFunc
) (scrp
, RR_GET_MODE_MM
, &RRModeMM
);
93 pSize
= RRRegisterSize(pScreen
,
94 mode
->HDisplay
, mode
->VDisplay
,
95 RRModeMM
.mmWidth
, RRModeMM
.mmHeight
);
98 RRRegisterRate(pScreen
, pSize
, refresh
);
99 if (mode
== scrp
->currentMode
&&
100 mode
->HDisplay
== scrp
->virtualX
&&
101 mode
->VDisplay
== scrp
->virtualY
)
102 RRSetCurrentConfig(pScreen
, randrp
->rotation
, refresh
, pSize
);
103 if (mode
->next
== scrp
->modes
)
106 if (scrp
->currentMode
->HDisplay
!= randrp
->virtualX
||
107 scrp
->currentMode
->VDisplay
!= randrp
->virtualY
) {
110 RRModeMM
.mode
= NULL
;
111 RRModeMM
.virtX
= randrp
->virtualX
;
112 RRModeMM
.virtY
= randrp
->virtualY
;
113 RRModeMM
.mmWidth
= randrp
->mmWidth
;
114 RRModeMM
.mmHeight
= randrp
->mmHeight
;
116 if (scrp
->DriverFunc
) {
117 (*scrp
->DriverFunc
) (scrp
, RR_GET_MODE_MM
, &RRModeMM
);
120 pSize
= RRRegisterSize(pScreen
,
121 randrp
->virtualX
, randrp
->virtualY
,
122 RRModeMM
.mmWidth
, RRModeMM
.mmHeight
);
125 RRRegisterRate(pScreen
, pSize
, refresh0
);
126 if (scrp
->virtualX
== randrp
->virtualX
&&
127 scrp
->virtualY
== randrp
->virtualY
) {
128 RRSetCurrentConfig(pScreen
, randrp
->rotation
, refresh0
, pSize
);
132 /* If there is driver support for randr, let it set our supported rotations */
133 if (scrp
->DriverFunc
) {
134 xorgRRRotation RRRotation
;
136 RRRotation
.RRRotations
= *rotations
;
137 if (!(*scrp
->DriverFunc
) (scrp
, RR_GET_INFO
, &RRRotation
))
139 *rotations
= RRRotation
.RRRotations
;
146 xf86RandRSetMode(ScreenPtr pScreen
,
148 Bool useVirtual
, int mmWidth
, int mmHeight
)
150 ScrnInfoPtr scrp
= xf86ScreenToScrn(pScreen
);
151 XF86RandRInfoPtr randrp
= XF86RANDRINFO(pScreen
);
152 int oldWidth
= pScreen
->width
;
153 int oldHeight
= pScreen
->height
;
154 int oldmmWidth
= pScreen
->mmWidth
;
155 int oldmmHeight
= pScreen
->mmHeight
;
156 int oldVirtualX
= scrp
->virtualX
;
157 int oldVirtualY
= scrp
->virtualY
;
158 WindowPtr pRoot
= pScreen
->root
;
161 if (pRoot
&& scrp
->vtSema
)
162 (*scrp
->EnableDisableFBAccess
) (scrp
, FALSE
);
164 scrp
->virtualX
= randrp
->virtualX
;
165 scrp
->virtualY
= randrp
->virtualY
;
168 scrp
->virtualX
= mode
->HDisplay
;
169 scrp
->virtualY
= mode
->VDisplay
;
173 * The DIX forgets the physical dimensions we passed into RRRegisterSize, so
174 * reconstruct them if possible.
176 if (scrp
->DriverFunc
) {
177 xorgRRModeMM RRModeMM
;
179 RRModeMM
.mode
= mode
;
180 RRModeMM
.virtX
= scrp
->virtualX
;
181 RRModeMM
.virtY
= scrp
->virtualY
;
182 RRModeMM
.mmWidth
= mmWidth
;
183 RRModeMM
.mmHeight
= mmHeight
;
185 (*scrp
->DriverFunc
) (scrp
, RR_GET_MODE_MM
, &RRModeMM
);
187 mmWidth
= RRModeMM
.mmWidth
;
188 mmHeight
= RRModeMM
.mmHeight
;
190 if (randrp
->rotation
& (RR_Rotate_90
| RR_Rotate_270
)) {
191 /* If the screen is rotated 90 or 270 degrees, swap the sizes. */
192 pScreen
->width
= scrp
->virtualY
;
193 pScreen
->height
= scrp
->virtualX
;
194 pScreen
->mmWidth
= mmHeight
;
195 pScreen
->mmHeight
= mmWidth
;
198 pScreen
->width
= scrp
->virtualX
;
199 pScreen
->height
= scrp
->virtualY
;
200 pScreen
->mmWidth
= mmWidth
;
201 pScreen
->mmHeight
= mmHeight
;
203 if (!xf86SwitchMode(pScreen
, mode
)) {
204 pScreen
->width
= oldWidth
;
205 pScreen
->height
= oldHeight
;
206 pScreen
->mmWidth
= oldmmWidth
;
207 pScreen
->mmHeight
= oldmmHeight
;
208 scrp
->virtualX
= oldVirtualX
;
209 scrp
->virtualY
= oldVirtualY
;
213 * Make sure the layout is correct
215 xf86ReconfigureLayout();
219 * Make sure the whole screen is visible
221 xf86SetViewport (pScreen
, pScreen
->width
, pScreen
->height
);
222 xf86SetViewport (pScreen
, 0, 0);
224 (*scrp
->EnableDisableFBAccess
) (scrp
, TRUE
);
230 xf86RandRSetConfig(ScreenPtr pScreen
,
231 Rotation rotation
, int rate
, RRScreenSizePtr pSize
)
233 ScrnInfoPtr scrp
= xf86ScreenToScrn(pScreen
);
234 XF86RandRInfoPtr randrp
= XF86RANDRINFO(pScreen
);
236 int pos
[MAXDEVICES
][2];
237 Bool useVirtual
= FALSE
;
238 Rotation oldRotation
= randrp
->rotation
;
240 Bool view_adjusted
= FALSE
;
242 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
) {
243 if (!IsMaster(dev
) && !IsFloating(dev
))
246 miPointerGetPosition(dev
, &pos
[dev
->id
][0], &pos
[dev
->id
][1]);
249 for (mode
= scrp
->modes
;; mode
= mode
->next
) {
250 if (mode
->HDisplay
== pSize
->width
&&
251 mode
->VDisplay
== pSize
->height
&&
252 (rate
== 0 || xf86RandRModeRefresh(mode
) == rate
))
254 if (mode
->next
== scrp
->modes
) {
255 if (pSize
->width
== randrp
->virtualX
&&
256 pSize
->height
== randrp
->virtualY
) {
265 if (randrp
->rotation
!= rotation
) {
267 /* Have the driver do its thing. */
268 if (scrp
->DriverFunc
) {
269 xorgRRRotation RRRotation
;
271 RRRotation
.RRConfig
.rotation
= rotation
;
272 RRRotation
.RRConfig
.rate
= rate
;
273 RRRotation
.RRConfig
.width
= pSize
->width
;
274 RRRotation
.RRConfig
.height
= pSize
->height
;
277 * Currently we need to rely on HW support for rotation.
279 if (!(*scrp
->DriverFunc
) (scrp
, RR_SET_CONFIG
, &RRRotation
))
285 randrp
->rotation
= rotation
;
288 if (!xf86RandRSetMode
289 (pScreen
, mode
, useVirtual
, pSize
->mmWidth
, pSize
->mmHeight
)) {
290 if (randrp
->rotation
!= oldRotation
) {
291 /* Have the driver undo its thing. */
292 if (scrp
->DriverFunc
) {
293 xorgRRRotation RRRotation
;
295 RRRotation
.RRConfig
.rotation
= oldRotation
;
296 RRRotation
.RRConfig
.rate
=
297 xf86RandRModeRefresh(scrp
->currentMode
);
298 RRRotation
.RRConfig
.width
= scrp
->virtualX
;
299 RRRotation
.RRConfig
.height
= scrp
->virtualY
;
300 (*scrp
->DriverFunc
) (scrp
, RR_SET_CONFIG
, &RRRotation
);
303 randrp
->rotation
= oldRotation
;
308 update_desktop_dimensions();
311 * Move the cursor back where it belongs; SwitchMode repositions it
312 * FIXME: duplicated code, see modes/xf86RandR12.c
314 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
) {
315 if (!IsMaster(dev
) && !IsFloating(dev
))
318 if (pScreen
== miPointerGetScreen(dev
)) {
319 int px
= pos
[dev
->id
][0];
320 int py
= pos
[dev
->id
][1];
322 px
= (px
>= pScreen
->width
? (pScreen
->width
- 1) : px
);
323 py
= (py
>= pScreen
->height
? (pScreen
->height
- 1) : py
);
325 /* Setting the viewpoint makes only sense on one device */
326 if (!view_adjusted
&& IsMaster(dev
)) {
327 xf86SetViewport(pScreen
, px
, py
);
328 view_adjusted
= TRUE
;
331 (*pScreen
->SetCursorPosition
) (dev
, pScreen
, px
, py
, FALSE
);
339 * Wait until the screen is initialized before whacking the
340 * sizes around; otherwise the screen pixmap will be allocated
341 * at the current mode size rather than the maximum size
344 xf86RandRCreateScreenResources(ScreenPtr pScreen
)
346 XF86RandRInfoPtr randrp
= XF86RANDRINFO(pScreen
);
349 ScrnInfoPtr scrp
= xf86ScreenToScrn(pScreen
);
353 pScreen
->CreateScreenResources
= randrp
->CreateScreenResources
;
354 if (!(*pScreen
->CreateScreenResources
) (pScreen
))
358 mode
= scrp
->currentMode
;
360 xf86RandRSetMode(pScreen
, mode
, TRUE
);
367 * Reset size back to original
370 xf86RandRCloseScreen(ScreenPtr pScreen
)
372 ScrnInfoPtr scrp
= xf86ScreenToScrn(pScreen
);
373 XF86RandRInfoPtr randrp
= XF86RANDRINFO(pScreen
);
375 scrp
->virtualX
= pScreen
->width
= randrp
->virtualX
;
376 scrp
->virtualY
= pScreen
->height
= randrp
->virtualY
;
377 scrp
->currentMode
= scrp
->modes
;
378 pScreen
->CloseScreen
= randrp
->CloseScreen
;
380 dixSetPrivate(&pScreen
->devPrivates
, xf86RandRKey
, NULL
);
381 return (*pScreen
->CloseScreen
) (pScreen
);
385 xf86GetRotation(ScreenPtr pScreen
)
387 if (xf86RandRKey
== NULL
)
390 return XF86RANDRINFO(pScreen
)->rotation
;
393 /* Function to change RandR's idea of the virtual screen size */
395 xf86RandRSetNewVirtualAndDimensions(ScreenPtr pScreen
,
396 int newvirtX
, int newvirtY
, int newmmWidth
,
397 int newmmHeight
, Bool resetMode
)
399 XF86RandRInfoPtr randrp
;
401 if (xf86RandRKey
== NULL
)
404 randrp
= XF86RANDRINFO(pScreen
);
409 randrp
->virtualX
= newvirtX
;
412 randrp
->virtualY
= newvirtY
;
415 randrp
->mmWidth
= newmmWidth
;
418 randrp
->mmHeight
= newmmHeight
;
420 /* This is only for during server start */
422 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
423 return (xf86RandRSetMode(pScreen
,
425 TRUE
, pScreen
->mmWidth
, pScreen
->mmHeight
));
432 xf86RandRInit(ScreenPtr pScreen
)
435 XF86RandRInfoPtr randrp
;
436 ScrnInfoPtr scrp
= xf86ScreenToScrn(pScreen
);
439 /* XXX disable RandR when using Xinerama */
440 if (!noPanoramiXExtension
)
444 xf86RandRKey
= &xf86RandRKeyRec
;
446 if (!dixRegisterPrivateKey(&xf86RandRKeyRec
, PRIVATE_SCREEN
, 0))
449 randrp
= malloc(sizeof(XF86RandRInfoRec
));
453 if (!RRScreenInit(pScreen
)) {
457 rp
= rrGetScrPriv(pScreen
);
458 rp
->rrGetInfo
= xf86RandRGetInfo
;
459 rp
->rrSetConfig
= xf86RandRSetConfig
;
461 randrp
->virtualX
= scrp
->virtualX
;
462 randrp
->virtualY
= scrp
->virtualY
;
463 randrp
->mmWidth
= pScreen
->mmWidth
;
464 randrp
->mmHeight
= pScreen
->mmHeight
;
466 randrp
->CreateScreenResources
= pScreen
->CreateScreenResources
;
467 pScreen
->CreateScreenResources
= xf86RandRCreateScreenResources
;
469 randrp
->CloseScreen
= pScreen
->CloseScreen
;
470 pScreen
->CloseScreen
= xf86RandRCloseScreen
;
472 randrp
->rotation
= RR_Rotate_0
;
474 dixSetPrivate(&pScreen
->devPrivates
, xf86RandRKey
, randrp
);