/* * Copyright © 2006 Keith Packard * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that copyright * notice and this permission notice appear in supporting documentation, and * that the name of the copyright holders not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. The copyright holders make no representations * about the suitability of this software for any purpose. It is provided "as * is" without express or implied warranty. * * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ #include "randrstr.h" /** * Returns the width/height that the crtc scans out from the framebuffer */ static void RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height) { if (crtc->mode == NULL) { *width = 0; *height = 0; return; } switch (crtc->rotation & 0xf) { case RR_Rotate_0: case RR_Rotate_180: *width = crtc->mode->mode.width; *height = crtc->mode->mode.height; break; case RR_Rotate_90: case RR_Rotate_270: *width = crtc->mode->mode.height; *height = crtc->mode->mode.width; break; } } /* * When the pointer moves, check to see if the specified position is outside * any of theavailable CRTCs and move it to a 'sensible' place if so, where * sensible is the closest monitor to the departing edge. * * Returns whether the position was adjusted */ static Bool RRCrtcContainsPosition (RRCrtcPtr crtc, int x, int y) { RRModePtr mode = crtc->mode; int scan_width, scan_height; if (!mode) return FALSE; RRCrtcGetScanoutSize (crtc, &scan_width, &scan_height); if (crtc->x <= x && x < crtc->x + scan_width && crtc->y <= y && y < crtc->y + scan_height) return TRUE; return FALSE; } /* * Find the CRTC nearest the specified position, ignoring 'skip' */ static void RRPointerToNearestCrtc (ScreenPtr pScreen, int x, int y, RRCrtcPtr skip) { rrScrPriv (pScreen); int c; RRCrtcPtr nearest = NULL; int best = 0; int best_dx = 0, best_dy = 0; for (c = 0; c < pScrPriv->numCrtcs; c++) { RRCrtcPtr crtc = pScrPriv->crtcs[c]; RRModePtr mode = crtc->mode; int dx, dy; int dist; int scan_width, scan_height; if (!mode) continue; if (crtc == skip) continue; RRCrtcGetScanoutSize (crtc, &scan_width, &scan_height); if (x < crtc->x) dx = crtc->x - x; else if (x > crtc->x + scan_width) dx = x - (crtc->x + scan_width); else dx = 0; if (y < crtc->y) dy = crtc->y - x; else if (y > crtc->y + scan_height) dy = y - (crtc->y + scan_height); else dy = 0; dist = dx + dy; if (!nearest || dist < best) { nearest = crtc; best_dx = dx; best_dy = dy; } } if (best_dx || best_dy) (*pScreen->SetCursorPosition) (pScreen, x + best_dx, y + best_dy, TRUE); pScrPriv->pointerCrtc = nearest; } void RRPointerMoved (ScreenPtr pScreen, int x, int y) { rrScrPriv (pScreen); RRCrtcPtr pointerCrtc = pScrPriv->pointerCrtc;; int c; /* Check last known CRTC */ if (pointerCrtc && RRCrtcContainsPosition (pointerCrtc, x, y)) return; /* Check all CRTCs */ for (c = 0; c < pScrPriv->numCrtcs; c++) { RRCrtcPtr crtc = pScrPriv->crtcs[c]; if (RRCrtcContainsPosition (crtc, x, y)) { /* Remember containing CRTC */ pScrPriv->pointerCrtc = crtc; return; } } /* None contain pointer, find nearest */ RRPointerToNearestCrtc (pScreen, x, y, pointerCrtc); } /* * When the screen is reconfigured, move the pointer to the nearest * CRTC */ void RRPointerScreenConfigured (ScreenPtr pScreen) { WindowPtr pRoot = GetCurrentRootWindow (); ScreenPtr pCurrentScreen = pRoot ? pRoot->drawable.pScreen : NULL; int x, y; if (pScreen != pCurrentScreen) return; GetSpritePosition (&x, &y); RRPointerToNearestCrtc (pScreen, x, y, NULL); }