/* * * Copyright © 1999 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 Keith Packard not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. Keith Packard makes no * representations about the suitability of this software for any purpose. It * is provided "as is" without express or implied warranty. * * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL KEITH PACKARD 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. */ #ifdef HAVE_CONFIG_H #include #endif #include "kdrive.h" #include #include #include #include "micmap.h" #ifdef DPMSExtension #include "dpmsproc.h" #endif typedef struct _kdDepths { CARD8 depth; CARD8 bpp; } KdDepths; static const KdDepths kdDepths[] = { {1, 1}, {4, 4}, {8, 8}, {15, 16}, {16, 16}, {24, 32}, {32, 32} }; #define NUM_KD_DEPTHS (sizeof (kdDepths) / sizeof (kdDepths[0])) int kdScreenPrivateIndex; static unsigned long kdGeneration; static Bool kdEmulateMiddleButton; static Bool kdRawPointerCoordinates; Bool kdDisableZaphod; Bool kdDontZap; static Bool kdEnabled; static int kdSubpixelOrder; int kdVirtualTerminal = -1; Bool kdSwitchPending; static const char *kdSwitchCmd; static DDXPointRec kdOrigin; /* * Carry arguments from InitOutput through driver initialization * to KdScreenInit */ const KdOsFuncs *kdOsFuncs; static void KdSetRootClip(ScreenPtr pScreen, BOOL enable) { WindowPtr pWin = WindowTable[pScreen->myNum]; WindowPtr pChild; Bool WasViewable; Bool anyMarked = FALSE; WindowPtr pLayerWin; BoxRec box; if (!pWin) return; WasViewable = (Bool) (pWin->viewable); if (WasViewable) { for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) { (void)(*pScreen->MarkOverlappedWindows) (pChild, pChild, &pLayerWin); } (*pScreen->MarkWindow) (pWin); anyMarked = TRUE; if (pWin->valdata) { if (HasBorder(pWin)) { RegionPtr borderVisible; borderVisible = REGION_CREATE(NullBox, 1); REGION_SUBTRACT(borderVisible, &pWin->borderClip, &pWin->winSize); pWin->valdata->before.borderVisible = borderVisible; } pWin->valdata->before.resized = TRUE; } } if (enable) { box.x1 = 0; box.y1 = 0; box.x2 = pScreen->width; box.y2 = pScreen->height; BoxRec *boxptr = &box; pWin->drawable.width = pScreen->width; pWin->drawable.height = pScreen->height; REGION_INIT(&pWin->winSize, boxptr, 1); REGION_INIT(&pWin->borderSize, boxptr, 1); REGION_RESET(&pWin->borderClip, &box); REGION_BREAK(&pWin->clipList); } else { REGION_EMPTY(&pWin->borderClip); REGION_BREAK(&pWin->clipList); } ResizeChildrenWinSize(pWin, 0, 0, 0, 0); if (WasViewable) { if (pWin->firstChild) { anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin->firstChild, pWin->firstChild, (WindowPtr *) NULL); } else { (*pScreen->MarkWindow) (pWin); anyMarked = TRUE; } if (anyMarked) (*pScreen->ValidateTree) (pWin, NullWindow, VTOther); } if (WasViewable) { if (anyMarked) (*pScreen->HandleExposures) (pWin); if (anyMarked && pScreen->PostValidateTree) (*pScreen->PostValidateTree) (pWin, NullWindow, VTOther); } if (pWin->realized) WindowsRestructured(); } void KdDisableScreen(ScreenPtr pScreen) { KdScreenPriv(pScreen); if (!pScreenPriv->enabled) return; if (!pScreenPriv->closed) KdSetRootClip(pScreen, FALSE); KdDisableColormap(pScreen); if (!pScreenPriv->screen->dumb && pScreenPriv->card->cfuncs->disableAccel) (*pScreenPriv->card->cfuncs->disableAccel) (pScreen); if (!pScreenPriv->screen->softCursor && pScreenPriv->card->cfuncs->disableCursor) (*pScreenPriv->card->cfuncs->disableCursor) (pScreen); if (pScreenPriv->card->cfuncs->dpms) (*pScreenPriv->card->cfuncs->dpms) (pScreen, KD_DPMS_NORMAL); pScreenPriv->enabled = FALSE; if (pScreenPriv->card->cfuncs->disable) (*pScreenPriv->card->cfuncs->disable) (pScreen); } static void KdDoSwitchCmd(const char *const reason) { if (kdSwitchCmd) { char *command; if (asprintf(&command, "%s %s", kdSwitchCmd, reason) == -1) return; system(command); free(command); } } void KdSuspend(void) { KdCardInfo *card; KdScreenInfo *screen; if (kdEnabled) { for (card = kdCardInfo; card; card = card->next) { for (screen = card->screenList; screen; screen = screen->next) if (screen->mynum == card->selected && screen->pScreen) KdDisableScreen(screen->pScreen); if (card->driver && card->cfuncs->restore) (*card->cfuncs->restore) (card); } KdDisableInput(); KdDoSwitchCmd("suspend"); } } static void KdDisableScreens(void) { KdSuspend(); if (kdEnabled) { if (kdOsFuncs->Disable) (*kdOsFuncs->Disable) (); kdEnabled = FALSE; } } Bool KdEnableScreen(ScreenPtr pScreen) { KdScreenPriv(pScreen); if (pScreenPriv->enabled) return TRUE; if (pScreenPriv->card->cfuncs->enable) if (!(*pScreenPriv->card->cfuncs->enable) (pScreen)) return FALSE; pScreenPriv->enabled = TRUE; pScreenPriv->dpmsState = KD_DPMS_NORMAL; pScreenPriv->card->selected = pScreenPriv->screen->mynum; if (!pScreenPriv->screen->softCursor && pScreenPriv->card->cfuncs->enableCursor) (*pScreenPriv->card->cfuncs->enableCursor) (pScreen); if (!pScreenPriv->screen->dumb && pScreenPriv->card->cfuncs->enableAccel) (*pScreenPriv->card->cfuncs->enableAccel) (pScreen); KdEnableColormap(pScreen); KdSetRootClip(pScreen, TRUE); if (pScreenPriv->card->cfuncs->dpms) (*pScreenPriv->card->cfuncs->dpms) (pScreen, pScreenPriv->dpmsState); return TRUE; } void KdResume(void) { KdCardInfo *card; KdScreenInfo *screen; if (kdEnabled) { KdDoSwitchCmd("resume"); for (card = kdCardInfo; card; card = card->next) { if (card->cfuncs->preserve) (*card->cfuncs->preserve) (card); for (screen = card->screenList; screen; screen = screen->next) if (screen->mynum == card->selected && screen->pScreen) KdEnableScreen(screen->pScreen); } KdEnableInput(); KdReleaseAllKeys(); } } static void KdEnableScreens(void) { if (!kdEnabled) { kdEnabled = TRUE; if (kdOsFuncs->Enable) (*kdOsFuncs->Enable) (); } KdResume(); } void KdProcessSwitch(void) { if (kdEnabled) KdDisableScreens(); else KdEnableScreens(); } void AbortDDX(void) { KdDisableScreens(); if (kdOsFuncs) { if (kdEnabled && kdOsFuncs->Disable) (*kdOsFuncs->Disable) (); if (kdOsFuncs->Fini) (*kdOsFuncs->Fini) (); KdDoSwitchCmd("stop"); } } void ddxGiveUp() { AbortDDX(); } static Bool kdDumbDriver; static Bool kdSoftCursor; static const char *KdParseFindNext(const char *cur, const char *delim, char *save, char *last) { while (*cur && !strchr(delim, *cur)) { *save++ = *cur++; } *save = 0; *last = *cur; if (*cur) cur++; return cur; } Rotation KdAddRotation(Rotation a, Rotation b) { Rotation rotate = (a & RR_Rotate_All) * (b & RR_Rotate_All); Rotation reflect = (a & RR_Reflect_All) ^ (b & RR_Reflect_All); if (rotate > RR_Rotate_270) rotate /= (RR_Rotate_270 * RR_Rotate_90); return reflect | rotate; } Rotation KdSubRotation(Rotation a, Rotation b) { Rotation rotate = (a & RR_Rotate_All) * 16 / (b & RR_Rotate_All); Rotation reflect = (a & RR_Reflect_All) ^ (b & RR_Reflect_All); if (rotate > RR_Rotate_270) rotate /= (RR_Rotate_270 * RR_Rotate_90); return reflect | rotate; } static void KdParseScreen(KdScreenInfo * screen, const char *arg) { char delim; char save[1024]; int i; int pixels, mm; screen->dumb = kdDumbDriver; screen->softCursor = kdSoftCursor; screen->origin = kdOrigin; screen->randr = RR_Rotate_0; screen->width = 0; screen->height = 0; screen->width_mm = 0; screen->height_mm = 0; screen->subpixel_order = kdSubpixelOrder; screen->rate = 0; screen->fb.depth = 0; if (!arg) return; if (strlen(arg) >= sizeof(save)) return; for (i = 0; i < 2; i++) { arg = KdParseFindNext(arg, "x/@XY", save, &delim); if (!save[0]) return; pixels = atoi(save); mm = 0; if (delim == '/') { arg = KdParseFindNext(arg, "x@XY", save, &delim); if (!save[0]) return; mm = atoi(save); } if (i == 0) { screen->width = pixels; screen->width_mm = mm; } else { screen->height = pixels; screen->height_mm = mm; } if (delim != 'x' && delim != '@' && delim != 'X' && delim != 'Y') return; } kdOrigin.x += screen->width; kdOrigin.y = 0; kdDumbDriver = FALSE; kdSoftCursor = FALSE; kdSubpixelOrder = SubPixelUnknown; if (delim == '@') { arg = KdParseFindNext(arg, "xXY", save, &delim); if (save[0]) { int rotate = atoi(save); if (rotate < 45) screen->randr = RR_Rotate_0; else if (rotate < 135) screen->randr = RR_Rotate_90; else if (rotate < 225) screen->randr = RR_Rotate_180; else if (rotate < 315) screen->randr = RR_Rotate_270; else screen->randr = RR_Rotate_0; } } if (delim == 'X') { arg = KdParseFindNext(arg, "xY", save, &delim); screen->randr |= RR_Reflect_X; } if (delim == 'Y') { arg = KdParseFindNext(arg, "xY", save, &delim); screen->randr |= RR_Reflect_Y; } arg = KdParseFindNext(arg, "x/,", save, &delim); if (save[0]) { screen->fb.depth = atoi(save); if (delim == '/') { arg = KdParseFindNext(arg, "x,", save, &delim); if (save[0]) screen->fb.bitsPerPixel = atoi(save); } else screen->fb.bitsPerPixel = 0; } if (delim == 'x') { KdParseFindNext(arg, "x", save, &delim); if (save[0]) screen->rate = atoi(save); } } /* * Mouse argument syntax: * * device,protocol,options... * * Options are any of: * 1-5 n button mouse * 2button emulate middle button * {NMO} Reorder buttons */ /* * Parse mouse information. Syntax: * * ,,{,