/* * $XFree86: xc/programs/Xserver/hw/tinyx/tinyx.c,v 1.1 2004/06/02 22:43:00 dawes Exp $ * * 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. */ /* * Copyright (c) 2004 by The XFree86 Project, Inc. * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject * to the following conditions: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution, and in the same place and form as other copyright, * license and disclaimer information. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: "This product * includes software developed by The XFree86 Project, Inc * (http://www.xfree86.org/) and its contributors", in the same * place and form as other third-party acknowledgments. Alternately, * this acknowledgment may appear in the software itself, in the * same form and location as other such third-party acknowledgments. * * 4. Except as contained in this notice, the name of The XFree86 * Project, Inc shall not be used in advertising or otherwise to * promote the sale, use or other dealings in this Software without * prior written authorization from The XFree86 Project, Inc. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE XFREE86 PROJECT, INC OR ITS CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "tinyx.h" #ifdef PSEUDO8 #include "pseudo8/pseudo8.h" #endif #include #include #ifdef RANDR #include #endif #ifdef XV #include "txxv.h" #endif #ifdef DPMSExtension #include "dpmsproc.h" #endif CARD8 kdBpp[] = { 1, 4, 8, 16, 24, 32 }; #define NUM_KD_BPP (sizeof (kdBpp) / sizeof (kdBpp[0])) int kdScreenPrivateIndex; unsigned long kdGeneration; Bool kdVideoTest; unsigned long kdVideoTestTime; Bool kdEmulateMiddleButton; Bool kdDisableZaphod; Bool kdEnabled; int kdSubpixelOrder; int kdVirtualTerminal = -1; Bool kdSwitchPending; DDXPointRec kdOrigin; /* * Carry arguments from InitOutput through driver initialization * to KdScreenInit */ KdOsFuncs *kdOsFuncs; void KdSetRootClip (ScreenPtr pScreen, BOOL enable) { #ifndef FB_OLD_SCREEN WindowPtr pWin = WindowTable[pScreen->myNum]; WindowPtr pChild; Bool WasViewable; Bool anyMarked = FALSE; RegionPtr pOldClip = NULL, bsExposed; #ifdef DO_SAVE_UNDERS Bool dosave = FALSE; #endif 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(pScreen, NullBox, 1); REGION_SUBTRACT(pScreen, 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; pWin->drawable.width = pScreen->width; pWin->drawable.height = pScreen->height; REGION_INIT (pScreen, &pWin->winSize, &box, 1); REGION_INIT (pScreen, &pWin->borderSize, &box, 1); REGION_RESET(pScreen, &pWin->borderClip, &box); REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); } else { REGION_EMPTY(pScreen, &pWin->borderClip); REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); } ResizeChildrenWinSize (pWin, 0, 0, 0, 0); if (WasViewable) { if (pWin->backStorage) { pOldClip = REGION_CREATE(pScreen, NullBox, 1); REGION_COPY(pScreen, pOldClip, &pWin->clipList); } if (pWin->firstChild) { anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild, pWin->firstChild, (WindowPtr *)NULL); } else { (*pScreen->MarkWindow) (pWin); anyMarked = TRUE; } #ifdef DO_SAVE_UNDERS if (DO_SAVE_UNDERS(pWin)) { dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin); } #endif /* DO_SAVE_UNDERS */ if (anyMarked) (*pScreen->ValidateTree)(pWin, NullWindow, VTOther); } if (pWin->backStorage && ((pWin->backingStore == Always) || WasViewable)) { if (!WasViewable) pOldClip = &pWin->clipList; /* a convenient empty region */ bsExposed = (*pScreen->TranslateBackingStore) (pWin, 0, 0, pOldClip, pWin->drawable.x, pWin->drawable.y); if (WasViewable) REGION_DESTROY(pScreen, pOldClip); if (bsExposed) { RegionPtr valExposed = NullRegion; if (pWin->valdata) valExposed = &pWin->valdata->after.exposed; (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); if (valExposed) REGION_EMPTY(pScreen, valExposed); REGION_DESTROY(pScreen, bsExposed); } } if (WasViewable) { if (anyMarked) (*pScreen->HandleExposures)(pWin); #ifdef DO_SAVE_UNDERS if (dosave) (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); #endif /* DO_SAVE_UNDERS */ if (anyMarked && pScreen->PostValidateTree) (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther); } if (pWin->realized) WindowsRestructured (); #endif /* !FB_OLD_SCREEN */ } void KdDisableScreen (ScreenPtr pScreen) { KdScreenPriv(pScreen); if (!pScreenPriv->enabled) return; KdCheckSync (pScreen); if (!pScreenPriv->closed) KdSetRootClip (pScreen, FALSE); KdDisableColormap (pScreen); if (!pScreenPriv->screen->dumb) (*pScreenPriv->card->cfuncs->disableAccel) (pScreen); if (!pScreenPriv->screen->softCursor) (*pScreenPriv->card->cfuncs->disableCursor) (pScreen); if (pScreenPriv->card->cfuncs->dpms) (*pScreenPriv->card->cfuncs->dpms) (pScreen, KD_DPMS_NORMAL); pScreenPriv->enabled = FALSE; (*pScreenPriv->card->cfuncs->disable) (pScreen); } 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); } KdDisableInput (); } } void KdDisableScreens (void) { KdSuspend (); if (kdEnabled) { (*kdOsFuncs->Disable) (); kdEnabled = FALSE; } } Bool KdEnableScreen (ScreenPtr pScreen) { KdScreenPriv (pScreen); if (pScreenPriv->enabled) return TRUE; if (!(*pScreenPriv->card->cfuncs->enable) (pScreen)) return FALSE; pScreenPriv->enabled = TRUE; pScreenPriv->card->selected = pScreenPriv->screen->mynum; if (!pScreenPriv->screen->softCursor) (*pScreenPriv->card->cfuncs->enableCursor) (pScreen); if (!pScreenPriv->screen->dumb) (*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) { for (card = kdCardInfo; card; card = card->next) { (*card->cfuncs->preserve) (card); for (screen = card->screenList; screen; screen = screen->next) if (screen->mynum == card->selected && screen->pScreen) KdEnableScreen (screen->pScreen); } KdEnableInput (); KdReleaseAllKeys (); } } void KdEnableScreens (void) { if (!kdEnabled) { kdEnabled = TRUE; (*kdOsFuncs->Enable) (); } KdResume (); } void KdProcessSwitch (void) { if (kdEnabled) KdDisableScreens (); else { KdEnableScreens (); } } void AbortDDX(void) { KdDisableScreens (); if (kdOsFuncs) { if (kdEnabled) (*kdOsFuncs->Disable) (); (*kdOsFuncs->Fini) (); } } void KdUseMsg() { ErrorF("\nTinyX Device Dependent Usage:\n"); ErrorF("-card pcmcia Use PCMCIA card as additional screen\n"); ErrorF("-screen WIDTH[/WIDTHMM]xHEIGHT[/HEIGHTMM][@ROTATION][X][Y][xDEPTH/BPP{,DEPTH/BPP}[xFREQ]] Specify screen characteristics\n"); ErrorF("-zaphod Disable cursor screen switching\n"); ErrorF("-2button Emulate 3 button mouse\n"); ErrorF("-3button Disable 3 button mouse emulation\n"); ErrorF("-dumb Disable hardware acceleration\n"); ErrorF("-softCursor Force software cursor\n"); ErrorF("-videoTest Start the server, pause momentarily and exit\n"); ErrorF("-origin X,Y Locates the next screen in the the virtual screen (Xinerama)\n"); ErrorF("-mouse path[,n] Filename of mouse device, n is number of buttons\n"); ErrorF("vtxx Use virtual terminal xx instead of the next available\n"); ErrorF("\n"); } void ddxGiveUp () { AbortDDX (); } Bool kdDumbDriver; Bool kdSoftCursor; static char * KdParseFindNext (char *cur, 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; } void KdParseScreen (KdScreenInfo *screen, char *arg) { char delim; char save[1024]; int fb; 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; for (fb = 0; fb < KD_MAX_FB; fb++) screen->fb[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; } fb = 0; while (fb < KD_MAX_FB) { arg = KdParseFindNext (arg, "x/,", save, &delim); if (!save[0]) break; screen->fb[fb].depth = atoi(save); if (delim == '/') { arg = KdParseFindNext (arg, "x,", save, &delim); if (!save[0]) break; screen->fb[fb].bitsPerPixel = atoi (save); } else screen->fb[fb].bitsPerPixel = 0; if (delim != ',') break; fb++; } if (delim == 'x') { arg = 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 */ char * KdSaveString (char *str) { char *n = (char *) xalloc (strlen (str) + 1); if (!n) return 0; strcpy (n, str); return n; } /* * Parse mouse information. Syntax: * * ,,{,