diff options
Diffstat (limited to 'xorg-server/hw')
-rw-r--r-- | xorg-server/hw/kdrive/src/kdrive.c | 2467 | ||||
-rw-r--r-- | xorg-server/hw/kdrive/src/kdrive.h | 1253 | ||||
-rw-r--r-- | xorg-server/hw/kdrive/src/kinput.c | 4659 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/common/xf86Helper.c | 104 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/common/xf86Xinput.c | 2820 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/dri/dri.c | 5000 | ||||
-rw-r--r-- | xorg-server/hw/xquartz/applewm.c | 1472 | ||||
-rw-r--r-- | xorg-server/hw/xquartz/darwin.c | 1650 | ||||
-rw-r--r-- | xorg-server/hw/xquartz/darwin.h | 183 | ||||
-rw-r--r-- | xorg-server/hw/xquartz/darwinXinput.c | 322 | ||||
-rw-r--r-- | xorg-server/hw/xquartz/quartz.c | 2 | ||||
-rw-r--r-- | xorg-server/hw/xquartz/threadSafety.h | 2 | ||||
-rw-r--r-- | xorg-server/hw/xquartz/xpr/xprScreen.c | 2 | ||||
-rw-r--r-- | xorg-server/hw/xwin/winrandr.c | 104 |
14 files changed, 9811 insertions, 10229 deletions
diff --git a/xorg-server/hw/kdrive/src/kdrive.c b/xorg-server/hw/kdrive/src/kdrive.c index 7f42248c0..f034ce463 100644 --- a/xorg-server/hw/kdrive/src/kdrive.c +++ b/xorg-server/hw/kdrive/src/kdrive.c @@ -1,1278 +1,1189 @@ -/*
- * 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 <kdrive-config.h>
-#endif
-#include "kdrive.h"
-#include <mivalidate.h>
-#include <dixstruct.h>
-#include "privates.h"
-#ifdef RANDR
-#include <randrstr.h>
-#endif
-
-#ifdef XV
-#include "kxv.h"
-#endif
-
-#ifdef DPMSExtension
-#include "dpmsproc.h"
-#endif
-
-#ifdef HAVE_EXECINFO_H
-#include <execinfo.h>
-#endif
-
-#include <signal.h>
-
-typedef struct _kdDepths {
- CARD8 depth;
- CARD8 bpp;
-} KdDepths;
-
-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]))
-
-#define KD_DEFAULT_BUTTONS 5
-
-DevPrivateKeyRec kdScreenPrivateKeyRec;
-unsigned long kdGeneration;
-
-Bool kdVideoTest;
-unsigned long kdVideoTestTime;
-Bool kdEmulateMiddleButton;
-Bool kdRawPointerCoordinates;
-Bool kdDisableZaphod;
-Bool kdAllowZap;
-Bool kdEnabled;
-int kdSubpixelOrder;
-int kdVirtualTerminal = -1;
-Bool kdSwitchPending;
-char *kdSwitchCmd;
-DDXPointRec kdOrigin;
-Bool kdHasPointer = FALSE;
-Bool kdHasKbd = FALSE;
-
-static Bool kdCaughtSignal = FALSE;
-
-/*
- * Carry arguments from InitOutput through driver initialization
- * to KdScreenInit
- */
-
-KdOsFuncs *kdOsFuncs;
-
-void
-KdSetRootClip (ScreenPtr pScreen, BOOL enable)
-{
- WindowPtr pWin = pScreen->root;
- 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 = RegionCreate(NullBox, 1);
- RegionSubtract(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;
- RegionInit(&pWin->winSize, &box, 1);
- RegionInit(&pWin->borderSize, &box, 1);
- RegionReset(&pWin->borderClip, &box);
- RegionBreak(&pWin->clipList);
- }
- else
- {
- RegionEmpty(&pWin->borderClip);
- RegionBreak(&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 (char *reason)
-{
- if (kdSwitchCmd)
- {
- char *command = malloc(strlen (kdSwitchCmd) +
- 1 +
- strlen (reason) +
- 1);
- if (!command)
- return;
- strcpy (command, kdSwitchCmd);
- strcat (command, " ");
- strcat (command, reason);
- 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");
- }
-}
-
-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 ();
- }
-}
-
-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");
- }
-
- if (kdCaughtSignal)
- OsAbort();
-}
-
-void
-ddxGiveUp (void)
-{
- AbortDDX ();
-}
-
-Bool kdDumbDriver;
-Bool kdSoftCursor;
-
-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 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')
- {
- 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
- */
-
-void
-KdParseRgba (char *rgba)
-{
- if (!strcmp (rgba, "rgb"))
- kdSubpixelOrder = SubPixelHorizontalRGB;
- else if (!strcmp (rgba, "bgr"))
- kdSubpixelOrder = SubPixelHorizontalBGR;
- else if (!strcmp (rgba, "vrgb"))
- kdSubpixelOrder = SubPixelVerticalRGB;
- else if (!strcmp (rgba, "vbgr"))
- kdSubpixelOrder = SubPixelVerticalBGR;
- else if (!strcmp (rgba, "none"))
- kdSubpixelOrder = SubPixelNone;
- else
- kdSubpixelOrder = SubPixelUnknown;
-}
-
-void
-KdUseMsg (void)
-{
- ErrorF("\nTinyX Device Dependent Usage:\n");
- ErrorF("-screen WIDTH[/WIDTHMM]xHEIGHT[/HEIGHTMM][@ROTATION][X][Y][xDEPTH/BPP[xFREQ]] Specify screen characteristics\n");
- ErrorF("-rgba rgb/bgr/vrgb/vbgr/none Specify subpixel ordering for LCD panels\n");
- ErrorF("-mouse driver [,n,,options] Specify the pointer driver and its options (n is the number of buttons)\n");
- ErrorF("-keybd driver [,,options] Specify the keyboard driver and its options\n");
- ErrorF("-zaphod Disable cursor screen switching\n");
- ErrorF("-2button Emulate 3 button mouse\n");
- ErrorF("-3button Disable 3 button mouse emulation\n");
- ErrorF("-rawcoord Don't transform pointer coordinates on rotation\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("-switchCmd Command to execute on vt switch\n");
- ErrorF("-zap Terminate server on Ctrl+Alt+Backspace\n");
- ErrorF("vtxx Use virtual terminal xx instead of the next available\n");
-}
-
-int
-KdProcessArgument (int argc, char **argv, int i)
-{
- KdCardInfo *card;
- KdScreenInfo *screen;
-
- if (!strcmp (argv[i], "-screen"))
- {
- if ((i+1) < argc)
- {
- card = KdCardInfoLast ();
- if (!card)
- {
- InitCard (0);
- card = KdCardInfoLast ();
- }
- if (card) {
- screen = KdScreenInfoAdd (card);
- KdParseScreen (screen, argv[i+1]);
- } else
- ErrorF("No matching card found!\n");
- }
- else
- UseMsg ();
- return 2;
- }
- if (!strcmp (argv[i], "-zaphod"))
- {
- kdDisableZaphod = TRUE;
- return 1;
- }
- if (!strcmp (argv[i], "-zap"))
- {
- kdAllowZap = TRUE;
- return 1;
- }
- if (!strcmp (argv[i], "-3button"))
- {
- kdEmulateMiddleButton = FALSE;
- return 1;
- }
- if (!strcmp (argv[i], "-2button"))
- {
- kdEmulateMiddleButton = TRUE;
- return 1;
- }
- if (!strcmp (argv[i], "-rawcoord"))
- {
- kdRawPointerCoordinates = 1;
- return 1;
- }
- if (!strcmp (argv[i], "-dumb"))
- {
- kdDumbDriver = TRUE;
- return 1;
- }
- if (!strcmp (argv[i], "-softCursor"))
- {
- kdSoftCursor = TRUE;
- return 1;
- }
- if (!strcmp (argv[i], "-videoTest"))
- {
- kdVideoTest = TRUE;
- return 1;
- }
- if (!strcmp (argv[i], "-origin"))
- {
- if ((i+1) < argc)
- {
- char *x = argv[i+1];
- char *y = strchr (x, ',');
- if (x)
- kdOrigin.x = atoi (x);
- else
- kdOrigin.x = 0;
- if (y)
- kdOrigin.y = atoi(y+1);
- else
- kdOrigin.y = 0;
- }
- else
- UseMsg ();
- return 2;
- }
- if (!strcmp (argv[i], "-rgba"))
- {
- if ((i+1) < argc)
- KdParseRgba (argv[i+1]);
- else
- UseMsg ();
- return 2;
- }
- if (!strcmp (argv[i], "-switchCmd"))
- {
- if ((i+1) < argc)
- kdSwitchCmd = argv[i+1];
- else
- UseMsg ();
- return 2;
- }
- if (!strncmp (argv[i], "vt", 2) &&
- sscanf (argv[i], "vt%2d", &kdVirtualTerminal) == 1)
- {
- return 1;
- }
- if (!strcmp (argv[i], "-mouse") ||
- !strcmp (argv[i], "-pointer")) {
- if (i + 1 >= argc)
- UseMsg();
- KdAddConfigPointer(argv[i + 1]);
- kdHasPointer = TRUE;
- return 2;
- }
- if (!strcmp (argv[i], "-keybd")) {
- if (i + 1 >= argc)
- UseMsg();
- KdAddConfigKeyboard(argv[i + 1]);
- kdHasKbd = TRUE;
- return 2;
- }
-
- return 0;
-}
-
-/*
- * These are getting tossed in here until I can think of where
- * they really belong
- */
-
-void
-KdOsInit (KdOsFuncs *pOsFuncs)
-{
- kdOsFuncs = pOsFuncs;
- if (pOsFuncs)
- {
- if (serverGeneration == 1)
- {
- KdDoSwitchCmd ("start");
- if (pOsFuncs->Init)
- (*pOsFuncs->Init) ();
- }
- }
-}
-
-Bool
-KdAllocatePrivates (ScreenPtr pScreen)
-{
- KdPrivScreenPtr pScreenPriv;
-
- if (kdGeneration != serverGeneration)
- kdGeneration = serverGeneration;
-
- if (!dixRegisterPrivateKey(&kdScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
- return FALSE;
-
- pScreenPriv = calloc(1, sizeof (*pScreenPriv));
- if (!pScreenPriv)
- return FALSE;
- KdSetScreenPriv (pScreen, pScreenPriv);
- return TRUE;
-}
-
-Bool
-KdCreateScreenResources (ScreenPtr pScreen)
-{
- KdScreenPriv(pScreen);
- KdCardInfo *card = pScreenPriv->card;
- Bool ret;
-
- pScreen->CreateScreenResources = pScreenPriv->CreateScreenResources;
- if(pScreen->CreateScreenResources)
- ret = (*pScreen->CreateScreenResources) (pScreen);
- else
- ret= -1;
- pScreenPriv->CreateScreenResources = pScreen->CreateScreenResources;
- pScreen->CreateScreenResources = KdCreateScreenResources;
- if (ret && card->cfuncs->createRes)
- ret = (*card->cfuncs->createRes) (pScreen);
- return ret;
-}
-
-Bool
-KdCloseScreen (int index, ScreenPtr pScreen)
-{
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- KdCardInfo *card = pScreenPriv->card;
- Bool ret;
-
- pScreenPriv->closed = TRUE;
- pScreen->CloseScreen = pScreenPriv->CloseScreen;
- if(pScreen->CloseScreen)
- ret = (*pScreen->CloseScreen) (index, pScreen);
- else
- ret = TRUE;
-
- if (pScreenPriv->dpmsState != KD_DPMS_NORMAL)
- (*card->cfuncs->dpms) (pScreen, KD_DPMS_NORMAL);
-
- if (screen->mynum == card->selected)
- KdDisableScreen (pScreen);
-
- /*
- * Restore video hardware when last screen is closed
- */
- if (screen == card->screenList)
- {
- if (kdEnabled && card->cfuncs->restore)
- (*card->cfuncs->restore) (card);
- }
-
- if (!pScreenPriv->screen->dumb && card->cfuncs->finiAccel)
- (*card->cfuncs->finiAccel) (pScreen);
-
- if (!pScreenPriv->screen->softCursor && card->cfuncs->finiCursor)
- (*card->cfuncs->finiCursor) (pScreen);
-
- if(card->cfuncs->scrfini)
- (*card->cfuncs->scrfini) (screen);
-
- /*
- * Clean up card when last screen is closed, DIX closes them in
- * reverse order, thus we check for when the first in the list is closed
- */
- if (screen == card->screenList)
- {
- if(card->cfuncs->cardfini)
- (*card->cfuncs->cardfini) (card);
- /*
- * Clean up OS when last card is closed
- */
- if (card == kdCardInfo)
- {
- if (kdEnabled)
- {
- kdEnabled = FALSE;
- if(kdOsFuncs->Disable)
- (*kdOsFuncs->Disable) ();
- }
- }
- }
-
- pScreenPriv->screen->pScreen = 0;
-
- free((pointer) pScreenPriv);
- return ret;
-}
-
-Bool
-KdSaveScreen (ScreenPtr pScreen, int on)
-{
- KdScreenPriv(pScreen);
- int dpmsState;
-
- if (!pScreenPriv->card->cfuncs->dpms)
- return FALSE;
-
- dpmsState = pScreenPriv->dpmsState;
- switch (on) {
- case SCREEN_SAVER_OFF:
- dpmsState = KD_DPMS_NORMAL;
- break;
- case SCREEN_SAVER_ON:
- if (dpmsState == KD_DPMS_NORMAL)
- dpmsState = KD_DPMS_NORMAL+1;
- break;
- case SCREEN_SAVER_CYCLE:
- if (dpmsState < KD_DPMS_MAX)
- dpmsState++;
- break;
- case SCREEN_SAVER_FORCER:
- break;
- }
- if (dpmsState != pScreenPriv->dpmsState)
- {
- if (pScreenPriv->enabled)
- (*pScreenPriv->card->cfuncs->dpms) (pScreen, dpmsState);
- pScreenPriv->dpmsState = dpmsState;
- }
- return TRUE;
-}
-
-static Bool
-KdCreateWindow (WindowPtr pWin)
-{
-#ifndef PHOENIX
- if (!pWin->parent)
- {
- KdScreenPriv(pWin->drawable.pScreen);
-
- if (!pScreenPriv->enabled)
- {
- RegionEmpty(&pWin->borderClip);
- RegionBreak(&pWin->clipList);
- }
- }
-#endif
- return fbCreateWindow (pWin);
-}
-
-void
-KdSetSubpixelOrder (ScreenPtr pScreen, Rotation randr)
-{
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- int subpixel_order = screen->subpixel_order;
- Rotation subpixel_dir;
- int i;
-
- static struct {
- int subpixel_order;
- Rotation direction;
- } orders[] = {
- { SubPixelHorizontalRGB, RR_Rotate_0 },
- { SubPixelHorizontalBGR, RR_Rotate_180 },
- { SubPixelVerticalRGB, RR_Rotate_270 },
- { SubPixelVerticalBGR, RR_Rotate_90 },
- };
-
- static struct {
- int bit;
- int normal;
- int reflect;
- } reflects[] = {
- { RR_Reflect_X, SubPixelHorizontalRGB, SubPixelHorizontalBGR },
- { RR_Reflect_X, SubPixelHorizontalBGR, SubPixelHorizontalRGB },
- { RR_Reflect_Y, SubPixelVerticalRGB, SubPixelVerticalBGR },
- { RR_Reflect_Y, SubPixelVerticalRGB, SubPixelVerticalRGB },
- };
-
- /* map subpixel to direction */
- for (i = 0; i < 4; i++)
- if (orders[i].subpixel_order == subpixel_order)
- break;
- if (i < 4)
- {
- subpixel_dir = KdAddRotation (randr & RR_Rotate_All, orders[i].direction);
-
- /* map back to subpixel order */
- for (i = 0; i < 4; i++)
- if (orders[i].direction & subpixel_dir)
- {
- subpixel_order = orders[i].subpixel_order;
- break;
- }
- /* reflect */
- for (i = 0; i < 4; i++)
- if ((randr & reflects[i].bit) &&
- reflects[i].normal == subpixel_order)
- {
- subpixel_order = reflects[i].reflect;
- break;
- }
- }
- PictureSetSubpixelOrder (pScreen, subpixel_order);
-}
-
-/* Pass through AddScreen, which doesn't take any closure */
-static KdScreenInfo *kdCurrentScreen;
-
-Bool
-KdScreenInit(int index, ScreenPtr pScreen, int argc, char **argv)
-{
- KdScreenInfo *screen = kdCurrentScreen;
- KdCardInfo *card = screen->card;
- KdPrivScreenPtr pScreenPriv;
- /*
- * note that screen->fb is set up for the nominal orientation
- * of the screen; that means if randr is rotated, the values
- * there should reflect a rotated frame buffer (or shadow).
- */
- Bool rotated = (screen->randr & (RR_Rotate_90|RR_Rotate_270)) != 0;
- int width, height, *width_mmp, *height_mmp;
-
- KdAllocatePrivates (pScreen);
-
- pScreenPriv = KdGetScreenPriv(pScreen);
-
- if (!rotated)
- {
- width = screen->width;
- height = screen->height;
- width_mmp = &screen->width_mm;
- height_mmp = &screen->height_mm;
- }
- else
- {
- width = screen->height;
- height = screen->width;
- width_mmp = &screen->height_mm;
- height_mmp = &screen->width_mm;
- }
- screen->pScreen = pScreen;
- pScreenPriv->screen = screen;
- pScreenPriv->card = card;
- pScreenPriv->bytesPerPixel = screen->fb.bitsPerPixel >> 3;
- pScreenPriv->dpmsState = KD_DPMS_NORMAL;
- pScreen->x = screen->origin.x;
- pScreen->y = screen->origin.y;
-
- if (!monitorResolution)
- monitorResolution = 75;
- /*
- * This is done in this order so that backing store wraps
- * our GC functions; fbFinishScreenInit initializes MI
- * backing store
- */
- if (!fbSetupScreen (pScreen,
- screen->fb.frameBuffer,
- width, height,
- monitorResolution, monitorResolution,
- screen->fb.pixelStride,
- screen->fb.bitsPerPixel))
- {
- return FALSE;
- }
-
- /*
- * Set colormap functions
- */
- pScreen->InstallColormap = KdInstallColormap;
- pScreen->UninstallColormap = KdUninstallColormap;
- pScreen->ListInstalledColormaps = KdListInstalledColormaps;
- pScreen->StoreColors = KdStoreColors;
-
- pScreen->SaveScreen = KdSaveScreen;
- pScreen->CreateWindow = KdCreateWindow;
-
- if (!fbFinishScreenInit (pScreen,
- screen->fb.frameBuffer,
- width, height,
- monitorResolution, monitorResolution,
- screen->fb.pixelStride,
- screen->fb.bitsPerPixel))
- {
- return FALSE;
- }
-
- /*
- * Fix screen sizes; for some reason mi takes dpi instead of mm.
- * Rounding errors are annoying
- */
- if (*width_mmp)
- pScreen->mmWidth = *width_mmp;
- else
- *width_mmp = pScreen->mmWidth;
- if (*height_mmp)
- pScreen->mmHeight = *height_mmp;
- else
- *height_mmp = pScreen->mmHeight;
-
- /*
- * Plug in our own block/wakeup handlers.
- * miScreenInit installs NoopDDA in both places
- */
- pScreen->BlockHandler = KdBlockHandler;
- pScreen->WakeupHandler = KdWakeupHandler;
-
- if (!fbPictureInit (pScreen, 0, 0))
- return FALSE;
- if (card->cfuncs->initScreen)
- if (!(*card->cfuncs->initScreen) (pScreen))
- return FALSE;
-
- if (!screen->dumb && card->cfuncs->initAccel)
- if (!(*card->cfuncs->initAccel) (pScreen))
- screen->dumb = TRUE;
-
- if (card->cfuncs->finishInitScreen)
- if (!(*card->cfuncs->finishInitScreen) (pScreen))
- return FALSE;
-
-#if 0
- fbInitValidateTree (pScreen);
-#endif
-
- /*
- * Wrap CloseScreen, the order now is:
- * KdCloseScreen
- * miBSCloseScreen
- * fbCloseScreen
- */
- pScreenPriv->CloseScreen = pScreen->CloseScreen;
- pScreen->CloseScreen = KdCloseScreen;
-
- pScreenPriv->CreateScreenResources = pScreen->CreateScreenResources;
- pScreen->CreateScreenResources = KdCreateScreenResources;
-
- if (screen->softCursor ||
- !card->cfuncs->initCursor ||
- !(*card->cfuncs->initCursor) (pScreen))
- {
- /* Use MI for cursor display and event queueing. */
- screen->softCursor = TRUE;
- miDCInitialize(pScreen, &kdPointerScreenFuncs);
- }
-
-
- if (!fbCreateDefColormap (pScreen))
- {
- return FALSE;
- }
-
- KdSetSubpixelOrder (pScreen, screen->randr);
-
- /*
- * Enable the hardware
- */
- if (!kdEnabled)
- {
- kdEnabled = TRUE;
- if(kdOsFuncs->Enable)
- (*kdOsFuncs->Enable) ();
- }
-
- if (screen->mynum == card->selected)
- {
- if(card->cfuncs->preserve)
- (*card->cfuncs->preserve) (card);
- if(card->cfuncs->enable)
- if (!(*card->cfuncs->enable) (pScreen))
- return FALSE;
- pScreenPriv->enabled = TRUE;
- if (!screen->softCursor && card->cfuncs->enableCursor)
- (*card->cfuncs->enableCursor) (pScreen);
- KdEnableColormap (pScreen);
- if (!screen->dumb && card->cfuncs->enableAccel)
- (*card->cfuncs->enableAccel) (pScreen);
- }
-
- return TRUE;
-}
-
-void
-KdInitScreen (ScreenInfo *pScreenInfo,
- KdScreenInfo *screen,
- int argc,
- char **argv)
-{
- KdCardInfo *card = screen->card;
-
- (*card->cfuncs->scrinit) (screen);
-
- if (!card->cfuncs->initAccel)
- screen->dumb = TRUE;
- if (!card->cfuncs->initCursor)
- screen->softCursor = TRUE;
-}
-
-static Bool
-KdSetPixmapFormats (ScreenInfo *pScreenInfo)
-{
- CARD8 depthToBpp[33]; /* depth -> bpp map */
- KdCardInfo *card;
- KdScreenInfo *screen;
- int i;
- int bpp;
- PixmapFormatRec *format;
-
- for (i = 1; i <= 32; i++)
- depthToBpp[i] = 0;
-
- /*
- * Generate mappings between bitsPerPixel and depth,
- * also ensure that all screens comply with protocol
- * restrictions on equivalent formats for the same
- * depth on different screens
- */
- for (card = kdCardInfo; card; card = card->next)
- {
- for (screen = card->screenList; screen; screen = screen->next)
- {
- bpp = screen->fb.bitsPerPixel;
- if (bpp == 24)
- bpp = 32;
- if (!depthToBpp[screen->fb.depth])
- depthToBpp[screen->fb.depth] = bpp;
- else if (depthToBpp[screen->fb.depth] != bpp)
- return FALSE;
- }
- }
-
- /*
- * Fill in additional formats
- */
- for (i = 0; i < NUM_KD_DEPTHS; i++)
- if (!depthToBpp[kdDepths[i].depth])
- depthToBpp[kdDepths[i].depth] = kdDepths[i].bpp;
-
- pScreenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
- pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
- pScreenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
- pScreenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
-
- pScreenInfo->numPixmapFormats = 0;
-
- for (i = 1; i <= 32; i++)
- {
- if (depthToBpp[i])
- {
- format = &pScreenInfo->formats[pScreenInfo->numPixmapFormats++];
- format->depth = i;
- format->bitsPerPixel = depthToBpp[i];
- format->scanlinePad = BITMAP_SCANLINE_PAD;
- }
- }
-
- return TRUE;
-}
-
-static void
-KdAddScreen (ScreenInfo *pScreenInfo,
- KdScreenInfo *screen,
- int argc,
- char **argv)
-{
- int i;
- /*
- * Fill in fb visual type masks for this screen
- */
- for (i = 0; i < pScreenInfo->numPixmapFormats; i++)
- {
- unsigned long visuals;
- Pixel rm, gm, bm;
-
- visuals = 0;
- rm = gm = bm = 0;
- if (pScreenInfo->formats[i].depth == screen->fb.depth)
- {
- visuals = screen->fb.visuals;
- rm = screen->fb.redMask;
- gm = screen->fb.greenMask;
- bm = screen->fb.blueMask;
- }
- fbSetVisualTypesAndMasks (pScreenInfo->formats[i].depth,
- visuals,
- 8,
- rm, gm, bm);
- }
-
- kdCurrentScreen = screen;
-
- AddScreen (KdScreenInit, argc, argv);
-}
-
-#if 0 /* This function is not used currently */
-
-int
-KdDepthToFb (ScreenPtr pScreen, int depth)
-{
- KdScreenPriv(pScreen);
-
- for (fb = 0; fb <= KD_MAX_FB && pScreenPriv->screen->fb.frameBuffer; fb++)
- if (pScreenPriv->screen->fb.depth == depth)
- return fb;
-}
-
-#endif
-
-static int
-KdSignalWrapper (int signum)
-{
- kdCaughtSignal = TRUE;
- return 1; /* use generic OS layer cleanup & abort */
-}
-
-void
-KdInitOutput (ScreenInfo *pScreenInfo,
- int argc,
- char **argv)
-{
- KdCardInfo *card;
- KdScreenInfo *screen;
-
- if (!kdCardInfo)
- {
- InitCard (0);
- if (!(card = KdCardInfoLast ()))
- FatalError("No matching cards found!\n");
- screen = KdScreenInfoAdd (card);
- KdParseScreen (screen, 0);
- }
- /*
- * Initialize all of the screens for all of the cards
- */
- for (card = kdCardInfo; card; card = card->next)
- {
- int ret=1;
- if(card->cfuncs->cardinit)
- ret=(*card->cfuncs->cardinit) (card);
- if (ret)
- {
- for (screen = card->screenList; screen; screen = screen->next)
- KdInitScreen (pScreenInfo, screen, argc, argv);
- }
- }
-
- /*
- * Merge the various pixmap formats together, this can fail
- * when two screens share depth but not bitsPerPixel
- */
- if (!KdSetPixmapFormats (pScreenInfo))
- return;
-
- /*
- * Add all of the screens
- */
- for (card = kdCardInfo; card; card = card->next)
- for (screen = card->screenList; screen; screen = screen->next)
- KdAddScreen (pScreenInfo, screen, argc, argv);
-
- OsRegisterSigWrapper(KdSignalWrapper);
-}
-
-void
-OsVendorFatalError(void)
-{
-}
-
-int
-DPMSSet(ClientPtr client, int level)
-{
- return Success;
-}
-
-Bool
-DPMSSupported (void)
-{
- return FALSE;
-}
+/* + * 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 <kdrive-config.h> +#endif +#include "kdrive.h" +#include <mivalidate.h> +#include <dixstruct.h> +#include "privates.h" +#ifdef RANDR +#include <randrstr.h> +#endif + +#ifdef XV +#include "kxv.h" +#endif + +#ifdef DPMSExtension +#include "dpmsproc.h" +#endif + +#ifdef HAVE_EXECINFO_H +#include <execinfo.h> +#endif + +#include <signal.h> + +typedef struct _kdDepths { + CARD8 depth; + CARD8 bpp; +} KdDepths; + +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])) + +#define KD_DEFAULT_BUTTONS 5 + +DevPrivateKeyRec kdScreenPrivateKeyRec; +unsigned long kdGeneration; + +Bool kdVideoTest; +unsigned long kdVideoTestTime; +Bool kdEmulateMiddleButton; +Bool kdRawPointerCoordinates; +Bool kdDisableZaphod; +Bool kdAllowZap; +Bool kdEnabled; +int kdSubpixelOrder; +int kdVirtualTerminal = -1; +Bool kdSwitchPending; +char *kdSwitchCmd; +DDXPointRec kdOrigin; +Bool kdHasPointer = FALSE; +Bool kdHasKbd = FALSE; + +static Bool kdCaughtSignal = FALSE; + +/* + * Carry arguments from InitOutput through driver initialization + * to KdScreenInit + */ + +KdOsFuncs *kdOsFuncs; + +void +KdDisableScreen (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + + if (!pScreenPriv->enabled) + return; + if (!pScreenPriv->closed) + SetRootClip (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 (char *reason) +{ + if (kdSwitchCmd) + { + char *command = malloc(strlen (kdSwitchCmd) + + 1 + + strlen (reason) + + 1); + if (!command) + return; + strcpy (command, kdSwitchCmd); + strcat (command, " "); + strcat (command, reason); + 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"); + } +} + +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); + SetRootClip (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 (); + } +} + +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"); + } + + if (kdCaughtSignal) + OsAbort(); +} + +void +ddxGiveUp (void) +{ + AbortDDX (); +} + +Bool kdDumbDriver; +Bool kdSoftCursor; + +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 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') + { + 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 + */ + +void +KdParseRgba (char *rgba) +{ + if (!strcmp (rgba, "rgb")) + kdSubpixelOrder = SubPixelHorizontalRGB; + else if (!strcmp (rgba, "bgr")) + kdSubpixelOrder = SubPixelHorizontalBGR; + else if (!strcmp (rgba, "vrgb")) + kdSubpixelOrder = SubPixelVerticalRGB; + else if (!strcmp (rgba, "vbgr")) + kdSubpixelOrder = SubPixelVerticalBGR; + else if (!strcmp (rgba, "none")) + kdSubpixelOrder = SubPixelNone; + else + kdSubpixelOrder = SubPixelUnknown; +} + +void +KdUseMsg (void) +{ + ErrorF("\nTinyX Device Dependent Usage:\n"); + ErrorF("-screen WIDTH[/WIDTHMM]xHEIGHT[/HEIGHTMM][@ROTATION][X][Y][xDEPTH/BPP[xFREQ]] Specify screen characteristics\n"); + ErrorF("-rgba rgb/bgr/vrgb/vbgr/none Specify subpixel ordering for LCD panels\n"); + ErrorF("-mouse driver [,n,,options] Specify the pointer driver and its options (n is the number of buttons)\n"); + ErrorF("-keybd driver [,,options] Specify the keyboard driver and its options\n"); + ErrorF("-zaphod Disable cursor screen switching\n"); + ErrorF("-2button Emulate 3 button mouse\n"); + ErrorF("-3button Disable 3 button mouse emulation\n"); + ErrorF("-rawcoord Don't transform pointer coordinates on rotation\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("-switchCmd Command to execute on vt switch\n"); + ErrorF("-zap Terminate server on Ctrl+Alt+Backspace\n"); + ErrorF("vtxx Use virtual terminal xx instead of the next available\n"); +} + +int +KdProcessArgument (int argc, char **argv, int i) +{ + KdCardInfo *card; + KdScreenInfo *screen; + + if (!strcmp (argv[i], "-screen")) + { + if ((i+1) < argc) + { + card = KdCardInfoLast (); + if (!card) + { + InitCard (0); + card = KdCardInfoLast (); + } + if (card) { + screen = KdScreenInfoAdd (card); + KdParseScreen (screen, argv[i+1]); + } else + ErrorF("No matching card found!\n"); + } + else + UseMsg (); + return 2; + } + if (!strcmp (argv[i], "-zaphod")) + { + kdDisableZaphod = TRUE; + return 1; + } + if (!strcmp (argv[i], "-zap")) + { + kdAllowZap = TRUE; + return 1; + } + if (!strcmp (argv[i], "-3button")) + { + kdEmulateMiddleButton = FALSE; + return 1; + } + if (!strcmp (argv[i], "-2button")) + { + kdEmulateMiddleButton = TRUE; + return 1; + } + if (!strcmp (argv[i], "-rawcoord")) + { + kdRawPointerCoordinates = 1; + return 1; + } + if (!strcmp (argv[i], "-dumb")) + { + kdDumbDriver = TRUE; + return 1; + } + if (!strcmp (argv[i], "-softCursor")) + { + kdSoftCursor = TRUE; + return 1; + } + if (!strcmp (argv[i], "-videoTest")) + { + kdVideoTest = TRUE; + return 1; + } + if (!strcmp (argv[i], "-origin")) + { + if ((i+1) < argc) + { + char *x = argv[i+1]; + char *y = strchr (x, ','); + if (x) + kdOrigin.x = atoi (x); + else + kdOrigin.x = 0; + if (y) + kdOrigin.y = atoi(y+1); + else + kdOrigin.y = 0; + } + else + UseMsg (); + return 2; + } + if (!strcmp (argv[i], "-rgba")) + { + if ((i+1) < argc) + KdParseRgba (argv[i+1]); + else + UseMsg (); + return 2; + } + if (!strcmp (argv[i], "-switchCmd")) + { + if ((i+1) < argc) + kdSwitchCmd = argv[i+1]; + else + UseMsg (); + return 2; + } + if (!strncmp (argv[i], "vt", 2) && + sscanf (argv[i], "vt%2d", &kdVirtualTerminal) == 1) + { + return 1; + } + if (!strcmp (argv[i], "-mouse") || + !strcmp (argv[i], "-pointer")) { + if (i + 1 >= argc) + UseMsg(); + KdAddConfigPointer(argv[i + 1]); + kdHasPointer = TRUE; + return 2; + } + if (!strcmp (argv[i], "-keybd")) { + if (i + 1 >= argc) + UseMsg(); + KdAddConfigKeyboard(argv[i + 1]); + kdHasKbd = TRUE; + return 2; + } + + return 0; +} + +/* + * These are getting tossed in here until I can think of where + * they really belong + */ + +void +KdOsInit (KdOsFuncs *pOsFuncs) +{ + kdOsFuncs = pOsFuncs; + if (pOsFuncs) + { + if (serverGeneration == 1) + { + KdDoSwitchCmd ("start"); + if (pOsFuncs->Init) + (*pOsFuncs->Init) (); + } + } +} + +Bool +KdAllocatePrivates (ScreenPtr pScreen) +{ + KdPrivScreenPtr pScreenPriv; + + if (kdGeneration != serverGeneration) + kdGeneration = serverGeneration; + + if (!dixRegisterPrivateKey(&kdScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + pScreenPriv = calloc(1, sizeof (*pScreenPriv)); + if (!pScreenPriv) + return FALSE; + KdSetScreenPriv (pScreen, pScreenPriv); + return TRUE; +} + +Bool +KdCreateScreenResources (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdCardInfo *card = pScreenPriv->card; + Bool ret; + + pScreen->CreateScreenResources = pScreenPriv->CreateScreenResources; + if(pScreen->CreateScreenResources) + ret = (*pScreen->CreateScreenResources) (pScreen); + else + ret= -1; + pScreenPriv->CreateScreenResources = pScreen->CreateScreenResources; + pScreen->CreateScreenResources = KdCreateScreenResources; + if (ret && card->cfuncs->createRes) + ret = (*card->cfuncs->createRes) (pScreen); + return ret; +} + +Bool +KdCloseScreen (int index, ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + KdCardInfo *card = pScreenPriv->card; + Bool ret; + + pScreenPriv->closed = TRUE; + pScreen->CloseScreen = pScreenPriv->CloseScreen; + if(pScreen->CloseScreen) + ret = (*pScreen->CloseScreen) (index, pScreen); + else + ret = TRUE; + + if (pScreenPriv->dpmsState != KD_DPMS_NORMAL) + (*card->cfuncs->dpms) (pScreen, KD_DPMS_NORMAL); + + if (screen->mynum == card->selected) + KdDisableScreen (pScreen); + + /* + * Restore video hardware when last screen is closed + */ + if (screen == card->screenList) + { + if (kdEnabled && card->cfuncs->restore) + (*card->cfuncs->restore) (card); + } + + if (!pScreenPriv->screen->dumb && card->cfuncs->finiAccel) + (*card->cfuncs->finiAccel) (pScreen); + + if (!pScreenPriv->screen->softCursor && card->cfuncs->finiCursor) + (*card->cfuncs->finiCursor) (pScreen); + + if(card->cfuncs->scrfini) + (*card->cfuncs->scrfini) (screen); + + /* + * Clean up card when last screen is closed, DIX closes them in + * reverse order, thus we check for when the first in the list is closed + */ + if (screen == card->screenList) + { + if(card->cfuncs->cardfini) + (*card->cfuncs->cardfini) (card); + /* + * Clean up OS when last card is closed + */ + if (card == kdCardInfo) + { + if (kdEnabled) + { + kdEnabled = FALSE; + if(kdOsFuncs->Disable) + (*kdOsFuncs->Disable) (); + } + } + } + + pScreenPriv->screen->pScreen = 0; + + free((pointer) pScreenPriv); + return ret; +} + +Bool +KdSaveScreen (ScreenPtr pScreen, int on) +{ + KdScreenPriv(pScreen); + int dpmsState; + + if (!pScreenPriv->card->cfuncs->dpms) + return FALSE; + + dpmsState = pScreenPriv->dpmsState; + switch (on) { + case SCREEN_SAVER_OFF: + dpmsState = KD_DPMS_NORMAL; + break; + case SCREEN_SAVER_ON: + if (dpmsState == KD_DPMS_NORMAL) + dpmsState = KD_DPMS_NORMAL+1; + break; + case SCREEN_SAVER_CYCLE: + if (dpmsState < KD_DPMS_MAX) + dpmsState++; + break; + case SCREEN_SAVER_FORCER: + break; + } + if (dpmsState != pScreenPriv->dpmsState) + { + if (pScreenPriv->enabled) + (*pScreenPriv->card->cfuncs->dpms) (pScreen, dpmsState); + pScreenPriv->dpmsState = dpmsState; + } + return TRUE; +} + +static Bool +KdCreateWindow (WindowPtr pWin) +{ +#ifndef PHOENIX + if (!pWin->parent) + { + KdScreenPriv(pWin->drawable.pScreen); + + if (!pScreenPriv->enabled) + { + RegionEmpty(&pWin->borderClip); + RegionBreak(&pWin->clipList); + } + } +#endif + return fbCreateWindow (pWin); +} + +void +KdSetSubpixelOrder (ScreenPtr pScreen, Rotation randr) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + int subpixel_order = screen->subpixel_order; + Rotation subpixel_dir; + int i; + + static struct { + int subpixel_order; + Rotation direction; + } orders[] = { + { SubPixelHorizontalRGB, RR_Rotate_0 }, + { SubPixelHorizontalBGR, RR_Rotate_180 }, + { SubPixelVerticalRGB, RR_Rotate_270 }, + { SubPixelVerticalBGR, RR_Rotate_90 }, + }; + + static struct { + int bit; + int normal; + int reflect; + } reflects[] = { + { RR_Reflect_X, SubPixelHorizontalRGB, SubPixelHorizontalBGR }, + { RR_Reflect_X, SubPixelHorizontalBGR, SubPixelHorizontalRGB }, + { RR_Reflect_Y, SubPixelVerticalRGB, SubPixelVerticalBGR }, + { RR_Reflect_Y, SubPixelVerticalRGB, SubPixelVerticalRGB }, + }; + + /* map subpixel to direction */ + for (i = 0; i < 4; i++) + if (orders[i].subpixel_order == subpixel_order) + break; + if (i < 4) + { + subpixel_dir = KdAddRotation (randr & RR_Rotate_All, orders[i].direction); + + /* map back to subpixel order */ + for (i = 0; i < 4; i++) + if (orders[i].direction & subpixel_dir) + { + subpixel_order = orders[i].subpixel_order; + break; + } + /* reflect */ + for (i = 0; i < 4; i++) + if ((randr & reflects[i].bit) && + reflects[i].normal == subpixel_order) + { + subpixel_order = reflects[i].reflect; + break; + } + } + PictureSetSubpixelOrder (pScreen, subpixel_order); +} + +/* Pass through AddScreen, which doesn't take any closure */ +static KdScreenInfo *kdCurrentScreen; + +Bool +KdScreenInit(int index, ScreenPtr pScreen, int argc, char **argv) +{ + KdScreenInfo *screen = kdCurrentScreen; + KdCardInfo *card = screen->card; + KdPrivScreenPtr pScreenPriv; + /* + * note that screen->fb is set up for the nominal orientation + * of the screen; that means if randr is rotated, the values + * there should reflect a rotated frame buffer (or shadow). + */ + Bool rotated = (screen->randr & (RR_Rotate_90|RR_Rotate_270)) != 0; + int width, height, *width_mmp, *height_mmp; + + KdAllocatePrivates (pScreen); + + pScreenPriv = KdGetScreenPriv(pScreen); + + if (!rotated) + { + width = screen->width; + height = screen->height; + width_mmp = &screen->width_mm; + height_mmp = &screen->height_mm; + } + else + { + width = screen->height; + height = screen->width; + width_mmp = &screen->height_mm; + height_mmp = &screen->width_mm; + } + screen->pScreen = pScreen; + pScreenPriv->screen = screen; + pScreenPriv->card = card; + pScreenPriv->bytesPerPixel = screen->fb.bitsPerPixel >> 3; + pScreenPriv->dpmsState = KD_DPMS_NORMAL; + pScreen->x = screen->origin.x; + pScreen->y = screen->origin.y; + + if (!monitorResolution) + monitorResolution = 75; + /* + * This is done in this order so that backing store wraps + * our GC functions; fbFinishScreenInit initializes MI + * backing store + */ + if (!fbSetupScreen (pScreen, + screen->fb.frameBuffer, + width, height, + monitorResolution, monitorResolution, + screen->fb.pixelStride, + screen->fb.bitsPerPixel)) + { + return FALSE; + } + + /* + * Set colormap functions + */ + pScreen->InstallColormap = KdInstallColormap; + pScreen->UninstallColormap = KdUninstallColormap; + pScreen->ListInstalledColormaps = KdListInstalledColormaps; + pScreen->StoreColors = KdStoreColors; + + pScreen->SaveScreen = KdSaveScreen; + pScreen->CreateWindow = KdCreateWindow; + + if (!fbFinishScreenInit (pScreen, + screen->fb.frameBuffer, + width, height, + monitorResolution, monitorResolution, + screen->fb.pixelStride, + screen->fb.bitsPerPixel)) + { + return FALSE; + } + + /* + * Fix screen sizes; for some reason mi takes dpi instead of mm. + * Rounding errors are annoying + */ + if (*width_mmp) + pScreen->mmWidth = *width_mmp; + else + *width_mmp = pScreen->mmWidth; + if (*height_mmp) + pScreen->mmHeight = *height_mmp; + else + *height_mmp = pScreen->mmHeight; + + /* + * Plug in our own block/wakeup handlers. + * miScreenInit installs NoopDDA in both places + */ + pScreen->BlockHandler = KdBlockHandler; + pScreen->WakeupHandler = KdWakeupHandler; + + if (!fbPictureInit (pScreen, 0, 0)) + return FALSE; + if (card->cfuncs->initScreen) + if (!(*card->cfuncs->initScreen) (pScreen)) + return FALSE; + + if (!screen->dumb && card->cfuncs->initAccel) + if (!(*card->cfuncs->initAccel) (pScreen)) + screen->dumb = TRUE; + + if (card->cfuncs->finishInitScreen) + if (!(*card->cfuncs->finishInitScreen) (pScreen)) + return FALSE; + +#if 0 + fbInitValidateTree (pScreen); +#endif + + /* + * Wrap CloseScreen, the order now is: + * KdCloseScreen + * miBSCloseScreen + * fbCloseScreen + */ + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = KdCloseScreen; + + pScreenPriv->CreateScreenResources = pScreen->CreateScreenResources; + pScreen->CreateScreenResources = KdCreateScreenResources; + + if (screen->softCursor || + !card->cfuncs->initCursor || + !(*card->cfuncs->initCursor) (pScreen)) + { + /* Use MI for cursor display and event queueing. */ + screen->softCursor = TRUE; + miDCInitialize(pScreen, &kdPointerScreenFuncs); + } + + + if (!fbCreateDefColormap (pScreen)) + { + return FALSE; + } + + KdSetSubpixelOrder (pScreen, screen->randr); + + /* + * Enable the hardware + */ + if (!kdEnabled) + { + kdEnabled = TRUE; + if(kdOsFuncs->Enable) + (*kdOsFuncs->Enable) (); + } + + if (screen->mynum == card->selected) + { + if(card->cfuncs->preserve) + (*card->cfuncs->preserve) (card); + if(card->cfuncs->enable) + if (!(*card->cfuncs->enable) (pScreen)) + return FALSE; + pScreenPriv->enabled = TRUE; + if (!screen->softCursor && card->cfuncs->enableCursor) + (*card->cfuncs->enableCursor) (pScreen); + KdEnableColormap (pScreen); + if (!screen->dumb && card->cfuncs->enableAccel) + (*card->cfuncs->enableAccel) (pScreen); + } + + return TRUE; +} + +void +KdInitScreen (ScreenInfo *pScreenInfo, + KdScreenInfo *screen, + int argc, + char **argv) +{ + KdCardInfo *card = screen->card; + + (*card->cfuncs->scrinit) (screen); + + if (!card->cfuncs->initAccel) + screen->dumb = TRUE; + if (!card->cfuncs->initCursor) + screen->softCursor = TRUE; +} + +static Bool +KdSetPixmapFormats (ScreenInfo *pScreenInfo) +{ + CARD8 depthToBpp[33]; /* depth -> bpp map */ + KdCardInfo *card; + KdScreenInfo *screen; + int i; + int bpp; + PixmapFormatRec *format; + + for (i = 1; i <= 32; i++) + depthToBpp[i] = 0; + + /* + * Generate mappings between bitsPerPixel and depth, + * also ensure that all screens comply with protocol + * restrictions on equivalent formats for the same + * depth on different screens + */ + for (card = kdCardInfo; card; card = card->next) + { + for (screen = card->screenList; screen; screen = screen->next) + { + bpp = screen->fb.bitsPerPixel; + if (bpp == 24) + bpp = 32; + if (!depthToBpp[screen->fb.depth]) + depthToBpp[screen->fb.depth] = bpp; + else if (depthToBpp[screen->fb.depth] != bpp) + return FALSE; + } + } + + /* + * Fill in additional formats + */ + for (i = 0; i < NUM_KD_DEPTHS; i++) + if (!depthToBpp[kdDepths[i].depth]) + depthToBpp[kdDepths[i].depth] = kdDepths[i].bpp; + + pScreenInfo->imageByteOrder = IMAGE_BYTE_ORDER; + pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; + pScreenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD; + pScreenInfo->bitmapBitOrder = BITMAP_BIT_ORDER; + + pScreenInfo->numPixmapFormats = 0; + + for (i = 1; i <= 32; i++) + { + if (depthToBpp[i]) + { + format = &pScreenInfo->formats[pScreenInfo->numPixmapFormats++]; + format->depth = i; + format->bitsPerPixel = depthToBpp[i]; + format->scanlinePad = BITMAP_SCANLINE_PAD; + } + } + + return TRUE; +} + +static void +KdAddScreen (ScreenInfo *pScreenInfo, + KdScreenInfo *screen, + int argc, + char **argv) +{ + int i; + /* + * Fill in fb visual type masks for this screen + */ + for (i = 0; i < pScreenInfo->numPixmapFormats; i++) + { + unsigned long visuals; + Pixel rm, gm, bm; + + visuals = 0; + rm = gm = bm = 0; + if (pScreenInfo->formats[i].depth == screen->fb.depth) + { + visuals = screen->fb.visuals; + rm = screen->fb.redMask; + gm = screen->fb.greenMask; + bm = screen->fb.blueMask; + } + fbSetVisualTypesAndMasks (pScreenInfo->formats[i].depth, + visuals, + 8, + rm, gm, bm); + } + + kdCurrentScreen = screen; + + AddScreen (KdScreenInit, argc, argv); +} + +#if 0 /* This function is not used currently */ + +int +KdDepthToFb (ScreenPtr pScreen, int depth) +{ + KdScreenPriv(pScreen); + + for (fb = 0; fb <= KD_MAX_FB && pScreenPriv->screen->fb.frameBuffer; fb++) + if (pScreenPriv->screen->fb.depth == depth) + return fb; +} + +#endif + +static int +KdSignalWrapper (int signum) +{ + kdCaughtSignal = TRUE; + return 1; /* use generic OS layer cleanup & abort */ +} + +void +KdInitOutput (ScreenInfo *pScreenInfo, + int argc, + char **argv) +{ + KdCardInfo *card; + KdScreenInfo *screen; + + if (!kdCardInfo) + { + InitCard (0); + if (!(card = KdCardInfoLast ())) + FatalError("No matching cards found!\n"); + screen = KdScreenInfoAdd (card); + KdParseScreen (screen, 0); + } + /* + * Initialize all of the screens for all of the cards + */ + for (card = kdCardInfo; card; card = card->next) + { + int ret=1; + if(card->cfuncs->cardinit) + ret=(*card->cfuncs->cardinit) (card); + if (ret) + { + for (screen = card->screenList; screen; screen = screen->next) + KdInitScreen (pScreenInfo, screen, argc, argv); + } + } + + /* + * Merge the various pixmap formats together, this can fail + * when two screens share depth but not bitsPerPixel + */ + if (!KdSetPixmapFormats (pScreenInfo)) + return; + + /* + * Add all of the screens + */ + for (card = kdCardInfo; card; card = card->next) + for (screen = card->screenList; screen; screen = screen->next) + KdAddScreen (pScreenInfo, screen, argc, argv); + + OsRegisterSigWrapper(KdSignalWrapper); +} + +void +OsVendorFatalError(void) +{ +} + +int +DPMSSet(ClientPtr client, int level) +{ + return Success; +} + +Bool +DPMSSupported (void) +{ + return FALSE; +} diff --git a/xorg-server/hw/kdrive/src/kdrive.h b/xorg-server/hw/kdrive/src/kdrive.h index 8873662ee..2ab535aef 100644 --- a/xorg-server/hw/kdrive/src/kdrive.h +++ b/xorg-server/hw/kdrive/src/kdrive.h @@ -1,628 +1,625 @@ -/*
- * 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.
- */
-
-#ifndef _KDRIVE_H_
-#define _KDRIVE_H_
-
-#include <stdio.h>
-#include <string.h>
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include <X11/Xos.h>
-#include "scrnintstr.h"
-#include "pixmapstr.h"
-#include "windowstr.h"
-#include "servermd.h"
-#include "mibstore.h"
-#include "colormapst.h"
-#include "gcstruct.h"
-#include "input.h"
-#include "mipointer.h"
-#include "mi.h"
-#include "dix.h"
-#include "fb.h"
-#include "fboverlay.h"
-#include "shadow.h"
-#include "randrstr.h"
-#include "globals.h"
-
-#include "xkbstr.h"
-
-#define KD_DPMS_NORMAL 0
-#define KD_DPMS_STANDBY 1
-#define KD_DPMS_SUSPEND 2
-#define KD_DPMS_POWERDOWN 3
-#define KD_DPMS_MAX KD_DPMS_POWERDOWN
-
-#define Status int
-
-typedef struct _KdCardInfo {
- struct _KdCardFuncs *cfuncs;
- void *closure;
- void *driver;
- struct _KdScreenInfo *screenList;
- int selected;
- struct _KdCardInfo *next;
-} KdCardInfo;
-
-extern KdCardInfo *kdCardInfo;
-
-/*
- * Configuration information per X screen
- */
-typedef struct _KdFrameBuffer {
- CARD8 *frameBuffer;
- int depth;
- int bitsPerPixel;
- int pixelStride;
- int byteStride;
- Bool shadow;
- unsigned long visuals;
- Pixel redMask, greenMask, blueMask;
- void *closure;
-} KdFrameBuffer;
-
-#define RR_Rotate_All (RR_Rotate_0|RR_Rotate_90|RR_Rotate_180|RR_Rotate_270)
-#define RR_Reflect_All (RR_Reflect_X|RR_Reflect_Y)
-
-typedef struct _KdScreenInfo {
- struct _KdScreenInfo *next;
- KdCardInfo *card;
- ScreenPtr pScreen;
- void *driver;
- Rotation randr; /* rotation and reflection */
- int width;
- int height;
- int rate;
- int width_mm;
- int height_mm;
- int subpixel_order;
- Bool dumb;
- Bool softCursor;
- int mynum;
- DDXPointRec origin;
- KdFrameBuffer fb;
-} KdScreenInfo;
-
-typedef struct _KdCardFuncs {
- Bool (*cardinit) (KdCardInfo *); /* detect and map device */
- Bool (*scrinit) (KdScreenInfo *);/* initialize screen information */
- Bool (*initScreen) (ScreenPtr); /* initialize ScreenRec */
- Bool (*finishInitScreen) (ScreenPtr pScreen);
- Bool (*createRes) (ScreenPtr); /* create screen resources */
- void (*preserve) (KdCardInfo *); /* save graphics card state */
- Bool (*enable) (ScreenPtr); /* set up for rendering */
- Bool (*dpms) (ScreenPtr, int); /* set DPMS screen saver */
- void (*disable) (ScreenPtr); /* turn off rendering */
- void (*restore) (KdCardInfo *); /* restore graphics card state */
- void (*scrfini) (KdScreenInfo *);/* close down screen */
- void (*cardfini) (KdCardInfo *); /* close down */
-
- Bool (*initCursor) (ScreenPtr); /* detect and map cursor */
- void (*enableCursor) (ScreenPtr); /* enable cursor */
- void (*disableCursor) (ScreenPtr); /* disable cursor */
- void (*finiCursor) (ScreenPtr); /* close down */
- void (*recolorCursor) (ScreenPtr, int, xColorItem *);
-
- Bool (*initAccel) (ScreenPtr);
- void (*enableAccel) (ScreenPtr);
- void (*disableAccel) (ScreenPtr);
- void (*finiAccel) (ScreenPtr);
-
- void (*getColors) (ScreenPtr, int, xColorItem *);
- void (*putColors) (ScreenPtr, int, xColorItem *);
-
-} KdCardFuncs;
-
-#define KD_MAX_PSEUDO_DEPTH 8
-#define KD_MAX_PSEUDO_SIZE (1 << KD_MAX_PSEUDO_DEPTH)
-
-typedef struct {
- KdScreenInfo *screen;
- KdCardInfo *card;
-
- Bool enabled;
- Bool closed;
- int bytesPerPixel;
-
- int dpmsState;
-
- ColormapPtr pInstalledmap; /* current colormap */
- xColorItem systemPalette[KD_MAX_PSEUDO_SIZE];/* saved windows colors */
-
- CreateScreenResourcesProcPtr CreateScreenResources;
- CloseScreenProcPtr CloseScreen;
-} KdPrivScreenRec, *KdPrivScreenPtr;
-
-typedef enum _kdPointerState {
- start,
- button_1_pend,
- button_1_down,
- button_2_down,
- button_3_pend,
- button_3_down,
- synth_2_down_13,
- synth_2_down_3,
- synth_2_down_1,
- num_input_states
-} KdPointerState;
-
-#define KD_MAX_BUTTON 32
-
-#define KD_KEYBOARD 1
-#define KD_MOUSE 2
-#define KD_TOUCHSCREEN 3
-
-typedef struct _KdPointerInfo KdPointerInfo;
-
-typedef struct _KdPointerDriver {
- char *name;
- Status (*Init) (KdPointerInfo *);
- Status (*Enable) (KdPointerInfo *);
- void (*Disable) (KdPointerInfo *);
- void (*Fini) (KdPointerInfo *);
- struct _KdPointerDriver *next;
-} KdPointerDriver;
-
-struct _KdPointerInfo {
- DeviceIntPtr dixdev;
- char *name;
- char *path;
- char *protocol;
- InputOption *options;
- int inputClass;
-
- CARD8 map[KD_MAX_BUTTON + 1];
- int nButtons;
- int nAxes;
-
- Bool emulateMiddleButton;
- unsigned long emulationTimeout;
- int emulationDx, emulationDy;
-
- Bool timeoutPending;
- KdPointerState mouseState;
- Bool eventHeld;
- struct {
- int type;
- int x;
- int y;
- int z;
- int flags;
- int absrel;
- } heldEvent;
- unsigned char buttonState;
- Bool transformCoordinates;
- int pressureThreshold;
-
- KdPointerDriver *driver;
- void *driverPrivate;
-
- struct _KdPointerInfo *next;
-};
-
-extern int KdCurScreen;
-
-void KdAddPointerDriver (KdPointerDriver *driver);
-void KdRemovePointerDriver (KdPointerDriver *driver);
-KdPointerInfo *KdNewPointer (void);
-void KdFreePointer (KdPointerInfo *);
-int KdAddPointer (KdPointerInfo *ki);
-int KdAddConfigPointer (char *pointer);
-void KdRemovePointer (KdPointerInfo *ki);
-
-
-#define KD_KEY_COUNT 248
-#define KD_MIN_KEYCODE 8
-#define KD_MAX_KEYCODE 255
-#define KD_MAX_WIDTH 4
-#define KD_MAX_LENGTH (KD_MAX_KEYCODE - KD_MIN_KEYCODE + 1)
-
-typedef struct {
- KeySym modsym;
- int modbit;
-} KdKeySymModsRec;
-
-typedef struct _KdKeyboardInfo KdKeyboardInfo;
-
-typedef struct _KdKeyboardDriver {
- char *name;
- Bool (*Init) (KdKeyboardInfo *);
- Bool (*Enable) (KdKeyboardInfo *);
- void (*Leds) (KdKeyboardInfo *, int);
- void (*Bell) (KdKeyboardInfo *, int, int, int);
- void (*Disable) (KdKeyboardInfo *);
- void (*Fini) (KdKeyboardInfo *);
- struct _KdKeyboardDriver *next;
-} KdKeyboardDriver;
-
-struct _KdKeyboardInfo {
- struct _KdKeyboardInfo *next;
- DeviceIntPtr dixdev;
- void *closure;
- char *name;
- char *path;
- int inputClass;
- char *xkbRules;
- char *xkbModel;
- char *xkbLayout;
- char *xkbVariant;
- char *xkbOptions;
- int LockLed;
-
- int minScanCode;
- int maxScanCode;
-
- int leds;
- int bellPitch;
- int bellDuration;
- InputOption *options;
-
- KdKeyboardDriver *driver;
- void *driverPrivate;
-};
-
-void KdAddKeyboardDriver (KdKeyboardDriver *driver);
-void KdRemoveKeyboardDriver (KdKeyboardDriver *driver);
-KdKeyboardInfo *KdNewKeyboard (void);
-void KdFreeKeyboard (KdKeyboardInfo *ki);
-int KdAddConfigKeyboard (char *pointer);
-int KdAddKeyboard (KdKeyboardInfo *ki);
-void KdRemoveKeyboard (KdKeyboardInfo *ki);
-
-typedef struct _KdOsFuncs {
- int (*Init) (void);
- void (*Enable) (void);
- Bool (*SpecialKey) (KeySym);
- void (*Disable) (void);
- void (*Fini) (void);
- void (*pollEvents) (void);
- void (*Bell) (int, int, int);
-} KdOsFuncs;
-
-typedef enum _KdSyncPolarity {
- KdSyncNegative, KdSyncPositive
-} KdSyncPolarity;
-
-typedef struct _KdMonitorTiming {
- /* label */
- int horizontal;
- int vertical;
- int rate;
- /* pixel clock */
- int clock; /* in KHz */
- /* horizontal timing */
- int hfp; /* front porch */
- int hbp; /* back porch */
- int hblank; /* blanking */
- KdSyncPolarity hpol; /* polarity */
- /* vertical timing */
- int vfp; /* front porch */
- int vbp; /* back porch */
- int vblank; /* blanking */
- KdSyncPolarity vpol; /* polarity */
-} KdMonitorTiming;
-
-extern const KdMonitorTiming kdMonitorTimings[];
-extern const int kdNumMonitorTimings;
-
-typedef struct _KdPointerMatrix {
- int matrix[2][3];
-} KdPointerMatrix;
-
-/*
- * This is the only completely portable way to
- * compute this info.
- */
-
-#ifndef BitsPerPixel
-#define BitsPerPixel(d) (\
- PixmapWidthPaddingInfo[d].notPower2 ? \
- (PixmapWidthPaddingInfo[d].bytesPerPixel * 8) : \
- ((1 << PixmapWidthPaddingInfo[d].padBytesLog2) * 8 / \
- (PixmapWidthPaddingInfo[d].padRoundUp+1)))
-#endif
-
-extern DevPrivateKeyRec kdScreenPrivateKeyRec;
-#define kdScreenPrivateKey (&kdScreenPrivateKeyRec)
-
-extern unsigned long kdGeneration;
-extern Bool kdEnabled;
-extern Bool kdSwitchPending;
-extern Bool kdEmulateMiddleButton;
-extern Bool kdDisableZaphod;
-extern Bool kdAllowZap;
-extern int kdVirtualTerminal;
-extern char *kdSwitchCmd;
-extern KdOsFuncs *kdOsFuncs;
-
-#define KdGetScreenPriv(pScreen) ((KdPrivScreenPtr) \
- dixLookupPrivate(&(pScreen)->devPrivates, kdScreenPrivateKey))
-#define KdSetScreenPriv(pScreen,v) \
- dixSetPrivate(&(pScreen)->devPrivates, kdScreenPrivateKey, v)
-#define KdScreenPriv(pScreen) KdPrivScreenPtr pScreenPriv = KdGetScreenPriv(pScreen)
-
-/* kcmap.c */
-void
-KdSetColormap (ScreenPtr pScreen);
-
-void
-KdEnableColormap (ScreenPtr pScreen);
-
-void
-KdDisableColormap (ScreenPtr pScreen);
-
-void
-KdInstallColormap (ColormapPtr pCmap);
-
-void
-KdUninstallColormap (ColormapPtr pCmap);
-
-int
-KdListInstalledColormaps (ScreenPtr pScreen, Colormap *pCmaps);
-
-void
-KdStoreColors (ColormapPtr pCmap, int ndef, xColorItem *pdefs);
-
-/* kdrive.c */
-extern miPointerScreenFuncRec kdPointerScreenFuncs;
-
-void
-KdSetRootClip (ScreenPtr pScreen, BOOL enable);
-
-void
-KdDisableScreen (ScreenPtr pScreen);
-
-void
-KdDisableScreens (void);
-
-Bool
-KdEnableScreen (ScreenPtr pScreen);
-
-void
-KdEnableScreens (void);
-
-void
-KdSuspend (void);
-
-void
-KdResume (void);
-
-void
-KdProcessSwitch (void);
-
-Rotation
-KdAddRotation (Rotation a, Rotation b);
-
-Rotation
-KdSubRotation (Rotation a, Rotation b);
-
-void
-KdParseScreen (KdScreenInfo *screen,
- char *arg);
-
-KdPointerInfo *
-KdParsePointer (char *arg);
-
-KdKeyboardInfo *
-KdParseKeyboard (char *arg);
-
-char *
-KdParseFindNext (char *cur, char *delim, char *save, char *last);
-
-void
-KdParseRgba (char *rgba);
-
-void
-KdUseMsg (void);
-
-int
-KdProcessArgument (int argc, char **argv, int i);
-
-void
-KdOsInit (KdOsFuncs *pOsFuncs);
-
-void
-KdOsAddInputDrivers (void);
-
-Bool
-KdAllocatePrivates (ScreenPtr pScreen);
-
-Bool
-KdCreateScreenResources (ScreenPtr pScreen);
-
-Bool
-KdCloseScreen (int index, ScreenPtr pScreen);
-
-Bool
-KdSaveScreen (ScreenPtr pScreen, int on);
-
-Bool
-KdScreenInit(int index, ScreenPtr pScreen, int argc, char **argv);
-
-void
-KdInitScreen (ScreenInfo *pScreenInfo,
- KdScreenInfo *screen,
- int argc,
- char **argv);
-
-void
-KdInitCard (ScreenInfo *pScreenInfo,
- KdCardInfo *card,
- int argc,
- char **argv);
-
-void
-KdInitOutput (ScreenInfo *pScreenInfo,
- int argc,
- char **argv);
-
-void
-KdSetSubpixelOrder (ScreenPtr pScreen, Rotation randr);
-
-void
-KdBacktrace (int signum);
-
-/* kinfo.c */
-KdCardInfo *
-KdCardInfoAdd (KdCardFuncs *funcs,
- void *closure);
-
-KdCardInfo *
-KdCardInfoLast (void);
-
-void
-KdCardInfoDispose (KdCardInfo *ci);
-
-KdScreenInfo *
-KdScreenInfoAdd (KdCardInfo *ci);
-
-void
-KdScreenInfoDispose (KdScreenInfo *si);
-
-
-/* kinput.c */
-void
-KdInitInput(void);
-
-void
-KdAddPointerDriver(KdPointerDriver *);
-
-void
-KdAddKeyboardDriver(KdKeyboardDriver *);
-
-Bool
-KdRegisterFd (int fd, void (*read) (int fd, void *closure), void *closure);
-
-void
-KdUnregisterFds (void *closure, Bool do_close);
-
-void
-KdUnregisterFd (void *closure, int fd, Bool do_close);
-
-void
-KdEnqueueKeyboardEvent(KdKeyboardInfo *ki, unsigned char scan_code,
- unsigned char is_up);
-
-#define KD_BUTTON_1 0x01
-#define KD_BUTTON_2 0x02
-#define KD_BUTTON_3 0x04
-#define KD_BUTTON_4 0x08
-#define KD_BUTTON_5 0x10
-#define KD_BUTTON_8 0x80
-#define KD_MOUSE_DELTA 0x80000000
-
-void
-KdEnqueuePointerEvent(KdPointerInfo *pi, unsigned long flags, int rx, int ry,
- int rz);
-
-void
-_KdEnqueuePointerEvent(KdPointerInfo *pi, int type, int x, int y, int z,
- int b, int absrel, Bool force);
-
-void
-KdReleaseAllKeys (void);
-
-void
-KdSetLed (KdKeyboardInfo *ki, int led, Bool on);
-
-void
-KdSetPointerMatrix (KdPointerMatrix *pointer);
-
-void
-KdComputePointerMatrix (KdPointerMatrix *pointer, Rotation randr, int width, int height);
-
-void
-KdScreenToPointerCoords (int *x, int *y);
-
-void
-KdBlockHandler (int screen,
- pointer blockData,
- pointer timeout,
- pointer readmask);
-
-void
-KdWakeupHandler (int screen,
- pointer data,
- unsigned long result,
- pointer readmask);
-
-void
-KdDisableInput (void);
-
-void
-KdEnableInput (void);
-
-void
-ProcessInputEvents (void);
-
-void
-KdRingBell (KdKeyboardInfo *ki,
- int volume,
- int pitch,
- int duration);
-
-/* kmode.c */
-const KdMonitorTiming *
-KdFindMode (KdScreenInfo *screen,
- Bool (*supported) (KdScreenInfo *,
- const KdMonitorTiming *));
-
-Bool
-KdTuneMode (KdScreenInfo *screen,
- Bool (*usable) (KdScreenInfo *),
- Bool (*supported) (KdScreenInfo *,
- const KdMonitorTiming *));
-
-#ifdef RANDR
-Bool
-KdRandRGetInfo (ScreenPtr pScreen,
- int randr,
- Bool (*supported) (ScreenPtr pScreen,
- const KdMonitorTiming *));
-
-const KdMonitorTiming *
-KdRandRGetTiming (ScreenPtr pScreen,
- Bool (*supported) (ScreenPtr pScreen,
- const KdMonitorTiming *),
- int rate,
- RRScreenSizePtr pSize);
-#endif
-
-/* kshadow.c */
-Bool
-KdShadowFbAlloc (KdScreenInfo *screen, Bool rotate);
-
-void
-KdShadowFbFree (KdScreenInfo *screen);
-
-Bool
-KdShadowSet (ScreenPtr pScreen, int randr, ShadowUpdateProc update, ShadowWindowProc window);
-
-void
-KdShadowUnset (ScreenPtr pScreen);
-
-/* function prototypes to be implemented by the drivers */
-void
-InitCard (char *name);
-
-#endif /* _KDRIVE_H_ */
+/* + * 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. + */ + +#ifndef _KDRIVE_H_ +#define _KDRIVE_H_ + +#include <stdio.h> +#include <string.h> +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/Xos.h> +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "servermd.h" +#include "mibstore.h" +#include "colormapst.h" +#include "gcstruct.h" +#include "input.h" +#include "mipointer.h" +#include "mi.h" +#include "dix.h" +#include "fb.h" +#include "fboverlay.h" +#include "shadow.h" +#include "randrstr.h" +#include "globals.h" + +#include "xkbstr.h" + +#define KD_DPMS_NORMAL 0 +#define KD_DPMS_STANDBY 1 +#define KD_DPMS_SUSPEND 2 +#define KD_DPMS_POWERDOWN 3 +#define KD_DPMS_MAX KD_DPMS_POWERDOWN + +#define Status int + +typedef struct _KdCardInfo { + struct _KdCardFuncs *cfuncs; + void *closure; + void *driver; + struct _KdScreenInfo *screenList; + int selected; + struct _KdCardInfo *next; +} KdCardInfo; + +extern KdCardInfo *kdCardInfo; + +/* + * Configuration information per X screen + */ +typedef struct _KdFrameBuffer { + CARD8 *frameBuffer; + int depth; + int bitsPerPixel; + int pixelStride; + int byteStride; + Bool shadow; + unsigned long visuals; + Pixel redMask, greenMask, blueMask; + void *closure; +} KdFrameBuffer; + +#define RR_Rotate_All (RR_Rotate_0|RR_Rotate_90|RR_Rotate_180|RR_Rotate_270) +#define RR_Reflect_All (RR_Reflect_X|RR_Reflect_Y) + +typedef struct _KdScreenInfo { + struct _KdScreenInfo *next; + KdCardInfo *card; + ScreenPtr pScreen; + void *driver; + Rotation randr; /* rotation and reflection */ + int width; + int height; + int rate; + int width_mm; + int height_mm; + int subpixel_order; + Bool dumb; + Bool softCursor; + int mynum; + DDXPointRec origin; + KdFrameBuffer fb; +} KdScreenInfo; + +typedef struct _KdCardFuncs { + Bool (*cardinit) (KdCardInfo *); /* detect and map device */ + Bool (*scrinit) (KdScreenInfo *);/* initialize screen information */ + Bool (*initScreen) (ScreenPtr); /* initialize ScreenRec */ + Bool (*finishInitScreen) (ScreenPtr pScreen); + Bool (*createRes) (ScreenPtr); /* create screen resources */ + void (*preserve) (KdCardInfo *); /* save graphics card state */ + Bool (*enable) (ScreenPtr); /* set up for rendering */ + Bool (*dpms) (ScreenPtr, int); /* set DPMS screen saver */ + void (*disable) (ScreenPtr); /* turn off rendering */ + void (*restore) (KdCardInfo *); /* restore graphics card state */ + void (*scrfini) (KdScreenInfo *);/* close down screen */ + void (*cardfini) (KdCardInfo *); /* close down */ + + Bool (*initCursor) (ScreenPtr); /* detect and map cursor */ + void (*enableCursor) (ScreenPtr); /* enable cursor */ + void (*disableCursor) (ScreenPtr); /* disable cursor */ + void (*finiCursor) (ScreenPtr); /* close down */ + void (*recolorCursor) (ScreenPtr, int, xColorItem *); + + Bool (*initAccel) (ScreenPtr); + void (*enableAccel) (ScreenPtr); + void (*disableAccel) (ScreenPtr); + void (*finiAccel) (ScreenPtr); + + void (*getColors) (ScreenPtr, int, xColorItem *); + void (*putColors) (ScreenPtr, int, xColorItem *); + +} KdCardFuncs; + +#define KD_MAX_PSEUDO_DEPTH 8 +#define KD_MAX_PSEUDO_SIZE (1 << KD_MAX_PSEUDO_DEPTH) + +typedef struct { + KdScreenInfo *screen; + KdCardInfo *card; + + Bool enabled; + Bool closed; + int bytesPerPixel; + + int dpmsState; + + ColormapPtr pInstalledmap; /* current colormap */ + xColorItem systemPalette[KD_MAX_PSEUDO_SIZE];/* saved windows colors */ + + CreateScreenResourcesProcPtr CreateScreenResources; + CloseScreenProcPtr CloseScreen; +} KdPrivScreenRec, *KdPrivScreenPtr; + +typedef enum _kdPointerState { + start, + button_1_pend, + button_1_down, + button_2_down, + button_3_pend, + button_3_down, + synth_2_down_13, + synth_2_down_3, + synth_2_down_1, + num_input_states +} KdPointerState; + +#define KD_MAX_BUTTON 32 + +#define KD_KEYBOARD 1 +#define KD_MOUSE 2 +#define KD_TOUCHSCREEN 3 + +typedef struct _KdPointerInfo KdPointerInfo; + +typedef struct _KdPointerDriver { + char *name; + Status (*Init) (KdPointerInfo *); + Status (*Enable) (KdPointerInfo *); + void (*Disable) (KdPointerInfo *); + void (*Fini) (KdPointerInfo *); + struct _KdPointerDriver *next; +} KdPointerDriver; + +struct _KdPointerInfo { + DeviceIntPtr dixdev; + char *name; + char *path; + char *protocol; + InputOption *options; + int inputClass; + + CARD8 map[KD_MAX_BUTTON + 1]; + int nButtons; + int nAxes; + + Bool emulateMiddleButton; + unsigned long emulationTimeout; + int emulationDx, emulationDy; + + Bool timeoutPending; + KdPointerState mouseState; + Bool eventHeld; + struct { + int type; + int x; + int y; + int z; + int flags; + int absrel; + } heldEvent; + unsigned char buttonState; + Bool transformCoordinates; + int pressureThreshold; + + KdPointerDriver *driver; + void *driverPrivate; + + struct _KdPointerInfo *next; +}; + +extern int KdCurScreen; + +void KdAddPointerDriver (KdPointerDriver *driver); +void KdRemovePointerDriver (KdPointerDriver *driver); +KdPointerInfo *KdNewPointer (void); +void KdFreePointer (KdPointerInfo *); +int KdAddPointer (KdPointerInfo *ki); +int KdAddConfigPointer (char *pointer); +void KdRemovePointer (KdPointerInfo *ki); + + +#define KD_KEY_COUNT 248 +#define KD_MIN_KEYCODE 8 +#define KD_MAX_KEYCODE 255 +#define KD_MAX_WIDTH 4 +#define KD_MAX_LENGTH (KD_MAX_KEYCODE - KD_MIN_KEYCODE + 1) + +typedef struct { + KeySym modsym; + int modbit; +} KdKeySymModsRec; + +typedef struct _KdKeyboardInfo KdKeyboardInfo; + +typedef struct _KdKeyboardDriver { + char *name; + Bool (*Init) (KdKeyboardInfo *); + Bool (*Enable) (KdKeyboardInfo *); + void (*Leds) (KdKeyboardInfo *, int); + void (*Bell) (KdKeyboardInfo *, int, int, int); + void (*Disable) (KdKeyboardInfo *); + void (*Fini) (KdKeyboardInfo *); + struct _KdKeyboardDriver *next; +} KdKeyboardDriver; + +struct _KdKeyboardInfo { + struct _KdKeyboardInfo *next; + DeviceIntPtr dixdev; + void *closure; + char *name; + char *path; + int inputClass; + char *xkbRules; + char *xkbModel; + char *xkbLayout; + char *xkbVariant; + char *xkbOptions; + int LockLed; + + int minScanCode; + int maxScanCode; + + int leds; + int bellPitch; + int bellDuration; + InputOption *options; + + KdKeyboardDriver *driver; + void *driverPrivate; +}; + +void KdAddKeyboardDriver (KdKeyboardDriver *driver); +void KdRemoveKeyboardDriver (KdKeyboardDriver *driver); +KdKeyboardInfo *KdNewKeyboard (void); +void KdFreeKeyboard (KdKeyboardInfo *ki); +int KdAddConfigKeyboard (char *pointer); +int KdAddKeyboard (KdKeyboardInfo *ki); +void KdRemoveKeyboard (KdKeyboardInfo *ki); + +typedef struct _KdOsFuncs { + int (*Init) (void); + void (*Enable) (void); + Bool (*SpecialKey) (KeySym); + void (*Disable) (void); + void (*Fini) (void); + void (*pollEvents) (void); + void (*Bell) (int, int, int); +} KdOsFuncs; + +typedef enum _KdSyncPolarity { + KdSyncNegative, KdSyncPositive +} KdSyncPolarity; + +typedef struct _KdMonitorTiming { + /* label */ + int horizontal; + int vertical; + int rate; + /* pixel clock */ + int clock; /* in KHz */ + /* horizontal timing */ + int hfp; /* front porch */ + int hbp; /* back porch */ + int hblank; /* blanking */ + KdSyncPolarity hpol; /* polarity */ + /* vertical timing */ + int vfp; /* front porch */ + int vbp; /* back porch */ + int vblank; /* blanking */ + KdSyncPolarity vpol; /* polarity */ +} KdMonitorTiming; + +extern const KdMonitorTiming kdMonitorTimings[]; +extern const int kdNumMonitorTimings; + +typedef struct _KdPointerMatrix { + int matrix[2][3]; +} KdPointerMatrix; + +/* + * This is the only completely portable way to + * compute this info. + */ + +#ifndef BitsPerPixel +#define BitsPerPixel(d) (\ + PixmapWidthPaddingInfo[d].notPower2 ? \ + (PixmapWidthPaddingInfo[d].bytesPerPixel * 8) : \ + ((1 << PixmapWidthPaddingInfo[d].padBytesLog2) * 8 / \ + (PixmapWidthPaddingInfo[d].padRoundUp+1))) +#endif + +extern DevPrivateKeyRec kdScreenPrivateKeyRec; +#define kdScreenPrivateKey (&kdScreenPrivateKeyRec) + +extern unsigned long kdGeneration; +extern Bool kdEnabled; +extern Bool kdSwitchPending; +extern Bool kdEmulateMiddleButton; +extern Bool kdDisableZaphod; +extern Bool kdAllowZap; +extern int kdVirtualTerminal; +extern char *kdSwitchCmd; +extern KdOsFuncs *kdOsFuncs; + +#define KdGetScreenPriv(pScreen) ((KdPrivScreenPtr) \ + dixLookupPrivate(&(pScreen)->devPrivates, kdScreenPrivateKey)) +#define KdSetScreenPriv(pScreen,v) \ + dixSetPrivate(&(pScreen)->devPrivates, kdScreenPrivateKey, v) +#define KdScreenPriv(pScreen) KdPrivScreenPtr pScreenPriv = KdGetScreenPriv(pScreen) + +/* kcmap.c */ +void +KdSetColormap (ScreenPtr pScreen); + +void +KdEnableColormap (ScreenPtr pScreen); + +void +KdDisableColormap (ScreenPtr pScreen); + +void +KdInstallColormap (ColormapPtr pCmap); + +void +KdUninstallColormap (ColormapPtr pCmap); + +int +KdListInstalledColormaps (ScreenPtr pScreen, Colormap *pCmaps); + +void +KdStoreColors (ColormapPtr pCmap, int ndef, xColorItem *pdefs); + +/* kdrive.c */ +extern miPointerScreenFuncRec kdPointerScreenFuncs; + +void +KdDisableScreen (ScreenPtr pScreen); + +void +KdDisableScreens (void); + +Bool +KdEnableScreen (ScreenPtr pScreen); + +void +KdEnableScreens (void); + +void +KdSuspend (void); + +void +KdResume (void); + +void +KdProcessSwitch (void); + +Rotation +KdAddRotation (Rotation a, Rotation b); + +Rotation +KdSubRotation (Rotation a, Rotation b); + +void +KdParseScreen (KdScreenInfo *screen, + char *arg); + +KdPointerInfo * +KdParsePointer (char *arg); + +KdKeyboardInfo * +KdParseKeyboard (char *arg); + +char * +KdParseFindNext (char *cur, char *delim, char *save, char *last); + +void +KdParseRgba (char *rgba); + +void +KdUseMsg (void); + +int +KdProcessArgument (int argc, char **argv, int i); + +void +KdOsInit (KdOsFuncs *pOsFuncs); + +void +KdOsAddInputDrivers (void); + +Bool +KdAllocatePrivates (ScreenPtr pScreen); + +Bool +KdCreateScreenResources (ScreenPtr pScreen); + +Bool +KdCloseScreen (int index, ScreenPtr pScreen); + +Bool +KdSaveScreen (ScreenPtr pScreen, int on); + +Bool +KdScreenInit(int index, ScreenPtr pScreen, int argc, char **argv); + +void +KdInitScreen (ScreenInfo *pScreenInfo, + KdScreenInfo *screen, + int argc, + char **argv); + +void +KdInitCard (ScreenInfo *pScreenInfo, + KdCardInfo *card, + int argc, + char **argv); + +void +KdInitOutput (ScreenInfo *pScreenInfo, + int argc, + char **argv); + +void +KdSetSubpixelOrder (ScreenPtr pScreen, Rotation randr); + +void +KdBacktrace (int signum); + +/* kinfo.c */ +KdCardInfo * +KdCardInfoAdd (KdCardFuncs *funcs, + void *closure); + +KdCardInfo * +KdCardInfoLast (void); + +void +KdCardInfoDispose (KdCardInfo *ci); + +KdScreenInfo * +KdScreenInfoAdd (KdCardInfo *ci); + +void +KdScreenInfoDispose (KdScreenInfo *si); + + +/* kinput.c */ +void +KdInitInput(void); + +void +KdAddPointerDriver(KdPointerDriver *); + +void +KdAddKeyboardDriver(KdKeyboardDriver *); + +Bool +KdRegisterFd (int fd, void (*read) (int fd, void *closure), void *closure); + +void +KdUnregisterFds (void *closure, Bool do_close); + +void +KdUnregisterFd (void *closure, int fd, Bool do_close); + +void +KdEnqueueKeyboardEvent(KdKeyboardInfo *ki, unsigned char scan_code, + unsigned char is_up); + +#define KD_BUTTON_1 0x01 +#define KD_BUTTON_2 0x02 +#define KD_BUTTON_3 0x04 +#define KD_BUTTON_4 0x08 +#define KD_BUTTON_5 0x10 +#define KD_BUTTON_8 0x80 +#define KD_MOUSE_DELTA 0x80000000 + +void +KdEnqueuePointerEvent(KdPointerInfo *pi, unsigned long flags, int rx, int ry, + int rz); + +void +_KdEnqueuePointerEvent(KdPointerInfo *pi, int type, int x, int y, int z, + int b, int absrel, Bool force); + +void +KdReleaseAllKeys (void); + +void +KdSetLed (KdKeyboardInfo *ki, int led, Bool on); + +void +KdSetPointerMatrix (KdPointerMatrix *pointer); + +void +KdComputePointerMatrix (KdPointerMatrix *pointer, Rotation randr, int width, int height); + +void +KdScreenToPointerCoords (int *x, int *y); + +void +KdBlockHandler (int screen, + pointer blockData, + pointer timeout, + pointer readmask); + +void +KdWakeupHandler (int screen, + pointer data, + unsigned long result, + pointer readmask); + +void +KdDisableInput (void); + +void +KdEnableInput (void); + +void +ProcessInputEvents (void); + +void +KdRingBell (KdKeyboardInfo *ki, + int volume, + int pitch, + int duration); + +/* kmode.c */ +const KdMonitorTiming * +KdFindMode (KdScreenInfo *screen, + Bool (*supported) (KdScreenInfo *, + const KdMonitorTiming *)); + +Bool +KdTuneMode (KdScreenInfo *screen, + Bool (*usable) (KdScreenInfo *), + Bool (*supported) (KdScreenInfo *, + const KdMonitorTiming *)); + +#ifdef RANDR +Bool +KdRandRGetInfo (ScreenPtr pScreen, + int randr, + Bool (*supported) (ScreenPtr pScreen, + const KdMonitorTiming *)); + +const KdMonitorTiming * +KdRandRGetTiming (ScreenPtr pScreen, + Bool (*supported) (ScreenPtr pScreen, + const KdMonitorTiming *), + int rate, + RRScreenSizePtr pSize); +#endif + +/* kshadow.c */ +Bool +KdShadowFbAlloc (KdScreenInfo *screen, Bool rotate); + +void +KdShadowFbFree (KdScreenInfo *screen); + +Bool +KdShadowSet (ScreenPtr pScreen, int randr, ShadowUpdateProc update, ShadowWindowProc window); + +void +KdShadowUnset (ScreenPtr pScreen); + +/* function prototypes to be implemented by the drivers */ +void +InitCard (char *name); + +#endif /* _KDRIVE_H_ */ diff --git a/xorg-server/hw/kdrive/src/kinput.c b/xorg-server/hw/kdrive/src/kinput.c index 0485dc413..e3bc4c523 100644 --- a/xorg-server/hw/kdrive/src/kinput.c +++ b/xorg-server/hw/kdrive/src/kinput.c @@ -1,2331 +1,2328 @@ -/*
- * Copyright © 1999 Keith Packard
- * Copyright © 2006 Nokia Corporation
- *
- * 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 authors not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. The authors make no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THE AUTHORS 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 <kdrive-config.h>
-#endif
-#include "kdrive.h"
-#include "inputstr.h"
-
-#define XK_PUBLISHING
-#include <X11/keysym.h>
-#if HAVE_X11_XF86KEYSYM_H
-#include <X11/XF86keysym.h>
-#endif
-#include <signal.h>
-#include <stdio.h>
-#ifdef sun
-#include <sys/file.h> /* needed for FNONBLOCK & FASYNC */
-#endif
-
-#include "xkbsrv.h"
-
-#include <X11/extensions/XI.h>
-#include <X11/extensions/XIproto.h>
-#include "XIstubs.h" /* even though we don't use stubs. cute, no? */
-#include "exevents.h"
-#include "extinit.h"
-#include "exglobals.h"
-#include "eventstr.h"
-#include "xserver-properties.h"
-#include "inpututils.h"
-
-#define AtomFromName(x) MakeAtom(x, strlen(x), 1)
-
-struct KdConfigDevice {
- char *line;
- struct KdConfigDevice *next;
-};
-
-/* kdKeyboards and kdPointers hold all the real devices. */
-static KdKeyboardInfo *kdKeyboards = NULL;
-static KdPointerInfo *kdPointers = NULL;
-static struct KdConfigDevice *kdConfigKeyboards = NULL;
-static struct KdConfigDevice *kdConfigPointers = NULL;
-
-static KdKeyboardDriver *kdKeyboardDrivers = NULL;
-static KdPointerDriver *kdPointerDrivers = NULL;
-
-static EventListPtr kdEvents = NULL;
-
-static Bool kdInputEnabled;
-static Bool kdOffScreen;
-static unsigned long kdOffScreenTime;
-static KdPointerMatrix kdPointerMatrix = {
- { { 1, 0, 0 },
- { 0, 1, 0 } }
-};
-
-void KdResetInputMachine (void);
-
-#define KD_MAX_INPUT_FDS 8
-
-typedef struct _kdInputFd {
- int fd;
- void (*read) (int fd, void *closure);
- int (*enable) (int fd, void *closure);
- void (*disable) (int fd, void *closure);
- void *closure;
-} KdInputFd;
-
-static KdInputFd kdInputFds[KD_MAX_INPUT_FDS];
-static int kdNumInputFds;
-
-extern Bool kdRawPointerCoordinates;
-
-static void
-KdSigio (int sig)
-{
- int i;
-
- for (i = 0; i < kdNumInputFds; i++)
- (*kdInputFds[i].read) (kdInputFds[i].fd, kdInputFds[i].closure);
-}
-
-static void
-KdBlockSigio (void)
-{
- sigset_t set;
-
- sigemptyset (&set);
- sigaddset (&set, SIGIO);
- sigprocmask (SIG_BLOCK, &set, 0);
-}
-
-static void
-KdUnblockSigio (void)
-{
- sigset_t set;
-
- sigemptyset (&set);
- sigaddset (&set, SIGIO);
- sigprocmask (SIG_UNBLOCK, &set, 0);
-}
-
-#ifdef DEBUG_SIGIO
-
-void
-KdAssertSigioBlocked (char *where)
-{
- sigset_t set, old;
-
- sigemptyset (&set);
- sigprocmask (SIG_BLOCK, &set, &old);
- if (!sigismember (&old, SIGIO)) {
- ErrorF ("SIGIO not blocked at %s\n", where);
- KdBacktrace(0);
- }
-}
-
-#else
-
-#define KdAssertSigioBlocked(s)
-
-#endif
-
-static int kdnFds;
-
-#ifdef FNONBLOCK
-#define NOBLOCK FNONBLOCK
-#else
-#define NOBLOCK FNDELAY
-#endif
-
-void
-KdResetInputMachine (void)
-{
- KdPointerInfo *pi;
-
- for (pi = kdPointers; pi; pi = pi->next) {
- pi->mouseState = start;
- pi->eventHeld = FALSE;
- }
-}
-
-static void
-KdNonBlockFd (int fd)
-{
- int flags;
- flags = fcntl (fd, F_GETFL);
- flags |= FASYNC|NOBLOCK;
- fcntl (fd, F_SETFL, flags);
-}
-
-static void
-KdAddFd (int fd)
-{
- struct sigaction act;
- sigset_t set;
-
- kdnFds++;
- fcntl (fd, F_SETOWN, getpid());
- KdNonBlockFd (fd);
- AddEnabledDevice (fd);
- memset (&act, '\0', sizeof act);
- act.sa_handler = KdSigio;
- sigemptyset (&act.sa_mask);
- sigaddset (&act.sa_mask, SIGIO);
- sigaddset (&act.sa_mask, SIGALRM);
- sigaddset (&act.sa_mask, SIGVTALRM);
- sigaction (SIGIO, &act, 0);
- sigemptyset (&set);
- sigprocmask (SIG_SETMASK, &set, 0);
-}
-
-static void
-KdRemoveFd (int fd)
-{
- struct sigaction act;
- int flags;
-
- kdnFds--;
- RemoveEnabledDevice (fd);
- flags = fcntl (fd, F_GETFL);
- flags &= ~(FASYNC|NOBLOCK);
- fcntl (fd, F_SETFL, flags);
- if (kdnFds == 0)
- {
- memset (&act, '\0', sizeof act);
- act.sa_handler = SIG_IGN;
- sigemptyset (&act.sa_mask);
- sigaction (SIGIO, &act, 0);
- }
-}
-
-Bool
-KdRegisterFd (int fd, void (*read) (int fd, void *closure), void *closure)
-{
- if (kdNumInputFds == KD_MAX_INPUT_FDS)
- return FALSE;
- kdInputFds[kdNumInputFds].fd = fd;
- kdInputFds[kdNumInputFds].read = read;
- kdInputFds[kdNumInputFds].enable = 0;
- kdInputFds[kdNumInputFds].disable = 0;
- kdInputFds[kdNumInputFds].closure = closure;
- kdNumInputFds++;
- if (kdInputEnabled)
- KdAddFd (fd);
- return TRUE;
-}
-
-void
-KdUnregisterFd (void *closure, int fd, Bool do_close)
-{
- int i, j;
-
- for (i = 0; i < kdNumInputFds; i++) {
- if (kdInputFds[i].closure == closure &&
- (fd == -1 || kdInputFds[i].fd == fd)) {
- if (kdInputEnabled)
- KdRemoveFd (kdInputFds[i].fd);
- if (do_close)
- close (kdInputFds[i].fd);
- kdNumInputFds--;
- for (j = i; j < kdNumInputFds; j++)
- kdInputFds[j] = kdInputFds[j+1];
- break;
- }
- }
-}
-
-void
-KdUnregisterFds (void *closure, Bool do_close)
-{
- KdUnregisterFd(closure, -1, do_close);
-}
-
-void
-KdDisableInput (void)
-{
- KdKeyboardInfo *ki;
- KdPointerInfo *pi;
- int found = 0, i = 0;
-
- KdBlockSigio();
-
- for (ki = kdKeyboards; ki; ki = ki->next) {
- if (ki->driver && ki->driver->Disable)
- (*ki->driver->Disable) (ki);
- }
-
- for (pi = kdPointers; pi; pi = pi->next) {
- if (pi->driver && pi->driver->Disable)
- (*pi->driver->Disable) (pi);
- }
-
- if (kdNumInputFds) {
- ErrorF("[KdDisableInput] Buggy drivers: still %d input fds left!",
- kdNumInputFds);
- i = 0;
- while (i < kdNumInputFds) {
- found = 0;
- for (ki = kdKeyboards; ki; ki = ki->next) {
- if (ki == kdInputFds[i].closure) {
- ErrorF(" fd %d belongs to keybd driver %s\n",
- kdInputFds[i].fd,
- ki->driver && ki->driver->name ?
- ki->driver->name : "(unnamed!)");
- found = 1;
- break;
- }
- }
-
- if (found) {
- i++;
- continue;
- }
-
- for (pi = kdPointers; pi; pi = pi->next) {
- if (pi == kdInputFds[i].closure) {
- ErrorF(" fd %d belongs to pointer driver %s\n",
- kdInputFds[i].fd,
- pi->driver && pi->driver->name ?
- pi->driver->name : "(unnamed!)");
- break;
- }
- }
-
- if (found) {
- i++;
- continue;
- }
-
- ErrorF(" fd %d not claimed by any active device!\n",
- kdInputFds[i].fd);
- KdUnregisterFd(kdInputFds[i].closure, kdInputFds[i].fd, TRUE);
- }
- }
-
- kdInputEnabled = FALSE;
-}
-
-void
-KdEnableInput (void)
-{
- InternalEvent ev;
- KdKeyboardInfo *ki;
- KdPointerInfo *pi;
-
- kdInputEnabled = TRUE;
-
- for (ki = kdKeyboards; ki; ki = ki->next) {
- if (ki->driver && ki->driver->Enable)
- (*ki->driver->Enable) (ki);
- }
-
- for (pi = kdPointers; pi; pi = pi->next) {
- if (pi->driver && pi->driver->Enable)
- (*pi->driver->Enable) (pi);
- }
-
- /* reset screen saver */
- ev.any.time = GetTimeInMillis ();
- NoticeEventTime (&ev);
-
- KdUnblockSigio ();
-}
-
-static KdKeyboardDriver *
-KdFindKeyboardDriver (char *name)
-{
- KdKeyboardDriver *ret;
-
- /* ask a stupid question ... */
- if (!name)
- return NULL;
-
- for (ret = kdKeyboardDrivers; ret; ret = ret->next) {
- if (strcmp(ret->name, name) == 0)
- return ret;
- }
-
- return NULL;
-}
-
-static KdPointerDriver *
-KdFindPointerDriver (char *name)
-{
- KdPointerDriver *ret;
-
- /* ask a stupid question ... */
- if (!name)
- return NULL;
-
- for (ret = kdPointerDrivers; ret; ret = ret->next) {
- if (strcmp(ret->name, name) == 0)
- return ret;
- }
-
- return NULL;
-}
-
-static int
-KdPointerProc(DeviceIntPtr pDevice, int onoff)
-{
- DevicePtr pDev = (DevicePtr)pDevice;
- KdPointerInfo *pi;
- Atom xiclass;
- Atom *btn_labels;
- Atom *axes_labels;
-
- if (!pDev)
- return BadImplementation;
-
- for (pi = kdPointers; pi; pi = pi->next) {
- if (pi->dixdev && pi->dixdev->id == pDevice->id)
- break;
- }
-
- if (!pi || !pi->dixdev || pi->dixdev->id != pDevice->id) {
- ErrorF("[KdPointerProc] Failed to find pointer for device %d!\n",
- pDevice->id);
- return BadImplementation;
- }
-
- switch (onoff)
- {
- case DEVICE_INIT:
-#ifdef DEBUG
- ErrorF("initialising pointer %s ...\n", pi->name);
-#endif
- if (!pi->driver) {
- if (!pi->driverPrivate) {
- ErrorF("no driver specified for %s\n", pi->name);
- return BadImplementation;
- }
-
- pi->driver = KdFindPointerDriver(pi->driverPrivate);
- if (!pi->driver) {
- ErrorF("Couldn't find pointer driver %s\n",
- pi->driverPrivate ? (char *) pi->driverPrivate :
- "(unnamed)");
- return !Success;
- }
- free(pi->driverPrivate);
- pi->driverPrivate = NULL;
- }
-
- if (!pi->driver->Init) {
- ErrorF("no init function\n");
- return BadImplementation;
- }
-
- if ((*pi->driver->Init) (pi) != Success) {
- return !Success;
- }
-
- btn_labels = calloc(pi->nButtons, sizeof(Atom));
- if (!btn_labels)
- return BadAlloc;
- axes_labels = calloc(pi->nAxes, sizeof(Atom));
- if (!axes_labels) {
- free(btn_labels);
- return BadAlloc;
- }
-
- switch(pi->nAxes)
- {
- default:
- case 7:
- btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
- case 6:
- btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
- case 5:
- btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
- case 4:
- btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
- case 3:
- btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
- case 2:
- btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
- case 1:
- btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
- case 0:
- break;
- }
-
- if (pi->nAxes >= 2) {
- axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
- axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
- }
-
- InitPointerDeviceStruct(pDev, pi->map, pi->nButtons, btn_labels,
- (PtrCtrlProcPtr)NoopDDA,
- GetMotionHistorySize(), pi->nAxes, axes_labels);
-
- free(btn_labels);
- free(axes_labels);
-
- if (pi->inputClass == KD_TOUCHSCREEN) {
- InitAbsoluteClassDeviceStruct(pDevice);
- xiclass = AtomFromName(XI_TOUCHSCREEN);
- }
- else {
- xiclass = AtomFromName(XI_MOUSE);
- }
-
- AssignTypeAndName(pi->dixdev, xiclass,
- pi->name ? pi->name : "Generic KDrive Pointer");
-
- return Success;
-
- case DEVICE_ON:
- if (pDev->on == TRUE)
- return Success;
-
- if (!pi->driver->Enable) {
- ErrorF("no enable function\n");
- return BadImplementation;
- }
-
- if ((*pi->driver->Enable) (pi) == Success) {
- pDev->on = TRUE;
- return Success;
- }
- else {
- return BadImplementation;
- }
-
- return Success;
-
- case DEVICE_OFF:
- if (pDev->on == FALSE) {
- return Success;
- }
-
- if (!pi->driver->Disable) {
- return BadImplementation;
- }
- else {
- (*pi->driver->Disable) (pi);
- pDev->on = FALSE;
- return Success;
- }
-
- return Success;
-
- case DEVICE_CLOSE:
- if (pDev->on) {
- if (!pi->driver->Disable) {
- return BadImplementation;
- }
- (*pi->driver->Disable) (pi);
- pDev->on = FALSE;
- }
-
- if (!pi->driver->Fini)
- return BadImplementation;
-
- (*pi->driver->Fini) (pi);
-
- KdRemovePointer(pi);
-
- return Success;
- }
-
- /* NOTREACHED */
- return BadImplementation;
-}
-
-Bool
-LegalModifier(unsigned int key, DeviceIntPtr pDev)
-{
- return TRUE;
-}
-
-static void
-KdBell (int volume, DeviceIntPtr pDev, pointer arg, int something)
-{
- KeybdCtrl *ctrl = arg;
- KdKeyboardInfo *ki = NULL;
-
- for (ki = kdKeyboards; ki; ki = ki->next) {
- if (ki->dixdev && ki->dixdev->id == pDev->id)
- break;
- }
-
- if (!ki || !ki->dixdev || ki->dixdev->id != pDev->id || !ki->driver)
- return;
-
- KdRingBell(ki, volume, ctrl->bell_pitch, ctrl->bell_duration);
-}
-
-void
-DDXRingBell(int volume, int pitch, int duration)
-{
- KdKeyboardInfo *ki = NULL;
-
- if (kdOsFuncs->Bell) {
- (*kdOsFuncs->Bell)(volume, pitch, duration);
- }
- else {
- for (ki = kdKeyboards; ki; ki = ki->next) {
- if (ki->dixdev->coreEvents)
- KdRingBell(ki, volume, pitch, duration);
- }
- }
-}
-
-void
-KdRingBell(KdKeyboardInfo *ki, int volume, int pitch, int duration)
-{
- if (!ki || !ki->driver || !ki->driver->Bell)
- return;
-
- if (kdInputEnabled)
- (*ki->driver->Bell) (ki, volume, pitch, duration);
-}
-
-
-static void
-KdSetLeds (KdKeyboardInfo *ki, int leds)
-{
- if (!ki || !ki->driver)
- return;
-
- if (kdInputEnabled) {
- if (ki->driver->Leds)
- (*ki->driver->Leds) (ki, leds);
- }
-}
-
-void
-KdSetLed (KdKeyboardInfo *ki, int led, Bool on)
-{
- if (!ki || !ki->dixdev || !ki->dixdev->kbdfeed)
- return;
-
- NoteLedState (ki->dixdev, led, on);
- KdSetLeds (ki, ki->dixdev->kbdfeed->ctrl.leds);
-}
-
-void
-KdSetPointerMatrix (KdPointerMatrix *matrix)
-{
- kdPointerMatrix = *matrix;
-}
-
-void
-KdComputePointerMatrix (KdPointerMatrix *m, Rotation randr, int width,
- int height)
-{
- int x_dir = 1, y_dir = 1;
- int i, j;
- int size[2];
-
- size[0] = width; size[1] = height;
- if (randr & RR_Reflect_X)
- x_dir = -1;
- if (randr & RR_Reflect_Y)
- y_dir = -1;
- switch (randr & (RR_Rotate_All)) {
- case RR_Rotate_0:
- m->matrix[0][0] = x_dir; m->matrix[0][1] = 0;
- m->matrix[1][0] = 0; m->matrix[1][1] = y_dir;
- break;
- case RR_Rotate_90:
- m->matrix[0][0] = 0; m->matrix[0][1] = -x_dir;
- m->matrix[1][0] = y_dir; m->matrix[1][1] = 0;
- break;
- case RR_Rotate_180:
- m->matrix[0][0] = -x_dir; m->matrix[0][1] = 0;
- m->matrix[1][0] = 0; m->matrix[1][1] = -y_dir;
- break;
- case RR_Rotate_270:
- m->matrix[0][0] = 0; m->matrix[0][1] = x_dir;
- m->matrix[1][0] = -y_dir; m->matrix[1][1] = 0;
- break;
- }
- for (i = 0; i < 2; i++)
- {
- m->matrix[i][2] = 0;
- for (j = 0 ; j < 2; j++)
- if (m->matrix[i][j] < 0)
- m->matrix[i][2] = size[j] - 1;
- }
-}
-
-void
-KdScreenToPointerCoords (int *x, int *y)
-{
- int (*m)[3] = kdPointerMatrix.matrix;
- int div = m[0][1] * m[1][0] - m[1][1] * m[0][0];
- int sx = *x;
- int sy = *y;
-
- *x = (m[0][1] * sy - m[0][1] * m[1][2] + m[1][1] * m[0][2] - m[1][1] * sx) / div;
- *y = (m[1][0] * sx + m[0][0] * m[1][2] - m[1][0] * m[0][2] - m[0][0] * sy) / div;
-}
-
-static void
-KdKbdCtrl (DeviceIntPtr pDevice, KeybdCtrl *ctrl)
-{
- KdKeyboardInfo *ki;
-
- for (ki = kdKeyboards; ki; ki = ki->next) {
- if (ki->dixdev && ki->dixdev->id == pDevice->id)
- break;
- }
-
- if (!ki || !ki->dixdev || ki->dixdev->id != pDevice->id || !ki->driver)
- return;
-
- KdSetLeds(ki, ctrl->leds);
- ki->bellPitch = ctrl->bell_pitch;
- ki->bellDuration = ctrl->bell_duration;
-}
-
-extern KeybdCtrl defaultKeyboardControl;
-
-static int
-KdKeyboardProc(DeviceIntPtr pDevice, int onoff)
-{
- Bool ret;
- DevicePtr pDev = (DevicePtr)pDevice;
- KdKeyboardInfo *ki;
- Atom xiclass;
- XkbRMLVOSet rmlvo;
-
- if (!pDev)
- return BadImplementation;
-
- for (ki = kdKeyboards; ki; ki = ki->next) {
- if (ki->dixdev && ki->dixdev->id == pDevice->id)
- break;
- }
-
- if (!ki || !ki->dixdev || ki->dixdev->id != pDevice->id) {
- return BadImplementation;
- }
-
- switch (onoff)
- {
- case DEVICE_INIT:
-#ifdef DEBUG
- ErrorF("initialising keyboard %s\n", ki->name);
-#endif
- if (!ki->driver) {
- if (!ki->driverPrivate) {
- ErrorF("no driver specified!\n");
- return BadImplementation;
- }
-
- ki->driver = KdFindKeyboardDriver(ki->driverPrivate);
- if (!ki->driver) {
- ErrorF("Couldn't find keyboard driver %s\n",
- ki->driverPrivate ? (char *) ki->driverPrivate :
- "(unnamed)");
- return !Success;
- }
- free(ki->driverPrivate);
- ki->driverPrivate = NULL;
- }
-
- if (!ki->driver->Init) {
- ErrorF("Keyboard %s: no init function\n", ki->name);
- return BadImplementation;
- }
-
- if ((*ki->driver->Init) (ki) != Success) {
- return !Success;
- }
-
- memset(&rmlvo, 0, sizeof(rmlvo));
- rmlvo.rules = ki->xkbRules;
- rmlvo.model = ki->xkbModel;
- rmlvo.layout = ki->xkbLayout;
- rmlvo.variant = ki->xkbVariant;
- rmlvo.options = ki->xkbOptions;
- ret = InitKeyboardDeviceStruct (pDevice, &rmlvo, KdBell, KdKbdCtrl);
- if (!ret) {
- ErrorF("Couldn't initialise keyboard %s\n", ki->name);
- return BadImplementation;
- }
-
- xiclass = AtomFromName(XI_KEYBOARD);
- AssignTypeAndName(pDevice, xiclass,
- ki->name ? ki->name : "Generic KDrive Keyboard");
-
- KdResetInputMachine();
-
- return Success;
-
- case DEVICE_ON:
- if (pDev->on == TRUE)
- return Success;
-
- if (!ki->driver->Enable)
- return BadImplementation;
-
- if ((*ki->driver->Enable) (ki) != Success) {
- return BadMatch;
- }
-
- pDev->on = TRUE;
- return Success;
-
- case DEVICE_OFF:
- if (pDev->on == FALSE)
- return Success;
-
- if (!ki->driver->Disable)
- return BadImplementation;
-
- (*ki->driver->Disable) (ki);
- pDev->on = FALSE;
-
- return Success;
-
- break;
-
- case DEVICE_CLOSE:
- if (pDev->on) {
- if (!ki->driver->Disable)
- return BadImplementation;
-
- (*ki->driver->Disable) (ki);
- pDev->on = FALSE;
- }
-
- if (!ki->driver->Fini)
- return BadImplementation;
-
- (*ki->driver->Fini) (ki);
-
- KdRemoveKeyboard(ki);
-
- return Success;
- }
-
- /* NOTREACHED */
- return BadImplementation;
-}
-
-void
-KdAddPointerDriver (KdPointerDriver *driver)
-{
- KdPointerDriver **prev;
-
- if (!driver)
- return;
-
- for (prev = &kdPointerDrivers; *prev; prev = &(*prev)->next) {
- if (*prev == driver)
- return;
- }
- *prev = driver;
-}
-
-void
-KdRemovePointerDriver (KdPointerDriver *driver)
-{
- KdPointerDriver *tmp;
-
- if (!driver)
- return;
-
- /* FIXME remove all pointers using this driver */
- for (tmp = kdPointerDrivers; tmp; tmp = tmp->next) {
- if (tmp->next == driver)
- tmp->next = driver->next;
- }
- if (tmp == driver)
- tmp = NULL;
-}
-
-void
-KdAddKeyboardDriver (KdKeyboardDriver *driver)
-{
- KdKeyboardDriver **prev;
-
- if (!driver)
- return;
-
- for (prev = &kdKeyboardDrivers; *prev; prev = &(*prev)->next) {
- if (*prev == driver)
- return;
- }
- *prev = driver;
-}
-
-void
-KdRemoveKeyboardDriver (KdKeyboardDriver *driver)
-{
- KdKeyboardDriver *tmp;
-
- if (!driver)
- return;
-
- /* FIXME remove all keyboards using this driver */
- for (tmp = kdKeyboardDrivers; tmp; tmp = tmp->next) {
- if (tmp->next == driver)
- tmp->next = driver->next;
- }
- if (tmp == driver)
- tmp = NULL;
-}
-
-KdKeyboardInfo *
-KdNewKeyboard (void)
-{
- KdKeyboardInfo *ki = calloc(sizeof(KdKeyboardInfo), 1);
- if (!ki)
- return NULL;
-
- ki->minScanCode = 0;
- ki->maxScanCode = 0;
- ki->leds = 0;
- ki->bellPitch = 1000;
- ki->bellDuration = 200;
- ki->next = NULL;
- ki->options = NULL;
- ki->xkbRules = strdup(XKB_DFLT_RULES);
- ki->xkbModel = strdup(XKB_DFLT_MODEL);
- ki->xkbLayout = strdup(XKB_DFLT_LAYOUT);
- ki->xkbVariant = strdup(XKB_DFLT_VARIANT);
- ki->xkbOptions = strdup(XKB_DFLT_OPTIONS);
-
- return ki;
-}
-
-int
-KdAddConfigKeyboard (char *keyboard)
-{
- struct KdConfigDevice **prev, *new;
-
- if (!keyboard)
- return Success;
-
- new = (struct KdConfigDevice *) calloc(sizeof(struct KdConfigDevice), 1);
- if (!new)
- return BadAlloc;
-
- new->line = strdup(keyboard);
- new->next = NULL;
-
- for (prev = &kdConfigKeyboards; *prev; prev = &(*prev)->next);
- *prev = new;
-
- return Success;
-}
-
-int
-KdAddKeyboard (KdKeyboardInfo *ki)
-{
- KdKeyboardInfo **prev;
-
- if (!ki)
- return !Success;
-
- ki->dixdev = AddInputDevice(serverClient, KdKeyboardProc, TRUE);
- if (!ki->dixdev) {
- ErrorF("Couldn't register keyboard device %s\n",
- ki->name ? ki->name : "(unnamed)");
- return !Success;
- }
-
-#ifdef DEBUG
- ErrorF("added keyboard %s with dix id %d\n", ki->name, ki->dixdev->id);
-#endif
-
- for (prev = &kdKeyboards; *prev; prev = &(*prev)->next);
- *prev = ki;
-
- return Success;
-}
-
-void
-KdRemoveKeyboard (KdKeyboardInfo *ki)
-{
- KdKeyboardInfo **prev;
-
- if (!ki)
- return;
-
- for (prev = &kdKeyboards; *prev; prev = &(*prev)->next) {
- if (*prev == ki) {
- *prev = ki->next;
- break;
- }
- }
-
- KdFreeKeyboard(ki);
-}
-
-int
-KdAddConfigPointer (char *pointer)
-{
- struct KdConfigDevice **prev, *new;
-
- if (!pointer)
- return Success;
-
- new = (struct KdConfigDevice *) calloc(sizeof(struct KdConfigDevice), 1);
- if (!new)
- return BadAlloc;
-
- new->line = strdup(pointer);
- new->next = NULL;
-
- for (prev = &kdConfigPointers; *prev; prev = &(*prev)->next);
- *prev = new;
-
- return Success;
-}
-
-int
-KdAddPointer (KdPointerInfo *pi)
-{
- KdPointerInfo **prev;
-
- if (!pi)
- return Success;
-
- pi->mouseState = start;
- pi->eventHeld = FALSE;
-
- pi->dixdev = AddInputDevice(serverClient, KdPointerProc, TRUE);
- if (!pi->dixdev) {
- ErrorF("Couldn't add pointer device %s\n",
- pi->name ? pi->name : "(unnamed)");
- return BadDevice;
- }
-
- for (prev = &kdPointers; *prev; prev = &(*prev)->next);
- *prev = pi;
-
- return Success;
-}
-
-void
-KdRemovePointer (KdPointerInfo *pi)
-{
- KdPointerInfo **prev;
-
- if (!pi)
- return;
-
- for (prev = &kdPointers; *prev; prev = &(*prev)->next) {
- if (*prev == pi) {
- *prev = pi->next;
- break;
- }
- }
-
- KdFreePointer(pi);
-}
-
-/*
- * You can call your kdriver server with something like:
- * $ ./hw/kdrive/yourserver/X :1 -mouse evdev,,device=/dev/input/event4 -keybd
- * evdev,,device=/dev/input/event1,xkbmodel=abnt2,xkblayout=br
- */
-static Bool
-KdGetOptions (InputOption **options, char *string)
-{
- InputOption *newopt = NULL, **tmpo = NULL;
- int tam_key = 0;
-
- newopt = calloc(1, sizeof (InputOption));
- if (!newopt)
- return FALSE;
-
- for (tmpo = options; *tmpo; tmpo = &(*tmpo)->next)
- ; /* Hello, I'm here */
- *tmpo = newopt;
-
- if (strchr(string, '='))
- {
- tam_key = (strchr(string, '=') - string);
- newopt->key = (char *)malloc(tam_key);
- strncpy(newopt->key, string, tam_key);
- newopt->key[tam_key] = '\0';
- newopt->value = strdup(strchr(string, '=') + 1);
- }
- else
- {
- newopt->key = strdup(string);
- newopt->value = NULL;
- }
- newopt->next = NULL;
-
- return TRUE;
-}
-
-static void
-KdParseKbdOptions (KdKeyboardInfo *ki)
-{
- InputOption *option = NULL;
-
- for (option = ki->options; option; option = option->next)
- {
- if (strcasecmp(option->key, "XkbRules") == 0)
- ki->xkbRules = option->value;
- else if (strcasecmp(option->key, "XkbModel") == 0)
- ki->xkbModel = option->value;
- else if (strcasecmp(option->key, "XkbLayout") == 0)
- ki->xkbLayout = option->value;
- else if (strcasecmp(option->key, "XkbVariant") == 0)
- ki->xkbVariant = option->value;
- else if (strcasecmp(option->key, "XkbOptions") == 0)
- ki->xkbOptions = option->value;
- else if (!strcasecmp (option->key, "device"))
- ki->path = strdup(option->value);
- else
- ErrorF("Kbd option key (%s) of value (%s) not assigned!\n",
- option->key, option->value);
- }
-}
-
-KdKeyboardInfo *
-KdParseKeyboard (char *arg)
-{
- char save[1024];
- char delim;
- InputOption *options = NULL;
- KdKeyboardInfo *ki = NULL;
-
- ki = KdNewKeyboard();
- if (!ki)
- return NULL;
-
- ki->name = strdup("Unknown KDrive Keyboard");
- ki->path = NULL;
- ki->driver = NULL;
- ki->driverPrivate = NULL;
- ki->next = NULL;
-
- if (!arg)
- {
- ErrorF("keybd: no arg\n");
- KdFreeKeyboard (ki);
- return NULL;
- }
-
- if (strlen (arg) >= sizeof (save))
- {
- ErrorF("keybd: arg too long\n");
- KdFreeKeyboard (ki);
- return NULL;
- }
-
- arg = KdParseFindNext (arg, ",", save, &delim);
- if (!save[0])
- {
- ErrorF("keybd: failed on save[0]\n");
- KdFreeKeyboard (ki);
- return NULL;
- }
-
- if (strcmp (save, "auto") == 0)
- ki->driverPrivate = NULL;
- else
- ki->driverPrivate = strdup(save);
-
- if (delim != ',')
- {
- return ki;
- }
-
- arg = KdParseFindNext (arg, ",", save, &delim);
-
- while (delim == ',')
- {
- arg = KdParseFindNext (arg, ",", save, &delim);
-
- if (!KdGetOptions(&options, save))
- {
- KdFreeKeyboard(ki);
- return NULL;
- }
- }
-
- if (options)
- {
- ki->options = options;
- KdParseKbdOptions(ki);
- }
-
- return ki;
-}
-
-static void
-KdParsePointerOptions (KdPointerInfo *pi)
-{
- InputOption *option = NULL;
-
- for (option = pi->options; option; option = option->next)
- {
- if (!strcmp (option->key, "emulatemiddle"))
- pi->emulateMiddleButton = TRUE;
- else if (!strcmp (option->key, "noemulatemiddle"))
- pi->emulateMiddleButton = FALSE;
- else if (!strcmp (option->key, "transformcoord"))
- pi->transformCoordinates = TRUE;
- else if (!strcmp (option->key, "rawcoord"))
- pi->transformCoordinates = FALSE;
- else if (!strcasecmp (option->key, "device"))
- pi->path = strdup(option->value);
- else if (!strcasecmp (option->key, "protocol"))
- pi->protocol = strdup(option->value);
- else
- ErrorF("Pointer option key (%s) of value (%s) not assigned!\n",
- option->key, option->value);
- }
-}
-
-KdPointerInfo *
-KdParsePointer (char *arg)
-{
- char save[1024];
- char delim;
- KdPointerInfo *pi = NULL;
- InputOption *options = NULL;
- int i = 0;
-
- pi = KdNewPointer();
- if (!pi)
- return NULL;
- pi->emulateMiddleButton = kdEmulateMiddleButton;
- pi->transformCoordinates = !kdRawPointerCoordinates;
- pi->protocol = NULL;
- pi->nButtons = 5; /* XXX should not be hardcoded */
- pi->inputClass = KD_MOUSE;
-
- if (!arg)
- {
- ErrorF("mouse: no arg\n");
- KdFreePointer (pi);
- return NULL;
- }
-
- if (strlen (arg) >= sizeof (save))
- {
- ErrorF("mouse: arg too long\n");
- KdFreePointer (pi);
- return NULL;
- }
- arg = KdParseFindNext (arg, ",", save, &delim);
- if (!save[0])
- {
- ErrorF("failed on save[0]\n");
- KdFreePointer (pi);
- return NULL;
- }
-
- if (strcmp(save, "auto") == 0)
- pi->driverPrivate = NULL;
- else
- pi->driverPrivate = strdup(save);
-
- if (delim != ',')
- {
- return pi;
- }
-
- arg = KdParseFindNext (arg, ",", save, &delim);
-
- while (delim == ',')
- {
- arg = KdParseFindNext (arg, ",", save, &delim);
- if (save[0] == '{')
- {
- char *s = save + 1;
- i = 0;
- while (*s && *s != '}')
- {
- if ('1' <= *s && *s <= '0' + pi->nButtons)
- pi->map[i] = *s - '0';
- else
- UseMsg ();
- s++;
- }
- }
- else
- {
- if (!KdGetOptions(&options, save))
- {
- KdFreePointer(pi);
- return NULL;
- }
- }
- }
-
- if (options)
- {
- pi->options = options;
- KdParsePointerOptions(pi);
- }
-
- return pi;
-}
-
-
-void
-KdInitInput (void)
-{
- KdPointerInfo *pi;
- KdKeyboardInfo *ki;
- struct KdConfigDevice *dev;
-
- kdInputEnabled = TRUE;
-
- for (dev = kdConfigPointers; dev; dev = dev->next) {
- pi = KdParsePointer(dev->line);
- if (!pi)
- ErrorF("Failed to parse pointer\n");
- if (KdAddPointer(pi) != Success)
- ErrorF("Failed to add pointer!\n");
- }
- for (dev = kdConfigKeyboards; dev; dev = dev->next) {
- ki = KdParseKeyboard(dev->line);
- if (!ki)
- ErrorF("Failed to parse keyboard\n");
- if (KdAddKeyboard(ki) != Success)
- ErrorF("Failed to add keyboard!\n");
- }
-
- mieqInit();
-}
-
-/*
- * Middle button emulation state machine
- *
- * Possible transitions:
- * Button 1 press v1
- * Button 1 release ^1
- * Button 2 press v2
- * Button 2 release ^2
- * Button 3 press v3
- * Button 3 release ^3
- * Button other press vo
- * Button other release ^o
- * Mouse motion <>
- * Keyboard event k
- * timeout ...
- * outside box <->
- *
- * States:
- * start
- * button_1_pend
- * button_1_down
- * button_2_down
- * button_3_pend
- * button_3_down
- * synthetic_2_down_13
- * synthetic_2_down_3
- * synthetic_2_down_1
- *
- * Transition diagram
- *
- * start
- * v1 -> (hold) (settimeout) button_1_pend
- * ^1 -> (deliver) start
- * v2 -> (deliver) button_2_down
- * ^2 -> (deliever) start
- * v3 -> (hold) (settimeout) button_3_pend
- * ^3 -> (deliver) start
- * vo -> (deliver) start
- * ^o -> (deliver) start
- * <> -> (deliver) start
- * k -> (deliver) start
- *
- * button_1_pend (button 1 is down, timeout pending)
- * ^1 -> (release) (deliver) start
- * v2 -> (release) (deliver) button_1_down
- * ^2 -> (release) (deliver) button_1_down
- * v3 -> (cleartimeout) (generate v2) synthetic_2_down_13
- * ^3 -> (release) (deliver) button_1_down
- * vo -> (release) (deliver) button_1_down
- * ^o -> (release) (deliver) button_1_down
- * <-> -> (release) (deliver) button_1_down
- * <> -> (deliver) button_1_pend
- * k -> (release) (deliver) button_1_down
- * ... -> (release) button_1_down
- *
- * button_1_down (button 1 is down)
- * ^1 -> (deliver) start
- * v2 -> (deliver) button_1_down
- * ^2 -> (deliver) button_1_down
- * v3 -> (deliver) button_1_down
- * ^3 -> (deliver) button_1_down
- * vo -> (deliver) button_1_down
- * ^o -> (deliver) button_1_down
- * <> -> (deliver) button_1_down
- * k -> (deliver) button_1_down
- *
- * button_2_down (button 2 is down)
- * v1 -> (deliver) button_2_down
- * ^1 -> (deliver) button_2_down
- * ^2 -> (deliver) start
- * v3 -> (deliver) button_2_down
- * ^3 -> (deliver) button_2_down
- * vo -> (deliver) button_2_down
- * ^o -> (deliver) button_2_down
- * <> -> (deliver) button_2_down
- * k -> (deliver) button_2_down
- *
- * button_3_pend (button 3 is down, timeout pending)
- * v1 -> (generate v2) synthetic_2_down
- * ^1 -> (release) (deliver) button_3_down
- * v2 -> (release) (deliver) button_3_down
- * ^2 -> (release) (deliver) button_3_down
- * ^3 -> (release) (deliver) start
- * vo -> (release) (deliver) button_3_down
- * ^o -> (release) (deliver) button_3_down
- * <-> -> (release) (deliver) button_3_down
- * <> -> (deliver) button_3_pend
- * k -> (release) (deliver) button_3_down
- * ... -> (release) button_3_down
- *
- * button_3_down (button 3 is down)
- * v1 -> (deliver) button_3_down
- * ^1 -> (deliver) button_3_down
- * v2 -> (deliver) button_3_down
- * ^2 -> (deliver) button_3_down
- * ^3 -> (deliver) start
- * vo -> (deliver) button_3_down
- * ^o -> (deliver) button_3_down
- * <> -> (deliver) button_3_down
- * k -> (deliver) button_3_down
- *
- * synthetic_2_down_13 (button 1 and 3 are down)
- * ^1 -> (generate ^2) synthetic_2_down_3
- * v2 -> synthetic_2_down_13
- * ^2 -> synthetic_2_down_13
- * ^3 -> (generate ^2) synthetic_2_down_1
- * vo -> (deliver) synthetic_2_down_13
- * ^o -> (deliver) synthetic_2_down_13
- * <> -> (deliver) synthetic_2_down_13
- * k -> (deliver) synthetic_2_down_13
- *
- * synthetic_2_down_3 (button 3 is down)
- * v1 -> (deliver) synthetic_2_down_3
- * ^1 -> (deliver) synthetic_2_down_3
- * v2 -> synthetic_2_down_3
- * ^2 -> synthetic_2_down_3
- * ^3 -> start
- * vo -> (deliver) synthetic_2_down_3
- * ^o -> (deliver) synthetic_2_down_3
- * <> -> (deliver) synthetic_2_down_3
- * k -> (deliver) synthetic_2_down_3
- *
- * synthetic_2_down_1 (button 1 is down)
- * ^1 -> start
- * v2 -> synthetic_2_down_1
- * ^2 -> synthetic_2_down_1
- * v3 -> (deliver) synthetic_2_down_1
- * ^3 -> (deliver) synthetic_2_down_1
- * vo -> (deliver) synthetic_2_down_1
- * ^o -> (deliver) synthetic_2_down_1
- * <> -> (deliver) synthetic_2_down_1
- * k -> (deliver) synthetic_2_down_1
- */
-
-typedef enum _inputClass {
- down_1, up_1,
- down_2, up_2,
- down_3, up_3,
- down_o, up_o,
- motion, outside_box,
- keyboard, timeout,
- num_input_class
-} KdInputClass;
-
-typedef enum _inputAction {
- noop,
- hold,
- setto,
- deliver,
- release,
- clearto,
- gen_down_2,
- gen_up_2
-} KdInputAction;
-
-#define MAX_ACTIONS 2
-
-typedef struct _inputTransition {
- KdInputAction actions[MAX_ACTIONS];
- KdPointerState nextState;
-} KdInputTransition;
-
-static const
-KdInputTransition kdInputMachine[num_input_states][num_input_class] = {
- /* start */
- {
- { { hold, setto }, button_1_pend }, /* v1 */
- { { deliver, noop }, start }, /* ^1 */
- { { deliver, noop }, button_2_down }, /* v2 */
- { { deliver, noop }, start }, /* ^2 */
- { { hold, setto }, button_3_pend }, /* v3 */
- { { deliver, noop }, start }, /* ^3 */
- { { deliver, noop }, start }, /* vo */
- { { deliver, noop }, start }, /* ^o */
- { { deliver, noop }, start }, /* <> */
- { { deliver, noop }, start }, /* <-> */
- { { noop, noop }, start }, /* k */
- { { noop, noop }, start }, /* ... */
- },
- /* button_1_pend */
- {
- { { noop, noop }, button_1_pend }, /* v1 */
- { { release, deliver }, start }, /* ^1 */
- { { release, deliver }, button_1_down }, /* v2 */
- { { release, deliver }, button_1_down }, /* ^2 */
- { { clearto, gen_down_2 }, synth_2_down_13 }, /* v3 */
- { { release, deliver }, button_1_down }, /* ^3 */
- { { release, deliver }, button_1_down }, /* vo */
- { { release, deliver }, button_1_down }, /* ^o */
- { { deliver, noop }, button_1_pend }, /* <> */
- { { release, deliver }, button_1_down }, /* <-> */
- { { noop, noop }, button_1_down }, /* k */
- { { release, noop }, button_1_down }, /* ... */
- },
- /* button_1_down */
- {
- { { noop, noop }, button_1_down }, /* v1 */
- { { deliver, noop }, start }, /* ^1 */
- { { deliver, noop }, button_1_down }, /* v2 */
- { { deliver, noop }, button_1_down }, /* ^2 */
- { { deliver, noop }, button_1_down }, /* v3 */
- { { deliver, noop }, button_1_down }, /* ^3 */
- { { deliver, noop }, button_1_down }, /* vo */
- { { deliver, noop }, button_1_down }, /* ^o */
- { { deliver, noop }, button_1_down }, /* <> */
- { { deliver, noop }, button_1_down }, /* <-> */
- { { noop, noop }, button_1_down }, /* k */
- { { noop, noop }, button_1_down }, /* ... */
- },
- /* button_2_down */
- {
- { { deliver, noop }, button_2_down }, /* v1 */
- { { deliver, noop }, button_2_down }, /* ^1 */
- { { noop, noop }, button_2_down }, /* v2 */
- { { deliver, noop }, start }, /* ^2 */
- { { deliver, noop }, button_2_down }, /* v3 */
- { { deliver, noop }, button_2_down }, /* ^3 */
- { { deliver, noop }, button_2_down }, /* vo */
- { { deliver, noop }, button_2_down }, /* ^o */
- { { deliver, noop }, button_2_down }, /* <> */
- { { deliver, noop }, button_2_down }, /* <-> */
- { { noop, noop }, button_2_down }, /* k */
- { { noop, noop }, button_2_down }, /* ... */
- },
- /* button_3_pend */
- {
- { { clearto, gen_down_2 }, synth_2_down_13 }, /* v1 */
- { { release, deliver }, button_3_down }, /* ^1 */
- { { release, deliver }, button_3_down }, /* v2 */
- { { release, deliver }, button_3_down }, /* ^2 */
- { { release, deliver }, button_3_down }, /* v3 */
- { { release, deliver }, start }, /* ^3 */
- { { release, deliver }, button_3_down }, /* vo */
- { { release, deliver }, button_3_down }, /* ^o */
- { { deliver, noop }, button_3_pend }, /* <> */
- { { release, deliver }, button_3_down }, /* <-> */
- { { release, noop }, button_3_down }, /* k */
- { { release, noop }, button_3_down }, /* ... */
- },
- /* button_3_down */
- {
- { { deliver, noop }, button_3_down }, /* v1 */
- { { deliver, noop }, button_3_down }, /* ^1 */
- { { deliver, noop }, button_3_down }, /* v2 */
- { { deliver, noop }, button_3_down }, /* ^2 */
- { { noop, noop }, button_3_down }, /* v3 */
- { { deliver, noop }, start }, /* ^3 */
- { { deliver, noop }, button_3_down }, /* vo */
- { { deliver, noop }, button_3_down }, /* ^o */
- { { deliver, noop }, button_3_down }, /* <> */
- { { deliver, noop }, button_3_down }, /* <-> */
- { { noop, noop }, button_3_down }, /* k */
- { { noop, noop }, button_3_down }, /* ... */
- },
- /* synthetic_2_down_13 */
- {
- { { noop, noop }, synth_2_down_13 }, /* v1 */
- { { gen_up_2, noop }, synth_2_down_3 }, /* ^1 */
- { { noop, noop }, synth_2_down_13 }, /* v2 */
- { { noop, noop }, synth_2_down_13 }, /* ^2 */
- { { noop, noop }, synth_2_down_13 }, /* v3 */
- { { gen_up_2, noop }, synth_2_down_1 }, /* ^3 */
- { { deliver, noop }, synth_2_down_13 }, /* vo */
- { { deliver, noop }, synth_2_down_13 }, /* ^o */
- { { deliver, noop }, synth_2_down_13 }, /* <> */
- { { deliver, noop }, synth_2_down_13 }, /* <-> */
- { { noop, noop }, synth_2_down_13 }, /* k */
- { { noop, noop }, synth_2_down_13 }, /* ... */
- },
- /* synthetic_2_down_3 */
- {
- { { deliver, noop }, synth_2_down_3 }, /* v1 */
- { { deliver, noop }, synth_2_down_3 }, /* ^1 */
- { { deliver, noop }, synth_2_down_3 }, /* v2 */
- { { deliver, noop }, synth_2_down_3 }, /* ^2 */
- { { noop, noop }, synth_2_down_3 }, /* v3 */
- { { noop, noop }, start }, /* ^3 */
- { { deliver, noop }, synth_2_down_3 }, /* vo */
- { { deliver, noop }, synth_2_down_3 }, /* ^o */
- { { deliver, noop }, synth_2_down_3 }, /* <> */
- { { deliver, noop }, synth_2_down_3 }, /* <-> */
- { { noop, noop }, synth_2_down_3 }, /* k */
- { { noop, noop }, synth_2_down_3 }, /* ... */
- },
- /* synthetic_2_down_1 */
- {
- { { noop, noop }, synth_2_down_1 }, /* v1 */
- { { noop, noop }, start }, /* ^1 */
- { { deliver, noop }, synth_2_down_1 }, /* v2 */
- { { deliver, noop }, synth_2_down_1 }, /* ^2 */
- { { deliver, noop }, synth_2_down_1 }, /* v3 */
- { { deliver, noop }, synth_2_down_1 }, /* ^3 */
- { { deliver, noop }, synth_2_down_1 }, /* vo */
- { { deliver, noop }, synth_2_down_1 }, /* ^o */
- { { deliver, noop }, synth_2_down_1 }, /* <> */
- { { deliver, noop }, synth_2_down_1 }, /* <-> */
- { { noop, noop }, synth_2_down_1 }, /* k */
- { { noop, noop }, synth_2_down_1 }, /* ... */
- },
-};
-
-#define EMULATION_WINDOW 10
-#define EMULATION_TIMEOUT 100
-
-static int
-KdInsideEmulationWindow (KdPointerInfo *pi, int x, int y, int z)
-{
- pi->emulationDx = pi->heldEvent.x - x;
- pi->emulationDy = pi->heldEvent.y - y;
-
- return (abs (pi->emulationDx) < EMULATION_WINDOW &&
- abs (pi->emulationDy) < EMULATION_WINDOW);
-}
-
-static KdInputClass
-KdClassifyInput (KdPointerInfo *pi, int type, int x, int y, int z, int b)
-{
- switch (type) {
- case ButtonPress:
- switch (b) {
- case 1: return down_1;
- case 2: return down_2;
- case 3: return down_3;
- default: return down_o;
- }
- break;
- case ButtonRelease:
- switch (b) {
- case 1: return up_1;
- case 2: return up_2;
- case 3: return up_3;
- default: return up_o;
- }
- break;
- case MotionNotify:
- if (pi->eventHeld && !KdInsideEmulationWindow(pi, x, y, z))
- return outside_box;
- else
- return motion;
- default:
- return keyboard;
- }
- return keyboard;
-}
-
-#ifdef DEBUG
-char *kdStateNames[] = {
- "start",
- "button_1_pend",
- "button_1_down",
- "button_2_down",
- "button_3_pend",
- "button_3_down",
- "synth_2_down_13",
- "synth_2_down_3",
- "synthetic_2_down_1",
- "num_input_states"
-};
-
-char *kdClassNames[] = {
- "down_1", "up_1",
- "down_2", "up_2",
- "down_3", "up_3",
- "motion", "ouside_box",
- "keyboard", "timeout",
- "num_input_class"
-};
-
-char *kdActionNames[] = {
- "noop",
- "hold",
- "setto",
- "deliver",
- "release",
- "clearto",
- "gen_down_2",
- "gen_up_2",
-};
-#endif /* DEBUG */
-
-static void
-KdQueueEvent (DeviceIntPtr pDev, InternalEvent *ev)
-{
- KdAssertSigioBlocked ("KdQueueEvent");
- mieqEnqueue (pDev, ev);
-}
-
-/* We return true if we're stealing the event. */
-static Bool
-KdRunMouseMachine (KdPointerInfo *pi, KdInputClass c, int type, int x, int y,
- int z, int b, int absrel)
-{
- const KdInputTransition *t;
- int a;
-
- c = KdClassifyInput(pi, type, x, y, z, b);
- t = &kdInputMachine[pi->mouseState][c];
- for (a = 0; a < MAX_ACTIONS; a++)
- {
- switch (t->actions[a]) {
- case noop:
- break;
- case hold:
- pi->eventHeld = TRUE;
- pi->emulationDx = 0;
- pi->emulationDy = 0;
- pi->heldEvent.type = type;
- pi->heldEvent.x = x;
- pi->heldEvent.y = y;
- pi->heldEvent.z = z;
- pi->heldEvent.flags = b;
- pi->heldEvent.absrel = absrel;
- return TRUE;
- break;
- case setto:
- pi->emulationTimeout = GetTimeInMillis () + EMULATION_TIMEOUT;
- pi->timeoutPending = TRUE;
- break;
- case deliver:
- _KdEnqueuePointerEvent (pi, pi->heldEvent.type, pi->heldEvent.x,
- pi->heldEvent.y, pi->heldEvent.z,
- pi->heldEvent.flags, pi->heldEvent.absrel,
- TRUE);
- break;
- case release:
- pi->eventHeld = FALSE;
- pi->timeoutPending = FALSE;
- _KdEnqueuePointerEvent (pi, pi->heldEvent.type, pi->heldEvent.x,
- pi->heldEvent.y, pi->heldEvent.z,
- pi->heldEvent.flags, pi->heldEvent.absrel,
- TRUE);
- return TRUE;
- break;
- case clearto:
- pi->timeoutPending = FALSE;
- break;
- case gen_down_2:
- _KdEnqueuePointerEvent (pi, ButtonPress, x, y, z, 2, absrel,
- TRUE);
- pi->eventHeld = FALSE;
- return TRUE;
- break;
- case gen_up_2:
- _KdEnqueuePointerEvent (pi, ButtonRelease, x, y, z, 2, absrel,
- TRUE);
- return TRUE;
- break;
- }
- }
- pi->mouseState = t->nextState;
- return FALSE;
-}
-
-static int
-KdHandlePointerEvent (KdPointerInfo *pi, int type, int x, int y, int z, int b,
- int absrel)
-{
- if (pi->emulateMiddleButton)
- return KdRunMouseMachine (pi, KdClassifyInput(pi, type, x, y, z, b),
- type, x, y, z, b, absrel);
- return FALSE;
-}
-
-static void
-KdReceiveTimeout (KdPointerInfo *pi)
-{
- KdRunMouseMachine (pi, timeout, 0, 0, 0, 0, 0, 0);
-}
-
-/*
- * kdCheckTermination
- *
- * This function checks for the key sequence that terminates the server. When
- * detected, it sets the dispatchException flag and returns. The key sequence
- * is:
- * Control-Alt
- * It's assumed that the server will be waken up by the caller when this
- * function returns.
- */
-
-extern int nClients;
-
-void
-KdReleaseAllKeys (void)
-{
-#if 0
- int key, nEvents, i;
- KdKeyboardInfo *ki;
-
- KdBlockSigio ();
-
- for (ki = kdKeyboards; ki; ki = ki->next) {
- for (key = ki->keySyms.minKeyCode; key < ki->keySyms.maxKeyCode;
- key++) {
- if (key_is_down(ki->dixdev, key, KEY_POSTED | KEY_PROCESSED)) {
- KdHandleKeyboardEvent(ki, KeyRelease, key);
- GetEventList(&kdEvents);
- nEvents = GetKeyboardEvents(kdEvents, ki->dixdev, KeyRelease, key);
- for (i = 0; i < nEvents; i++)
- KdQueueEvent (ki->dixdev, (kdEvents + i)->event);
- }
- }
- }
-
- KdUnblockSigio ();
-#endif
-}
-
-static void
-KdCheckLock (void)
-{
- KeyClassPtr keyc = NULL;
- Bool isSet = FALSE, shouldBeSet = FALSE;
- KdKeyboardInfo *tmp = NULL;
-
- for (tmp = kdKeyboards; tmp; tmp = tmp->next) {
- if (tmp->LockLed && tmp->dixdev && tmp->dixdev->key) {
- keyc = tmp->dixdev->key;
- isSet = (tmp->leds & (1 << (tmp->LockLed-1))) != 0;
- /* FIXME: Just use XKB indicators! */
- shouldBeSet = !!(XkbStateFieldFromRec(&keyc->xkbInfo->state) & LockMask);
- if (isSet != shouldBeSet)
- KdSetLed (tmp, tmp->LockLed, shouldBeSet);
- }
- }
-}
-
-void
-KdEnqueueKeyboardEvent(KdKeyboardInfo *ki,
- unsigned char scan_code,
- unsigned char is_up)
-{
- unsigned char key_code;
- KeyClassPtr keyc = NULL;
- KeybdCtrl *ctrl = NULL;
- int type, nEvents, i;
-
- if (!ki || !ki->dixdev || !ki->dixdev->kbdfeed || !ki->dixdev->key)
- return;
-
- keyc = ki->dixdev->key;
- ctrl = &ki->dixdev->kbdfeed->ctrl;
-
- if (scan_code >= ki->minScanCode && scan_code <= ki->maxScanCode)
- {
- key_code = scan_code + KD_MIN_KEYCODE - ki->minScanCode;
-
- /*
- * Set up this event -- the type may be modified below
- */
- if (is_up)
- type = KeyRelease;
- else
- type = KeyPress;
-
- GetEventList(&kdEvents);
-
- nEvents = GetKeyboardEvents(kdEvents, ki->dixdev, type, key_code);
- for (i = 0; i < nEvents; i++)
- KdQueueEvent(ki->dixdev, (InternalEvent *)((kdEvents + i)->event));
- }
- else {
- ErrorF("driver %s wanted to post scancode %d outside of [%d, %d]!\n",
- ki->name, scan_code, ki->minScanCode, ki->maxScanCode);
- }
-}
-
-/*
- * kdEnqueuePointerEvent
- *
- * This function converts hardware mouse event information into X event
- * information. A mouse movement event is passed off to MI to generate
- * a MotionNotify event, if appropriate. Button events are created and
- * passed off to MI for enqueueing.
- */
-
-/* FIXME do something a little more clever to deal with multiple axes here */
-void
-KdEnqueuePointerEvent(KdPointerInfo *pi, unsigned long flags, int rx, int ry,
- int rz)
-{
- CARD32 ms;
- unsigned char buttons;
- int x, y, z;
- int (*matrix)[3] = kdPointerMatrix.matrix;
- unsigned long button;
- int n;
- int dixflags = 0;
-
- if (!pi)
- return;
-
- ms = GetTimeInMillis();
-
- /* we don't need to transform z, so we don't. */
- if (flags & KD_MOUSE_DELTA) {
- if (pi->transformCoordinates) {
- x = matrix[0][0] * rx + matrix[0][1] * ry;
- y = matrix[1][0] * rx + matrix[1][1] * ry;
- }
- else {
- x = rx;
- y = ry;
- }
- }
- else {
- if (pi->transformCoordinates) {
- x = matrix[0][0] * rx + matrix[0][1] * ry + matrix[0][2];
- y = matrix[1][0] * rx + matrix[1][1] * ry + matrix[1][2];
- }
- else {
- x = rx;
- y = ry;
- }
- }
- z = rz;
-
- if (flags & KD_MOUSE_DELTA)
- {
- if (x || y || z)
- {
- dixflags = POINTER_RELATIVE | POINTER_ACCELERATE;
- _KdEnqueuePointerEvent(pi, MotionNotify, x, y, z, 0, dixflags, FALSE);
- }
- } else
- {
- dixflags = POINTER_ABSOLUTE;
- if (x != pi->dixdev->last.valuators[0] ||
- y != pi->dixdev->last.valuators[1])
- _KdEnqueuePointerEvent(pi, MotionNotify, x, y, z, 0, dixflags, FALSE);
- }
-
- buttons = flags;
-
- for (button = KD_BUTTON_1, n = 1; n <= pi->nButtons;
- button <<= 1, n++) {
- if (((pi->buttonState & button) ^ (buttons & button)) &&
- !(buttons & button)) {
- _KdEnqueuePointerEvent(pi, ButtonRelease, x, y, z, n,
- dixflags, FALSE);
- }
- }
- for (button = KD_BUTTON_1, n = 1; n <= pi->nButtons;
- button <<= 1, n++) {
- if (((pi->buttonState & button) ^ (buttons & button)) &&
- (buttons & button)) {
- _KdEnqueuePointerEvent(pi, ButtonPress, x, y, z, n,
- dixflags, FALSE);
- }
- }
-
- pi->buttonState = buttons;
-}
-
-void
-_KdEnqueuePointerEvent (KdPointerInfo *pi, int type, int x, int y, int z,
- int b, int absrel, Bool force)
-{
- int nEvents = 0, i = 0;
- int valuators[3] = { x, y, z };
- ValuatorMask mask;
-
- /* TRUE from KdHandlePointerEvent, means 'we swallowed the event'. */
- if (!force && KdHandlePointerEvent(pi, type, x, y, z, b, absrel))
- return;
-
- valuator_mask_set_range(&mask, 0, 3, valuators);
-
- GetEventList(&kdEvents);
- nEvents = GetPointerEvents(kdEvents, pi->dixdev, type, b, absrel, &mask);
- for (i = 0; i < nEvents; i++)
- KdQueueEvent(pi->dixdev, (InternalEvent *)((kdEvents + i)->event));
-}
-
-void
-KdBlockHandler (int screen,
- pointer blockData,
- pointer timeout,
- pointer readmask)
-{
- KdPointerInfo *pi;
- int myTimeout=0;
-
- for (pi = kdPointers; pi; pi = pi->next)
- {
- if (pi->timeoutPending)
- {
- int ms;
-
- ms = pi->emulationTimeout - GetTimeInMillis ();
- if (ms < 1)
- ms = 1;
- if(ms<myTimeout || myTimeout==0)
- myTimeout=ms;
- }
- }
- /* if we need to poll for events, do that */
- if(kdOsFuncs->pollEvents)
- {
- (*kdOsFuncs->pollEvents)();
- myTimeout=20;
- }
- if(myTimeout>0)
- AdjustWaitForDelay (timeout, myTimeout);
-}
-
-void
-KdWakeupHandler (int screen,
- pointer data,
- unsigned long lresult,
- pointer readmask)
-{
- int result = (int) lresult;
- fd_set *pReadmask = (fd_set *) readmask;
- int i;
- KdPointerInfo *pi;
-
- if (kdInputEnabled && result > 0)
- {
- for (i = 0; i < kdNumInputFds; i++)
- if (FD_ISSET (kdInputFds[i].fd, pReadmask))
- {
- KdBlockSigio ();
- (*kdInputFds[i].read) (kdInputFds[i].fd, kdInputFds[i].closure);
- KdUnblockSigio ();
- }
- }
- for (pi = kdPointers; pi; pi = pi->next)
- {
- if (pi->timeoutPending)
- {
- if ((long) (GetTimeInMillis () - pi->emulationTimeout) >= 0)
- {
- pi->timeoutPending = FALSE;
- KdBlockSigio ();
- KdReceiveTimeout (pi);
- KdUnblockSigio ();
- }
- }
- }
- if (kdSwitchPending)
- KdProcessSwitch ();
-}
-
-#define KdScreenOrigin(pScreen) (&(KdGetScreenPriv(pScreen)->screen->origin))
-
-static Bool
-KdCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y)
-{
- ScreenPtr pScreen = *ppScreen;
- ScreenPtr pNewScreen;
- int n;
- int dx, dy;
- int best_x, best_y;
- int n_best_x, n_best_y;
- CARD32 ms;
-
- if (kdDisableZaphod || screenInfo.numScreens <= 1)
- return FALSE;
-
- if (0 <= *x && *x < pScreen->width && 0 <= *y && *y < pScreen->height)
- return FALSE;
-
- ms = GetTimeInMillis ();
- if (kdOffScreen && (int) (ms - kdOffScreenTime) < 1000)
- return FALSE;
- kdOffScreen = TRUE;
- kdOffScreenTime = ms;
- n_best_x = -1;
- best_x = 32767;
- n_best_y = -1;
- best_y = 32767;
- for (n = 0; n < screenInfo.numScreens; n++)
- {
- pNewScreen = screenInfo.screens[n];
- if (pNewScreen == pScreen)
- continue;
- dx = KdScreenOrigin(pNewScreen)->x - KdScreenOrigin(pScreen)->x;
- dy = KdScreenOrigin(pNewScreen)->y - KdScreenOrigin(pScreen)->y;
- if (*x < 0)
- {
- if (dx <= 0 && -dx < best_x)
- {
- best_x = -dx;
- n_best_x = n;
- }
- }
- else if (*x >= pScreen->width)
- {
- if (dx >= 0 && dx < best_x)
- {
- best_x = dx;
- n_best_x = n;
- }
- }
- if (*y < 0)
- {
- if (dy <= 0 && -dy < best_y)
- {
- best_y = -dy;
- n_best_y = n;
- }
- }
- else if (*y >= pScreen->height)
- {
- if (dy >= 0 && dy < best_y)
- {
- best_y = dy;
- n_best_y = n;
- }
- }
- }
- if (best_y < best_x)
- n_best_x = n_best_y;
- if (n_best_x == -1)
- return FALSE;
- pNewScreen = screenInfo.screens[n_best_x];
-
- if (*x < 0)
- *x += pNewScreen->width;
- if (*y < 0)
- *y += pNewScreen->height;
-
- if (*x >= pScreen->width)
- *x -= pScreen->width;
- if (*y >= pScreen->height)
- *y -= pScreen->height;
-
- *ppScreen = pNewScreen;
- return TRUE;
-}
-
-static void
-KdCrossScreen(ScreenPtr pScreen, Bool entering)
-{
-#ifndef XIPAQ
- if (entering)
- KdEnableScreen (pScreen);
- else
- KdDisableScreen (pScreen);
-#endif
-}
-
-int KdCurScreen; /* current event screen */
-
-static void
-KdWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
-{
- KdBlockSigio ();
- KdCurScreen = pScreen->myNum;
- miPointerWarpCursor(pDev, pScreen, x, y);
- KdUnblockSigio ();
-}
-
-miPointerScreenFuncRec kdPointerScreenFuncs =
-{
- KdCursorOffScreen,
- KdCrossScreen,
- KdWarpCursor
-};
-
-void
-ProcessInputEvents (void)
-{
- mieqProcessInputEvents();
- miPointerUpdateSprite(inputInfo.pointer);
- if (kdSwitchPending)
- KdProcessSwitch ();
- KdCheckLock ();
-}
-
-/* At the moment, absolute/relative is up to the client. */
-int
-SetDeviceMode(register ClientPtr client, DeviceIntPtr pDev, int mode)
-{
- return BadMatch;
-}
-
-int
-SetDeviceValuators(register ClientPtr client, DeviceIntPtr pDev,
- int *valuators, int first_valuator, int num_valuators)
-{
- return BadMatch;
-}
-
-int
-ChangeDeviceControl(register ClientPtr client, DeviceIntPtr pDev,
- xDeviceCtl *control)
-{
- switch (control->control) {
- case DEVICE_RESOLUTION:
- /* FIXME do something more intelligent here */
- return BadMatch;
-
- case DEVICE_ABS_CALIB:
- case DEVICE_ABS_AREA:
- return Success;
-
- case DEVICE_CORE:
- return BadMatch;
- case DEVICE_ENABLE:
- return Success;
-
- default:
- return BadMatch;
- }
-
- /* NOTREACHED */
- return BadImplementation;
-}
-
-int
-NewInputDeviceRequest(InputOption *options, InputAttributes *attrs,
- DeviceIntPtr *pdev)
-{
- InputOption *option = NULL;
- KdPointerInfo *pi = NULL;
- KdKeyboardInfo *ki = NULL;
-
- for (option = options; option; option = option->next) {
- if (strcmp(option->key, "type") == 0) {
- if (strcmp(option->value, "pointer") == 0) {
- pi = KdNewPointer();
- if (!pi)
- return BadAlloc;
- }
- else if (strcmp(option->value, "keyboard") == 0) {
- ki = KdNewKeyboard();
- if (!ki)
- return BadAlloc;
- }
- else {
- ErrorF("unrecognised device type!\n");
- return BadValue;
- }
- }
-#ifdef CONFIG_HAL
- else if (strcmp(option->key, "_source") == 0 &&
- strcmp(option->value, "server/hal") == 0)
- {
- ErrorF("Ignoring device from HAL.\n");
- return BadValue;
- }
-#endif
-#ifdef CONFIG_UDEV
- else if (strcmp(option->key, "_source") == 0 &&
- strcmp(option->value, "server/udev") == 0)
- {
- ErrorF("Ignoring device from udev.\n");
- return BadValue;
- }
-#endif
- }
-
- if (!ki && !pi) {
- ErrorF("unrecognised device identifier!\n");
- return BadValue;
- }
-
- /* FIXME: change this code below to use KdParseKbdOptions and
- * KdParsePointerOptions */
- for (option = options; option; option = option->next) {
- if (strcmp(option->key, "device") == 0) {
- if (pi && option->value)
- pi->path = strdup(option->value);
- else if (ki && option->value)
- ki->path = strdup(option->value);
- }
- else if (strcmp(option->key, "driver") == 0) {
- if (pi) {
- pi->driver = KdFindPointerDriver(option->value);
- if (!pi->driver) {
- ErrorF("couldn't find driver!\n");
- KdFreePointer(pi);
- return BadValue;
- }
- pi->options = options;
- }
- else if (ki) {
- ki->driver = KdFindKeyboardDriver(option->value);
- if (!ki->driver) {
- ErrorF("couldn't find driver!\n");
- KdFreeKeyboard(ki);
- return BadValue;
- }
- ki->options = options;
- }
- }
- }
-
- if (pi) {
- if (KdAddPointer(pi) != Success ||
- ActivateDevice(pi->dixdev, TRUE) != Success ||
- EnableDevice(pi->dixdev, TRUE) != TRUE) {
- ErrorF("couldn't add or enable pointer\n");
- return BadImplementation;
- }
- }
- else if (ki) {
- if (KdAddKeyboard(ki) != Success ||
- ActivateDevice(ki->dixdev, TRUE) != Success ||
- EnableDevice(ki->dixdev, TRUE) != TRUE) {
- ErrorF("couldn't add or enable keyboard\n");
- return BadImplementation;
- }
- }
-
- if (pi) {
- *pdev = pi->dixdev;
- } else if(ki) {
- *pdev = ki->dixdev;
- }
-
- return Success;
-}
-
-void
-DeleteInputDeviceRequest(DeviceIntPtr pDev)
-{
- RemoveDevice(pDev, TRUE);
-}
+/* + * Copyright © 1999 Keith Packard + * Copyright © 2006 Nokia Corporation + * + * 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 authors not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The authors make no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE AUTHORS 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 <kdrive-config.h> +#endif +#include "kdrive.h" +#include "inputstr.h" + +#define XK_PUBLISHING +#include <X11/keysym.h> +#if HAVE_X11_XF86KEYSYM_H +#include <X11/XF86keysym.h> +#endif +#include <signal.h> +#include <stdio.h> +#ifdef sun +#include <sys/file.h> /* needed for FNONBLOCK & FASYNC */ +#endif + +#include "xkbsrv.h" + +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include "XIstubs.h" /* even though we don't use stubs. cute, no? */ +#include "exevents.h" +#include "extinit.h" +#include "exglobals.h" +#include "eventstr.h" +#include "xserver-properties.h" +#include "inpututils.h" + +#define AtomFromName(x) MakeAtom(x, strlen(x), 1) + +struct KdConfigDevice { + char *line; + struct KdConfigDevice *next; +}; + +/* kdKeyboards and kdPointers hold all the real devices. */ +static KdKeyboardInfo *kdKeyboards = NULL; +static KdPointerInfo *kdPointers = NULL; +static struct KdConfigDevice *kdConfigKeyboards = NULL; +static struct KdConfigDevice *kdConfigPointers = NULL; + +static KdKeyboardDriver *kdKeyboardDrivers = NULL; +static KdPointerDriver *kdPointerDrivers = NULL; + +static EventListPtr kdEvents = NULL; + +static Bool kdInputEnabled; +static Bool kdOffScreen; +static unsigned long kdOffScreenTime; +static KdPointerMatrix kdPointerMatrix = { + { { 1, 0, 0 }, + { 0, 1, 0 } } +}; + +void KdResetInputMachine (void); + +#define KD_MAX_INPUT_FDS 8 + +typedef struct _kdInputFd { + int fd; + void (*read) (int fd, void *closure); + int (*enable) (int fd, void *closure); + void (*disable) (int fd, void *closure); + void *closure; +} KdInputFd; + +static KdInputFd kdInputFds[KD_MAX_INPUT_FDS]; +static int kdNumInputFds; + +extern Bool kdRawPointerCoordinates; + +static void +KdSigio (int sig) +{ + int i; + + for (i = 0; i < kdNumInputFds; i++) + (*kdInputFds[i].read) (kdInputFds[i].fd, kdInputFds[i].closure); +} + +static void +KdBlockSigio (void) +{ + sigset_t set; + + sigemptyset (&set); + sigaddset (&set, SIGIO); + sigprocmask (SIG_BLOCK, &set, 0); +} + +static void +KdUnblockSigio (void) +{ + sigset_t set; + + sigemptyset (&set); + sigaddset (&set, SIGIO); + sigprocmask (SIG_UNBLOCK, &set, 0); +} + +#ifdef DEBUG_SIGIO + +void +KdAssertSigioBlocked (char *where) +{ + sigset_t set, old; + + sigemptyset (&set); + sigprocmask (SIG_BLOCK, &set, &old); + if (!sigismember (&old, SIGIO)) { + ErrorF ("SIGIO not blocked at %s\n", where); + KdBacktrace(0); + } +} + +#else + +#define KdAssertSigioBlocked(s) + +#endif + +static int kdnFds; + +#ifdef FNONBLOCK +#define NOBLOCK FNONBLOCK +#else +#define NOBLOCK FNDELAY +#endif + +void +KdResetInputMachine (void) +{ + KdPointerInfo *pi; + + for (pi = kdPointers; pi; pi = pi->next) { + pi->mouseState = start; + pi->eventHeld = FALSE; + } +} + +static void +KdNonBlockFd (int fd) +{ + int flags; + flags = fcntl (fd, F_GETFL); + flags |= FASYNC|NOBLOCK; + fcntl (fd, F_SETFL, flags); +} + +static void +KdAddFd (int fd) +{ + struct sigaction act; + sigset_t set; + + kdnFds++; + fcntl (fd, F_SETOWN, getpid()); + KdNonBlockFd (fd); + AddEnabledDevice (fd); + memset (&act, '\0', sizeof act); + act.sa_handler = KdSigio; + sigemptyset (&act.sa_mask); + sigaddset (&act.sa_mask, SIGIO); + sigaddset (&act.sa_mask, SIGALRM); + sigaddset (&act.sa_mask, SIGVTALRM); + sigaction (SIGIO, &act, 0); + sigemptyset (&set); + sigprocmask (SIG_SETMASK, &set, 0); +} + +static void +KdRemoveFd (int fd) +{ + struct sigaction act; + int flags; + + kdnFds--; + RemoveEnabledDevice (fd); + flags = fcntl (fd, F_GETFL); + flags &= ~(FASYNC|NOBLOCK); + fcntl (fd, F_SETFL, flags); + if (kdnFds == 0) + { + memset (&act, '\0', sizeof act); + act.sa_handler = SIG_IGN; + sigemptyset (&act.sa_mask); + sigaction (SIGIO, &act, 0); + } +} + +Bool +KdRegisterFd (int fd, void (*read) (int fd, void *closure), void *closure) +{ + if (kdNumInputFds == KD_MAX_INPUT_FDS) + return FALSE; + kdInputFds[kdNumInputFds].fd = fd; + kdInputFds[kdNumInputFds].read = read; + kdInputFds[kdNumInputFds].enable = 0; + kdInputFds[kdNumInputFds].disable = 0; + kdInputFds[kdNumInputFds].closure = closure; + kdNumInputFds++; + if (kdInputEnabled) + KdAddFd (fd); + return TRUE; +} + +void +KdUnregisterFd (void *closure, int fd, Bool do_close) +{ + int i, j; + + for (i = 0; i < kdNumInputFds; i++) { + if (kdInputFds[i].closure == closure && + (fd == -1 || kdInputFds[i].fd == fd)) { + if (kdInputEnabled) + KdRemoveFd (kdInputFds[i].fd); + if (do_close) + close (kdInputFds[i].fd); + kdNumInputFds--; + for (j = i; j < kdNumInputFds; j++) + kdInputFds[j] = kdInputFds[j+1]; + break; + } + } +} + +void +KdUnregisterFds (void *closure, Bool do_close) +{ + KdUnregisterFd(closure, -1, do_close); +} + +void +KdDisableInput (void) +{ + KdKeyboardInfo *ki; + KdPointerInfo *pi; + int found = 0, i = 0; + + KdBlockSigio(); + + for (ki = kdKeyboards; ki; ki = ki->next) { + if (ki->driver && ki->driver->Disable) + (*ki->driver->Disable) (ki); + } + + for (pi = kdPointers; pi; pi = pi->next) { + if (pi->driver && pi->driver->Disable) + (*pi->driver->Disable) (pi); + } + + if (kdNumInputFds) { + ErrorF("[KdDisableInput] Buggy drivers: still %d input fds left!", + kdNumInputFds); + i = 0; + while (i < kdNumInputFds) { + found = 0; + for (ki = kdKeyboards; ki; ki = ki->next) { + if (ki == kdInputFds[i].closure) { + ErrorF(" fd %d belongs to keybd driver %s\n", + kdInputFds[i].fd, + ki->driver && ki->driver->name ? + ki->driver->name : "(unnamed!)"); + found = 1; + break; + } + } + + if (found) { + i++; + continue; + } + + for (pi = kdPointers; pi; pi = pi->next) { + if (pi == kdInputFds[i].closure) { + ErrorF(" fd %d belongs to pointer driver %s\n", + kdInputFds[i].fd, + pi->driver && pi->driver->name ? + pi->driver->name : "(unnamed!)"); + break; + } + } + + if (found) { + i++; + continue; + } + + ErrorF(" fd %d not claimed by any active device!\n", + kdInputFds[i].fd); + KdUnregisterFd(kdInputFds[i].closure, kdInputFds[i].fd, TRUE); + } + } + + kdInputEnabled = FALSE; +} + +void +KdEnableInput (void) +{ + InternalEvent ev; + KdKeyboardInfo *ki; + KdPointerInfo *pi; + + kdInputEnabled = TRUE; + + for (ki = kdKeyboards; ki; ki = ki->next) { + if (ki->driver && ki->driver->Enable) + (*ki->driver->Enable) (ki); + } + + for (pi = kdPointers; pi; pi = pi->next) { + if (pi->driver && pi->driver->Enable) + (*pi->driver->Enable) (pi); + } + + /* reset screen saver */ + ev.any.time = GetTimeInMillis (); + NoticeEventTime (&ev); + + KdUnblockSigio (); +} + +static KdKeyboardDriver * +KdFindKeyboardDriver (char *name) +{ + KdKeyboardDriver *ret; + + /* ask a stupid question ... */ + if (!name) + return NULL; + + for (ret = kdKeyboardDrivers; ret; ret = ret->next) { + if (strcmp(ret->name, name) == 0) + return ret; + } + + return NULL; +} + +static KdPointerDriver * +KdFindPointerDriver (char *name) +{ + KdPointerDriver *ret; + + /* ask a stupid question ... */ + if (!name) + return NULL; + + for (ret = kdPointerDrivers; ret; ret = ret->next) { + if (strcmp(ret->name, name) == 0) + return ret; + } + + return NULL; +} + +static int +KdPointerProc(DeviceIntPtr pDevice, int onoff) +{ + DevicePtr pDev = (DevicePtr)pDevice; + KdPointerInfo *pi; + Atom xiclass; + Atom *btn_labels; + Atom *axes_labels; + + if (!pDev) + return BadImplementation; + + for (pi = kdPointers; pi; pi = pi->next) { + if (pi->dixdev && pi->dixdev->id == pDevice->id) + break; + } + + if (!pi || !pi->dixdev || pi->dixdev->id != pDevice->id) { + ErrorF("[KdPointerProc] Failed to find pointer for device %d!\n", + pDevice->id); + return BadImplementation; + } + + switch (onoff) + { + case DEVICE_INIT: +#ifdef DEBUG + ErrorF("initialising pointer %s ...\n", pi->name); +#endif + if (!pi->driver) { + if (!pi->driverPrivate) { + ErrorF("no driver specified for %s\n", pi->name); + return BadImplementation; + } + + pi->driver = KdFindPointerDriver(pi->driverPrivate); + if (!pi->driver) { + ErrorF("Couldn't find pointer driver %s\n", + pi->driverPrivate ? (char *) pi->driverPrivate : + "(unnamed)"); + return !Success; + } + free(pi->driverPrivate); + pi->driverPrivate = NULL; + } + + if (!pi->driver->Init) { + ErrorF("no init function\n"); + return BadImplementation; + } + + if ((*pi->driver->Init) (pi) != Success) { + return !Success; + } + + btn_labels = calloc(pi->nButtons, sizeof(Atom)); + if (!btn_labels) + return BadAlloc; + axes_labels = calloc(pi->nAxes, sizeof(Atom)); + if (!axes_labels) { + free(btn_labels); + return BadAlloc; + } + + switch(pi->nAxes) + { + default: + case 7: + btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT); + case 6: + btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT); + case 5: + btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN); + case 4: + btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP); + case 3: + btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); + case 2: + btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); + case 1: + btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); + case 0: + break; + } + + if (pi->nAxes >= 2) { + axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); + axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); + } + + InitPointerDeviceStruct(pDev, pi->map, pi->nButtons, btn_labels, + (PtrCtrlProcPtr)NoopDDA, + GetMotionHistorySize(), pi->nAxes, axes_labels); + + free(btn_labels); + free(axes_labels); + + if (pi->inputClass == KD_TOUCHSCREEN) { + xiclass = AtomFromName(XI_TOUCHSCREEN); + } + else { + xiclass = AtomFromName(XI_MOUSE); + } + + AssignTypeAndName(pi->dixdev, xiclass, + pi->name ? pi->name : "Generic KDrive Pointer"); + + return Success; + + case DEVICE_ON: + if (pDev->on == TRUE) + return Success; + + if (!pi->driver->Enable) { + ErrorF("no enable function\n"); + return BadImplementation; + } + + if ((*pi->driver->Enable) (pi) == Success) { + pDev->on = TRUE; + return Success; + } + else { + return BadImplementation; + } + + return Success; + + case DEVICE_OFF: + if (pDev->on == FALSE) { + return Success; + } + + if (!pi->driver->Disable) { + return BadImplementation; + } + else { + (*pi->driver->Disable) (pi); + pDev->on = FALSE; + return Success; + } + + return Success; + + case DEVICE_CLOSE: + if (pDev->on) { + if (!pi->driver->Disable) { + return BadImplementation; + } + (*pi->driver->Disable) (pi); + pDev->on = FALSE; + } + + if (!pi->driver->Fini) + return BadImplementation; + + (*pi->driver->Fini) (pi); + + KdRemovePointer(pi); + + return Success; + } + + /* NOTREACHED */ + return BadImplementation; +} + +Bool +LegalModifier(unsigned int key, DeviceIntPtr pDev) +{ + return TRUE; +} + +static void +KdBell (int volume, DeviceIntPtr pDev, pointer arg, int something) +{ + KeybdCtrl *ctrl = arg; + KdKeyboardInfo *ki = NULL; + + for (ki = kdKeyboards; ki; ki = ki->next) { + if (ki->dixdev && ki->dixdev->id == pDev->id) + break; + } + + if (!ki || !ki->dixdev || ki->dixdev->id != pDev->id || !ki->driver) + return; + + KdRingBell(ki, volume, ctrl->bell_pitch, ctrl->bell_duration); +} + +void +DDXRingBell(int volume, int pitch, int duration) +{ + KdKeyboardInfo *ki = NULL; + + if (kdOsFuncs->Bell) { + (*kdOsFuncs->Bell)(volume, pitch, duration); + } + else { + for (ki = kdKeyboards; ki; ki = ki->next) { + if (ki->dixdev->coreEvents) + KdRingBell(ki, volume, pitch, duration); + } + } +} + +void +KdRingBell(KdKeyboardInfo *ki, int volume, int pitch, int duration) +{ + if (!ki || !ki->driver || !ki->driver->Bell) + return; + + if (kdInputEnabled) + (*ki->driver->Bell) (ki, volume, pitch, duration); +} + + +static void +KdSetLeds (KdKeyboardInfo *ki, int leds) +{ + if (!ki || !ki->driver) + return; + + if (kdInputEnabled) { + if (ki->driver->Leds) + (*ki->driver->Leds) (ki, leds); + } +} + +void +KdSetLed (KdKeyboardInfo *ki, int led, Bool on) +{ + if (!ki || !ki->dixdev || !ki->dixdev->kbdfeed) + return; + + NoteLedState (ki->dixdev, led, on); + KdSetLeds (ki, ki->dixdev->kbdfeed->ctrl.leds); +} + +void +KdSetPointerMatrix (KdPointerMatrix *matrix) +{ + kdPointerMatrix = *matrix; +} + +void +KdComputePointerMatrix (KdPointerMatrix *m, Rotation randr, int width, + int height) +{ + int x_dir = 1, y_dir = 1; + int i, j; + int size[2]; + + size[0] = width; size[1] = height; + if (randr & RR_Reflect_X) + x_dir = -1; + if (randr & RR_Reflect_Y) + y_dir = -1; + switch (randr & (RR_Rotate_All)) { + case RR_Rotate_0: + m->matrix[0][0] = x_dir; m->matrix[0][1] = 0; + m->matrix[1][0] = 0; m->matrix[1][1] = y_dir; + break; + case RR_Rotate_90: + m->matrix[0][0] = 0; m->matrix[0][1] = -x_dir; + m->matrix[1][0] = y_dir; m->matrix[1][1] = 0; + break; + case RR_Rotate_180: + m->matrix[0][0] = -x_dir; m->matrix[0][1] = 0; + m->matrix[1][0] = 0; m->matrix[1][1] = -y_dir; + break; + case RR_Rotate_270: + m->matrix[0][0] = 0; m->matrix[0][1] = x_dir; + m->matrix[1][0] = -y_dir; m->matrix[1][1] = 0; + break; + } + for (i = 0; i < 2; i++) + { + m->matrix[i][2] = 0; + for (j = 0 ; j < 2; j++) + if (m->matrix[i][j] < 0) + m->matrix[i][2] = size[j] - 1; + } +} + +void +KdScreenToPointerCoords (int *x, int *y) +{ + int (*m)[3] = kdPointerMatrix.matrix; + int div = m[0][1] * m[1][0] - m[1][1] * m[0][0]; + int sx = *x; + int sy = *y; + + *x = (m[0][1] * sy - m[0][1] * m[1][2] + m[1][1] * m[0][2] - m[1][1] * sx) / div; + *y = (m[1][0] * sx + m[0][0] * m[1][2] - m[1][0] * m[0][2] - m[0][0] * sy) / div; +} + +static void +KdKbdCtrl (DeviceIntPtr pDevice, KeybdCtrl *ctrl) +{ + KdKeyboardInfo *ki; + + for (ki = kdKeyboards; ki; ki = ki->next) { + if (ki->dixdev && ki->dixdev->id == pDevice->id) + break; + } + + if (!ki || !ki->dixdev || ki->dixdev->id != pDevice->id || !ki->driver) + return; + + KdSetLeds(ki, ctrl->leds); + ki->bellPitch = ctrl->bell_pitch; + ki->bellDuration = ctrl->bell_duration; +} + +extern KeybdCtrl defaultKeyboardControl; + +static int +KdKeyboardProc(DeviceIntPtr pDevice, int onoff) +{ + Bool ret; + DevicePtr pDev = (DevicePtr)pDevice; + KdKeyboardInfo *ki; + Atom xiclass; + XkbRMLVOSet rmlvo; + + if (!pDev) + return BadImplementation; + + for (ki = kdKeyboards; ki; ki = ki->next) { + if (ki->dixdev && ki->dixdev->id == pDevice->id) + break; + } + + if (!ki || !ki->dixdev || ki->dixdev->id != pDevice->id) { + return BadImplementation; + } + + switch (onoff) + { + case DEVICE_INIT: +#ifdef DEBUG + ErrorF("initialising keyboard %s\n", ki->name); +#endif + if (!ki->driver) { + if (!ki->driverPrivate) { + ErrorF("no driver specified!\n"); + return BadImplementation; + } + + ki->driver = KdFindKeyboardDriver(ki->driverPrivate); + if (!ki->driver) { + ErrorF("Couldn't find keyboard driver %s\n", + ki->driverPrivate ? (char *) ki->driverPrivate : + "(unnamed)"); + return !Success; + } + free(ki->driverPrivate); + ki->driverPrivate = NULL; + } + + if (!ki->driver->Init) { + ErrorF("Keyboard %s: no init function\n", ki->name); + return BadImplementation; + } + + if ((*ki->driver->Init) (ki) != Success) { + return !Success; + } + + memset(&rmlvo, 0, sizeof(rmlvo)); + rmlvo.rules = ki->xkbRules; + rmlvo.model = ki->xkbModel; + rmlvo.layout = ki->xkbLayout; + rmlvo.variant = ki->xkbVariant; + rmlvo.options = ki->xkbOptions; + ret = InitKeyboardDeviceStruct (pDevice, &rmlvo, KdBell, KdKbdCtrl); + if (!ret) { + ErrorF("Couldn't initialise keyboard %s\n", ki->name); + return BadImplementation; + } + + xiclass = AtomFromName(XI_KEYBOARD); + AssignTypeAndName(pDevice, xiclass, + ki->name ? ki->name : "Generic KDrive Keyboard"); + + KdResetInputMachine(); + + return Success; + + case DEVICE_ON: + if (pDev->on == TRUE) + return Success; + + if (!ki->driver->Enable) + return BadImplementation; + + if ((*ki->driver->Enable) (ki) != Success) { + return BadMatch; + } + + pDev->on = TRUE; + return Success; + + case DEVICE_OFF: + if (pDev->on == FALSE) + return Success; + + if (!ki->driver->Disable) + return BadImplementation; + + (*ki->driver->Disable) (ki); + pDev->on = FALSE; + + return Success; + + break; + + case DEVICE_CLOSE: + if (pDev->on) { + if (!ki->driver->Disable) + return BadImplementation; + + (*ki->driver->Disable) (ki); + pDev->on = FALSE; + } + + if (!ki->driver->Fini) + return BadImplementation; + + (*ki->driver->Fini) (ki); + + KdRemoveKeyboard(ki); + + return Success; + } + + /* NOTREACHED */ + return BadImplementation; +} + +void +KdAddPointerDriver (KdPointerDriver *driver) +{ + KdPointerDriver **prev; + + if (!driver) + return; + + for (prev = &kdPointerDrivers; *prev; prev = &(*prev)->next) { + if (*prev == driver) + return; + } + *prev = driver; +} + +void +KdRemovePointerDriver (KdPointerDriver *driver) +{ + KdPointerDriver *tmp; + + if (!driver) + return; + + /* FIXME remove all pointers using this driver */ + for (tmp = kdPointerDrivers; tmp; tmp = tmp->next) { + if (tmp->next == driver) + tmp->next = driver->next; + } + if (tmp == driver) + tmp = NULL; +} + +void +KdAddKeyboardDriver (KdKeyboardDriver *driver) +{ + KdKeyboardDriver **prev; + + if (!driver) + return; + + for (prev = &kdKeyboardDrivers; *prev; prev = &(*prev)->next) { + if (*prev == driver) + return; + } + *prev = driver; +} + +void +KdRemoveKeyboardDriver (KdKeyboardDriver *driver) +{ + KdKeyboardDriver *tmp; + + if (!driver) + return; + + /* FIXME remove all keyboards using this driver */ + for (tmp = kdKeyboardDrivers; tmp; tmp = tmp->next) { + if (tmp->next == driver) + tmp->next = driver->next; + } + if (tmp == driver) + tmp = NULL; +} + +KdKeyboardInfo * +KdNewKeyboard (void) +{ + KdKeyboardInfo *ki = calloc(sizeof(KdKeyboardInfo), 1); + if (!ki) + return NULL; + + ki->minScanCode = 0; + ki->maxScanCode = 0; + ki->leds = 0; + ki->bellPitch = 1000; + ki->bellDuration = 200; + ki->next = NULL; + ki->options = NULL; + ki->xkbRules = strdup(XKB_DFLT_RULES); + ki->xkbModel = strdup(XKB_DFLT_MODEL); + ki->xkbLayout = strdup(XKB_DFLT_LAYOUT); + ki->xkbVariant = strdup(XKB_DFLT_VARIANT); + ki->xkbOptions = strdup(XKB_DFLT_OPTIONS); + + return ki; +} + +int +KdAddConfigKeyboard (char *keyboard) +{ + struct KdConfigDevice **prev, *new; + + if (!keyboard) + return Success; + + new = (struct KdConfigDevice *) calloc(sizeof(struct KdConfigDevice), 1); + if (!new) + return BadAlloc; + + new->line = strdup(keyboard); + new->next = NULL; + + for (prev = &kdConfigKeyboards; *prev; prev = &(*prev)->next); + *prev = new; + + return Success; +} + +int +KdAddKeyboard (KdKeyboardInfo *ki) +{ + KdKeyboardInfo **prev; + + if (!ki) + return !Success; + + ki->dixdev = AddInputDevice(serverClient, KdKeyboardProc, TRUE); + if (!ki->dixdev) { + ErrorF("Couldn't register keyboard device %s\n", + ki->name ? ki->name : "(unnamed)"); + return !Success; + } + +#ifdef DEBUG + ErrorF("added keyboard %s with dix id %d\n", ki->name, ki->dixdev->id); +#endif + + for (prev = &kdKeyboards; *prev; prev = &(*prev)->next); + *prev = ki; + + return Success; +} + +void +KdRemoveKeyboard (KdKeyboardInfo *ki) +{ + KdKeyboardInfo **prev; + + if (!ki) + return; + + for (prev = &kdKeyboards; *prev; prev = &(*prev)->next) { + if (*prev == ki) { + *prev = ki->next; + break; + } + } + + KdFreeKeyboard(ki); +} + +int +KdAddConfigPointer (char *pointer) +{ + struct KdConfigDevice **prev, *new; + + if (!pointer) + return Success; + + new = (struct KdConfigDevice *) calloc(sizeof(struct KdConfigDevice), 1); + if (!new) + return BadAlloc; + + new->line = strdup(pointer); + new->next = NULL; + + for (prev = &kdConfigPointers; *prev; prev = &(*prev)->next); + *prev = new; + + return Success; +} + +int +KdAddPointer (KdPointerInfo *pi) +{ + KdPointerInfo **prev; + + if (!pi) + return Success; + + pi->mouseState = start; + pi->eventHeld = FALSE; + + pi->dixdev = AddInputDevice(serverClient, KdPointerProc, TRUE); + if (!pi->dixdev) { + ErrorF("Couldn't add pointer device %s\n", + pi->name ? pi->name : "(unnamed)"); + return BadDevice; + } + + for (prev = &kdPointers; *prev; prev = &(*prev)->next); + *prev = pi; + + return Success; +} + +void +KdRemovePointer (KdPointerInfo *pi) +{ + KdPointerInfo **prev; + + if (!pi) + return; + + for (prev = &kdPointers; *prev; prev = &(*prev)->next) { + if (*prev == pi) { + *prev = pi->next; + break; + } + } + + KdFreePointer(pi); +} + +/* + * You can call your kdriver server with something like: + * $ ./hw/kdrive/yourserver/X :1 -mouse evdev,,device=/dev/input/event4 -keybd + * evdev,,device=/dev/input/event1,xkbmodel=abnt2,xkblayout=br + */ +static Bool +KdGetOptions (InputOption **options, char *string) +{ + InputOption *newopt = NULL, **tmpo = NULL; + int tam_key = 0; + + newopt = calloc(1, sizeof (InputOption)); + if (!newopt) + return FALSE; + + for (tmpo = options; *tmpo; tmpo = &(*tmpo)->next) + ; /* Hello, I'm here */ + *tmpo = newopt; + + if (strchr(string, '=')) + { + tam_key = (strchr(string, '=') - string); + newopt->key = (char *)malloc(tam_key); + strncpy(newopt->key, string, tam_key); + newopt->key[tam_key] = '\0'; + newopt->value = strdup(strchr(string, '=') + 1); + } + else + { + newopt->key = strdup(string); + newopt->value = NULL; + } + newopt->next = NULL; + + return TRUE; +} + +static void +KdParseKbdOptions (KdKeyboardInfo *ki) +{ + InputOption *option = NULL; + + for (option = ki->options; option; option = option->next) + { + if (strcasecmp(option->key, "XkbRules") == 0) + ki->xkbRules = option->value; + else if (strcasecmp(option->key, "XkbModel") == 0) + ki->xkbModel = option->value; + else if (strcasecmp(option->key, "XkbLayout") == 0) + ki->xkbLayout = option->value; + else if (strcasecmp(option->key, "XkbVariant") == 0) + ki->xkbVariant = option->value; + else if (strcasecmp(option->key, "XkbOptions") == 0) + ki->xkbOptions = option->value; + else if (!strcasecmp (option->key, "device")) + ki->path = strdup(option->value); + else + ErrorF("Kbd option key (%s) of value (%s) not assigned!\n", + option->key, option->value); + } +} + +KdKeyboardInfo * +KdParseKeyboard (char *arg) +{ + char save[1024]; + char delim; + InputOption *options = NULL; + KdKeyboardInfo *ki = NULL; + + ki = KdNewKeyboard(); + if (!ki) + return NULL; + + ki->name = strdup("Unknown KDrive Keyboard"); + ki->path = NULL; + ki->driver = NULL; + ki->driverPrivate = NULL; + ki->next = NULL; + + if (!arg) + { + ErrorF("keybd: no arg\n"); + KdFreeKeyboard (ki); + return NULL; + } + + if (strlen (arg) >= sizeof (save)) + { + ErrorF("keybd: arg too long\n"); + KdFreeKeyboard (ki); + return NULL; + } + + arg = KdParseFindNext (arg, ",", save, &delim); + if (!save[0]) + { + ErrorF("keybd: failed on save[0]\n"); + KdFreeKeyboard (ki); + return NULL; + } + + if (strcmp (save, "auto") == 0) + ki->driverPrivate = NULL; + else + ki->driverPrivate = strdup(save); + + if (delim != ',') + { + return ki; + } + + arg = KdParseFindNext (arg, ",", save, &delim); + + while (delim == ',') + { + arg = KdParseFindNext (arg, ",", save, &delim); + + if (!KdGetOptions(&options, save)) + { + KdFreeKeyboard(ki); + return NULL; + } + } + + if (options) + { + ki->options = options; + KdParseKbdOptions(ki); + } + + return ki; +} + +static void +KdParsePointerOptions (KdPointerInfo *pi) +{ + InputOption *option = NULL; + + for (option = pi->options; option; option = option->next) + { + if (!strcmp (option->key, "emulatemiddle")) + pi->emulateMiddleButton = TRUE; + else if (!strcmp (option->key, "noemulatemiddle")) + pi->emulateMiddleButton = FALSE; + else if (!strcmp (option->key, "transformcoord")) + pi->transformCoordinates = TRUE; + else if (!strcmp (option->key, "rawcoord")) + pi->transformCoordinates = FALSE; + else if (!strcasecmp (option->key, "device")) + pi->path = strdup(option->value); + else if (!strcasecmp (option->key, "protocol")) + pi->protocol = strdup(option->value); + else + ErrorF("Pointer option key (%s) of value (%s) not assigned!\n", + option->key, option->value); + } +} + +KdPointerInfo * +KdParsePointer (char *arg) +{ + char save[1024]; + char delim; + KdPointerInfo *pi = NULL; + InputOption *options = NULL; + int i = 0; + + pi = KdNewPointer(); + if (!pi) + return NULL; + pi->emulateMiddleButton = kdEmulateMiddleButton; + pi->transformCoordinates = !kdRawPointerCoordinates; + pi->protocol = NULL; + pi->nButtons = 5; /* XXX should not be hardcoded */ + pi->inputClass = KD_MOUSE; + + if (!arg) + { + ErrorF("mouse: no arg\n"); + KdFreePointer (pi); + return NULL; + } + + if (strlen (arg) >= sizeof (save)) + { + ErrorF("mouse: arg too long\n"); + KdFreePointer (pi); + return NULL; + } + arg = KdParseFindNext (arg, ",", save, &delim); + if (!save[0]) + { + ErrorF("failed on save[0]\n"); + KdFreePointer (pi); + return NULL; + } + + if (strcmp(save, "auto") == 0) + pi->driverPrivate = NULL; + else + pi->driverPrivate = strdup(save); + + if (delim != ',') + { + return pi; + } + + arg = KdParseFindNext (arg, ",", save, &delim); + + while (delim == ',') + { + arg = KdParseFindNext (arg, ",", save, &delim); + if (save[0] == '{') + { + char *s = save + 1; + i = 0; + while (*s && *s != '}') + { + if ('1' <= *s && *s <= '0' + pi->nButtons) + pi->map[i] = *s - '0'; + else + UseMsg (); + s++; + } + } + else + { + if (!KdGetOptions(&options, save)) + { + KdFreePointer(pi); + return NULL; + } + } + } + + if (options) + { + pi->options = options; + KdParsePointerOptions(pi); + } + + return pi; +} + + +void +KdInitInput (void) +{ + KdPointerInfo *pi; + KdKeyboardInfo *ki; + struct KdConfigDevice *dev; + + kdInputEnabled = TRUE; + + for (dev = kdConfigPointers; dev; dev = dev->next) { + pi = KdParsePointer(dev->line); + if (!pi) + ErrorF("Failed to parse pointer\n"); + if (KdAddPointer(pi) != Success) + ErrorF("Failed to add pointer!\n"); + } + for (dev = kdConfigKeyboards; dev; dev = dev->next) { + ki = KdParseKeyboard(dev->line); + if (!ki) + ErrorF("Failed to parse keyboard\n"); + if (KdAddKeyboard(ki) != Success) + ErrorF("Failed to add keyboard!\n"); + } + + mieqInit(); +} + +/* + * Middle button emulation state machine + * + * Possible transitions: + * Button 1 press v1 + * Button 1 release ^1 + * Button 2 press v2 + * Button 2 release ^2 + * Button 3 press v3 + * Button 3 release ^3 + * Button other press vo + * Button other release ^o + * Mouse motion <> + * Keyboard event k + * timeout ... + * outside box <-> + * + * States: + * start + * button_1_pend + * button_1_down + * button_2_down + * button_3_pend + * button_3_down + * synthetic_2_down_13 + * synthetic_2_down_3 + * synthetic_2_down_1 + * + * Transition diagram + * + * start + * v1 -> (hold) (settimeout) button_1_pend + * ^1 -> (deliver) start + * v2 -> (deliver) button_2_down + * ^2 -> (deliever) start + * v3 -> (hold) (settimeout) button_3_pend + * ^3 -> (deliver) start + * vo -> (deliver) start + * ^o -> (deliver) start + * <> -> (deliver) start + * k -> (deliver) start + * + * button_1_pend (button 1 is down, timeout pending) + * ^1 -> (release) (deliver) start + * v2 -> (release) (deliver) button_1_down + * ^2 -> (release) (deliver) button_1_down + * v3 -> (cleartimeout) (generate v2) synthetic_2_down_13 + * ^3 -> (release) (deliver) button_1_down + * vo -> (release) (deliver) button_1_down + * ^o -> (release) (deliver) button_1_down + * <-> -> (release) (deliver) button_1_down + * <> -> (deliver) button_1_pend + * k -> (release) (deliver) button_1_down + * ... -> (release) button_1_down + * + * button_1_down (button 1 is down) + * ^1 -> (deliver) start + * v2 -> (deliver) button_1_down + * ^2 -> (deliver) button_1_down + * v3 -> (deliver) button_1_down + * ^3 -> (deliver) button_1_down + * vo -> (deliver) button_1_down + * ^o -> (deliver) button_1_down + * <> -> (deliver) button_1_down + * k -> (deliver) button_1_down + * + * button_2_down (button 2 is down) + * v1 -> (deliver) button_2_down + * ^1 -> (deliver) button_2_down + * ^2 -> (deliver) start + * v3 -> (deliver) button_2_down + * ^3 -> (deliver) button_2_down + * vo -> (deliver) button_2_down + * ^o -> (deliver) button_2_down + * <> -> (deliver) button_2_down + * k -> (deliver) button_2_down + * + * button_3_pend (button 3 is down, timeout pending) + * v1 -> (generate v2) synthetic_2_down + * ^1 -> (release) (deliver) button_3_down + * v2 -> (release) (deliver) button_3_down + * ^2 -> (release) (deliver) button_3_down + * ^3 -> (release) (deliver) start + * vo -> (release) (deliver) button_3_down + * ^o -> (release) (deliver) button_3_down + * <-> -> (release) (deliver) button_3_down + * <> -> (deliver) button_3_pend + * k -> (release) (deliver) button_3_down + * ... -> (release) button_3_down + * + * button_3_down (button 3 is down) + * v1 -> (deliver) button_3_down + * ^1 -> (deliver) button_3_down + * v2 -> (deliver) button_3_down + * ^2 -> (deliver) button_3_down + * ^3 -> (deliver) start + * vo -> (deliver) button_3_down + * ^o -> (deliver) button_3_down + * <> -> (deliver) button_3_down + * k -> (deliver) button_3_down + * + * synthetic_2_down_13 (button 1 and 3 are down) + * ^1 -> (generate ^2) synthetic_2_down_3 + * v2 -> synthetic_2_down_13 + * ^2 -> synthetic_2_down_13 + * ^3 -> (generate ^2) synthetic_2_down_1 + * vo -> (deliver) synthetic_2_down_13 + * ^o -> (deliver) synthetic_2_down_13 + * <> -> (deliver) synthetic_2_down_13 + * k -> (deliver) synthetic_2_down_13 + * + * synthetic_2_down_3 (button 3 is down) + * v1 -> (deliver) synthetic_2_down_3 + * ^1 -> (deliver) synthetic_2_down_3 + * v2 -> synthetic_2_down_3 + * ^2 -> synthetic_2_down_3 + * ^3 -> start + * vo -> (deliver) synthetic_2_down_3 + * ^o -> (deliver) synthetic_2_down_3 + * <> -> (deliver) synthetic_2_down_3 + * k -> (deliver) synthetic_2_down_3 + * + * synthetic_2_down_1 (button 1 is down) + * ^1 -> start + * v2 -> synthetic_2_down_1 + * ^2 -> synthetic_2_down_1 + * v3 -> (deliver) synthetic_2_down_1 + * ^3 -> (deliver) synthetic_2_down_1 + * vo -> (deliver) synthetic_2_down_1 + * ^o -> (deliver) synthetic_2_down_1 + * <> -> (deliver) synthetic_2_down_1 + * k -> (deliver) synthetic_2_down_1 + */ + +typedef enum _inputClass { + down_1, up_1, + down_2, up_2, + down_3, up_3, + down_o, up_o, + motion, outside_box, + keyboard, timeout, + num_input_class +} KdInputClass; + +typedef enum _inputAction { + noop, + hold, + setto, + deliver, + release, + clearto, + gen_down_2, + gen_up_2 +} KdInputAction; + +#define MAX_ACTIONS 2 + +typedef struct _inputTransition { + KdInputAction actions[MAX_ACTIONS]; + KdPointerState nextState; +} KdInputTransition; + +static const +KdInputTransition kdInputMachine[num_input_states][num_input_class] = { + /* start */ + { + { { hold, setto }, button_1_pend }, /* v1 */ + { { deliver, noop }, start }, /* ^1 */ + { { deliver, noop }, button_2_down }, /* v2 */ + { { deliver, noop }, start }, /* ^2 */ + { { hold, setto }, button_3_pend }, /* v3 */ + { { deliver, noop }, start }, /* ^3 */ + { { deliver, noop }, start }, /* vo */ + { { deliver, noop }, start }, /* ^o */ + { { deliver, noop }, start }, /* <> */ + { { deliver, noop }, start }, /* <-> */ + { { noop, noop }, start }, /* k */ + { { noop, noop }, start }, /* ... */ + }, + /* button_1_pend */ + { + { { noop, noop }, button_1_pend }, /* v1 */ + { { release, deliver }, start }, /* ^1 */ + { { release, deliver }, button_1_down }, /* v2 */ + { { release, deliver }, button_1_down }, /* ^2 */ + { { clearto, gen_down_2 }, synth_2_down_13 }, /* v3 */ + { { release, deliver }, button_1_down }, /* ^3 */ + { { release, deliver }, button_1_down }, /* vo */ + { { release, deliver }, button_1_down }, /* ^o */ + { { deliver, noop }, button_1_pend }, /* <> */ + { { release, deliver }, button_1_down }, /* <-> */ + { { noop, noop }, button_1_down }, /* k */ + { { release, noop }, button_1_down }, /* ... */ + }, + /* button_1_down */ + { + { { noop, noop }, button_1_down }, /* v1 */ + { { deliver, noop }, start }, /* ^1 */ + { { deliver, noop }, button_1_down }, /* v2 */ + { { deliver, noop }, button_1_down }, /* ^2 */ + { { deliver, noop }, button_1_down }, /* v3 */ + { { deliver, noop }, button_1_down }, /* ^3 */ + { { deliver, noop }, button_1_down }, /* vo */ + { { deliver, noop }, button_1_down }, /* ^o */ + { { deliver, noop }, button_1_down }, /* <> */ + { { deliver, noop }, button_1_down }, /* <-> */ + { { noop, noop }, button_1_down }, /* k */ + { { noop, noop }, button_1_down }, /* ... */ + }, + /* button_2_down */ + { + { { deliver, noop }, button_2_down }, /* v1 */ + { { deliver, noop }, button_2_down }, /* ^1 */ + { { noop, noop }, button_2_down }, /* v2 */ + { { deliver, noop }, start }, /* ^2 */ + { { deliver, noop }, button_2_down }, /* v3 */ + { { deliver, noop }, button_2_down }, /* ^3 */ + { { deliver, noop }, button_2_down }, /* vo */ + { { deliver, noop }, button_2_down }, /* ^o */ + { { deliver, noop }, button_2_down }, /* <> */ + { { deliver, noop }, button_2_down }, /* <-> */ + { { noop, noop }, button_2_down }, /* k */ + { { noop, noop }, button_2_down }, /* ... */ + }, + /* button_3_pend */ + { + { { clearto, gen_down_2 }, synth_2_down_13 }, /* v1 */ + { { release, deliver }, button_3_down }, /* ^1 */ + { { release, deliver }, button_3_down }, /* v2 */ + { { release, deliver }, button_3_down }, /* ^2 */ + { { release, deliver }, button_3_down }, /* v3 */ + { { release, deliver }, start }, /* ^3 */ + { { release, deliver }, button_3_down }, /* vo */ + { { release, deliver }, button_3_down }, /* ^o */ + { { deliver, noop }, button_3_pend }, /* <> */ + { { release, deliver }, button_3_down }, /* <-> */ + { { release, noop }, button_3_down }, /* k */ + { { release, noop }, button_3_down }, /* ... */ + }, + /* button_3_down */ + { + { { deliver, noop }, button_3_down }, /* v1 */ + { { deliver, noop }, button_3_down }, /* ^1 */ + { { deliver, noop }, button_3_down }, /* v2 */ + { { deliver, noop }, button_3_down }, /* ^2 */ + { { noop, noop }, button_3_down }, /* v3 */ + { { deliver, noop }, start }, /* ^3 */ + { { deliver, noop }, button_3_down }, /* vo */ + { { deliver, noop }, button_3_down }, /* ^o */ + { { deliver, noop }, button_3_down }, /* <> */ + { { deliver, noop }, button_3_down }, /* <-> */ + { { noop, noop }, button_3_down }, /* k */ + { { noop, noop }, button_3_down }, /* ... */ + }, + /* synthetic_2_down_13 */ + { + { { noop, noop }, synth_2_down_13 }, /* v1 */ + { { gen_up_2, noop }, synth_2_down_3 }, /* ^1 */ + { { noop, noop }, synth_2_down_13 }, /* v2 */ + { { noop, noop }, synth_2_down_13 }, /* ^2 */ + { { noop, noop }, synth_2_down_13 }, /* v3 */ + { { gen_up_2, noop }, synth_2_down_1 }, /* ^3 */ + { { deliver, noop }, synth_2_down_13 }, /* vo */ + { { deliver, noop }, synth_2_down_13 }, /* ^o */ + { { deliver, noop }, synth_2_down_13 }, /* <> */ + { { deliver, noop }, synth_2_down_13 }, /* <-> */ + { { noop, noop }, synth_2_down_13 }, /* k */ + { { noop, noop }, synth_2_down_13 }, /* ... */ + }, + /* synthetic_2_down_3 */ + { + { { deliver, noop }, synth_2_down_3 }, /* v1 */ + { { deliver, noop }, synth_2_down_3 }, /* ^1 */ + { { deliver, noop }, synth_2_down_3 }, /* v2 */ + { { deliver, noop }, synth_2_down_3 }, /* ^2 */ + { { noop, noop }, synth_2_down_3 }, /* v3 */ + { { noop, noop }, start }, /* ^3 */ + { { deliver, noop }, synth_2_down_3 }, /* vo */ + { { deliver, noop }, synth_2_down_3 }, /* ^o */ + { { deliver, noop }, synth_2_down_3 }, /* <> */ + { { deliver, noop }, synth_2_down_3 }, /* <-> */ + { { noop, noop }, synth_2_down_3 }, /* k */ + { { noop, noop }, synth_2_down_3 }, /* ... */ + }, + /* synthetic_2_down_1 */ + { + { { noop, noop }, synth_2_down_1 }, /* v1 */ + { { noop, noop }, start }, /* ^1 */ + { { deliver, noop }, synth_2_down_1 }, /* v2 */ + { { deliver, noop }, synth_2_down_1 }, /* ^2 */ + { { deliver, noop }, synth_2_down_1 }, /* v3 */ + { { deliver, noop }, synth_2_down_1 }, /* ^3 */ + { { deliver, noop }, synth_2_down_1 }, /* vo */ + { { deliver, noop }, synth_2_down_1 }, /* ^o */ + { { deliver, noop }, synth_2_down_1 }, /* <> */ + { { deliver, noop }, synth_2_down_1 }, /* <-> */ + { { noop, noop }, synth_2_down_1 }, /* k */ + { { noop, noop }, synth_2_down_1 }, /* ... */ + }, +}; + +#define EMULATION_WINDOW 10 +#define EMULATION_TIMEOUT 100 + +static int +KdInsideEmulationWindow (KdPointerInfo *pi, int x, int y, int z) +{ + pi->emulationDx = pi->heldEvent.x - x; + pi->emulationDy = pi->heldEvent.y - y; + + return (abs (pi->emulationDx) < EMULATION_WINDOW && + abs (pi->emulationDy) < EMULATION_WINDOW); +} + +static KdInputClass +KdClassifyInput (KdPointerInfo *pi, int type, int x, int y, int z, int b) +{ + switch (type) { + case ButtonPress: + switch (b) { + case 1: return down_1; + case 2: return down_2; + case 3: return down_3; + default: return down_o; + } + break; + case ButtonRelease: + switch (b) { + case 1: return up_1; + case 2: return up_2; + case 3: return up_3; + default: return up_o; + } + break; + case MotionNotify: + if (pi->eventHeld && !KdInsideEmulationWindow(pi, x, y, z)) + return outside_box; + else + return motion; + default: + return keyboard; + } + return keyboard; +} + +#ifdef DEBUG +char *kdStateNames[] = { + "start", + "button_1_pend", + "button_1_down", + "button_2_down", + "button_3_pend", + "button_3_down", + "synth_2_down_13", + "synth_2_down_3", + "synthetic_2_down_1", + "num_input_states" +}; + +char *kdClassNames[] = { + "down_1", "up_1", + "down_2", "up_2", + "down_3", "up_3", + "motion", "ouside_box", + "keyboard", "timeout", + "num_input_class" +}; + +char *kdActionNames[] = { + "noop", + "hold", + "setto", + "deliver", + "release", + "clearto", + "gen_down_2", + "gen_up_2", +}; +#endif /* DEBUG */ + +static void +KdQueueEvent (DeviceIntPtr pDev, InternalEvent *ev) +{ + KdAssertSigioBlocked ("KdQueueEvent"); + mieqEnqueue (pDev, ev); +} + +/* We return true if we're stealing the event. */ +static Bool +KdRunMouseMachine (KdPointerInfo *pi, KdInputClass c, int type, int x, int y, + int z, int b, int absrel) +{ + const KdInputTransition *t; + int a; + + c = KdClassifyInput(pi, type, x, y, z, b); + t = &kdInputMachine[pi->mouseState][c]; + for (a = 0; a < MAX_ACTIONS; a++) + { + switch (t->actions[a]) { + case noop: + break; + case hold: + pi->eventHeld = TRUE; + pi->emulationDx = 0; + pi->emulationDy = 0; + pi->heldEvent.type = type; + pi->heldEvent.x = x; + pi->heldEvent.y = y; + pi->heldEvent.z = z; + pi->heldEvent.flags = b; + pi->heldEvent.absrel = absrel; + return TRUE; + break; + case setto: + pi->emulationTimeout = GetTimeInMillis () + EMULATION_TIMEOUT; + pi->timeoutPending = TRUE; + break; + case deliver: + _KdEnqueuePointerEvent (pi, pi->heldEvent.type, pi->heldEvent.x, + pi->heldEvent.y, pi->heldEvent.z, + pi->heldEvent.flags, pi->heldEvent.absrel, + TRUE); + break; + case release: + pi->eventHeld = FALSE; + pi->timeoutPending = FALSE; + _KdEnqueuePointerEvent (pi, pi->heldEvent.type, pi->heldEvent.x, + pi->heldEvent.y, pi->heldEvent.z, + pi->heldEvent.flags, pi->heldEvent.absrel, + TRUE); + return TRUE; + break; + case clearto: + pi->timeoutPending = FALSE; + break; + case gen_down_2: + _KdEnqueuePointerEvent (pi, ButtonPress, x, y, z, 2, absrel, + TRUE); + pi->eventHeld = FALSE; + return TRUE; + break; + case gen_up_2: + _KdEnqueuePointerEvent (pi, ButtonRelease, x, y, z, 2, absrel, + TRUE); + return TRUE; + break; + } + } + pi->mouseState = t->nextState; + return FALSE; +} + +static int +KdHandlePointerEvent (KdPointerInfo *pi, int type, int x, int y, int z, int b, + int absrel) +{ + if (pi->emulateMiddleButton) + return KdRunMouseMachine (pi, KdClassifyInput(pi, type, x, y, z, b), + type, x, y, z, b, absrel); + return FALSE; +} + +static void +KdReceiveTimeout (KdPointerInfo *pi) +{ + KdRunMouseMachine (pi, timeout, 0, 0, 0, 0, 0, 0); +} + +/* + * kdCheckTermination + * + * This function checks for the key sequence that terminates the server. When + * detected, it sets the dispatchException flag and returns. The key sequence + * is: + * Control-Alt + * It's assumed that the server will be waken up by the caller when this + * function returns. + */ + +extern int nClients; + +void +KdReleaseAllKeys (void) +{ +#if 0 + int key, nEvents, i; + KdKeyboardInfo *ki; + + KdBlockSigio (); + + for (ki = kdKeyboards; ki; ki = ki->next) { + for (key = ki->keySyms.minKeyCode; key < ki->keySyms.maxKeyCode; + key++) { + if (key_is_down(ki->dixdev, key, KEY_POSTED | KEY_PROCESSED)) { + KdHandleKeyboardEvent(ki, KeyRelease, key); + GetEventList(&kdEvents); + nEvents = GetKeyboardEvents(kdEvents, ki->dixdev, KeyRelease, key); + for (i = 0; i < nEvents; i++) + KdQueueEvent (ki->dixdev, (kdEvents + i)->event); + } + } + } + + KdUnblockSigio (); +#endif +} + +static void +KdCheckLock (void) +{ + KeyClassPtr keyc = NULL; + Bool isSet = FALSE, shouldBeSet = FALSE; + KdKeyboardInfo *tmp = NULL; + + for (tmp = kdKeyboards; tmp; tmp = tmp->next) { + if (tmp->LockLed && tmp->dixdev && tmp->dixdev->key) { + keyc = tmp->dixdev->key; + isSet = (tmp->leds & (1 << (tmp->LockLed-1))) != 0; + /* FIXME: Just use XKB indicators! */ + shouldBeSet = !!(XkbStateFieldFromRec(&keyc->xkbInfo->state) & LockMask); + if (isSet != shouldBeSet) + KdSetLed (tmp, tmp->LockLed, shouldBeSet); + } + } +} + +void +KdEnqueueKeyboardEvent(KdKeyboardInfo *ki, + unsigned char scan_code, + unsigned char is_up) +{ + unsigned char key_code; + KeyClassPtr keyc = NULL; + KeybdCtrl *ctrl = NULL; + int type, nEvents, i; + + if (!ki || !ki->dixdev || !ki->dixdev->kbdfeed || !ki->dixdev->key) + return; + + keyc = ki->dixdev->key; + ctrl = &ki->dixdev->kbdfeed->ctrl; + + if (scan_code >= ki->minScanCode && scan_code <= ki->maxScanCode) + { + key_code = scan_code + KD_MIN_KEYCODE - ki->minScanCode; + + /* + * Set up this event -- the type may be modified below + */ + if (is_up) + type = KeyRelease; + else + type = KeyPress; + + GetEventList(&kdEvents); + + nEvents = GetKeyboardEvents(kdEvents, ki->dixdev, type, key_code); + for (i = 0; i < nEvents; i++) + KdQueueEvent(ki->dixdev, (InternalEvent *)((kdEvents + i)->event)); + } + else { + ErrorF("driver %s wanted to post scancode %d outside of [%d, %d]!\n", + ki->name, scan_code, ki->minScanCode, ki->maxScanCode); + } +} + +/* + * kdEnqueuePointerEvent + * + * This function converts hardware mouse event information into X event + * information. A mouse movement event is passed off to MI to generate + * a MotionNotify event, if appropriate. Button events are created and + * passed off to MI for enqueueing. + */ + +/* FIXME do something a little more clever to deal with multiple axes here */ +void +KdEnqueuePointerEvent(KdPointerInfo *pi, unsigned long flags, int rx, int ry, + int rz) +{ + CARD32 ms; + unsigned char buttons; + int x, y, z; + int (*matrix)[3] = kdPointerMatrix.matrix; + unsigned long button; + int n; + int dixflags = 0; + + if (!pi) + return; + + ms = GetTimeInMillis(); + + /* we don't need to transform z, so we don't. */ + if (flags & KD_MOUSE_DELTA) { + if (pi->transformCoordinates) { + x = matrix[0][0] * rx + matrix[0][1] * ry; + y = matrix[1][0] * rx + matrix[1][1] * ry; + } + else { + x = rx; + y = ry; + } + } + else { + if (pi->transformCoordinates) { + x = matrix[0][0] * rx + matrix[0][1] * ry + matrix[0][2]; + y = matrix[1][0] * rx + matrix[1][1] * ry + matrix[1][2]; + } + else { + x = rx; + y = ry; + } + } + z = rz; + + if (flags & KD_MOUSE_DELTA) + { + if (x || y || z) + { + dixflags = POINTER_RELATIVE | POINTER_ACCELERATE; + _KdEnqueuePointerEvent(pi, MotionNotify, x, y, z, 0, dixflags, FALSE); + } + } else + { + dixflags = POINTER_ABSOLUTE; + if (x != pi->dixdev->last.valuators[0] || + y != pi->dixdev->last.valuators[1]) + _KdEnqueuePointerEvent(pi, MotionNotify, x, y, z, 0, dixflags, FALSE); + } + + buttons = flags; + + for (button = KD_BUTTON_1, n = 1; n <= pi->nButtons; + button <<= 1, n++) { + if (((pi->buttonState & button) ^ (buttons & button)) && + !(buttons & button)) { + _KdEnqueuePointerEvent(pi, ButtonRelease, x, y, z, n, + dixflags, FALSE); + } + } + for (button = KD_BUTTON_1, n = 1; n <= pi->nButtons; + button <<= 1, n++) { + if (((pi->buttonState & button) ^ (buttons & button)) && + (buttons & button)) { + _KdEnqueuePointerEvent(pi, ButtonPress, x, y, z, n, + dixflags, FALSE); + } + } + + pi->buttonState = buttons; +} + +void +_KdEnqueuePointerEvent (KdPointerInfo *pi, int type, int x, int y, int z, + int b, int absrel, Bool force) +{ + int nEvents = 0, i = 0; + int valuators[3] = { x, y, z }; + ValuatorMask mask; + + /* TRUE from KdHandlePointerEvent, means 'we swallowed the event'. */ + if (!force && KdHandlePointerEvent(pi, type, x, y, z, b, absrel)) + return; + + valuator_mask_set_range(&mask, 0, 3, valuators); + + GetEventList(&kdEvents); + nEvents = GetPointerEvents(kdEvents, pi->dixdev, type, b, absrel, &mask); + for (i = 0; i < nEvents; i++) + KdQueueEvent(pi->dixdev, (InternalEvent *)((kdEvents + i)->event)); +} + +void +KdBlockHandler (int screen, + pointer blockData, + pointer timeout, + pointer readmask) +{ + KdPointerInfo *pi; + int myTimeout=0; + + for (pi = kdPointers; pi; pi = pi->next) + { + if (pi->timeoutPending) + { + int ms; + + ms = pi->emulationTimeout - GetTimeInMillis (); + if (ms < 1) + ms = 1; + if(ms<myTimeout || myTimeout==0) + myTimeout=ms; + } + } + /* if we need to poll for events, do that */ + if(kdOsFuncs->pollEvents) + { + (*kdOsFuncs->pollEvents)(); + myTimeout=20; + } + if(myTimeout>0) + AdjustWaitForDelay (timeout, myTimeout); +} + +void +KdWakeupHandler (int screen, + pointer data, + unsigned long lresult, + pointer readmask) +{ + int result = (int) lresult; + fd_set *pReadmask = (fd_set *) readmask; + int i; + KdPointerInfo *pi; + + if (kdInputEnabled && result > 0) + { + for (i = 0; i < kdNumInputFds; i++) + if (FD_ISSET (kdInputFds[i].fd, pReadmask)) + { + KdBlockSigio (); + (*kdInputFds[i].read) (kdInputFds[i].fd, kdInputFds[i].closure); + KdUnblockSigio (); + } + } + for (pi = kdPointers; pi; pi = pi->next) + { + if (pi->timeoutPending) + { + if ((long) (GetTimeInMillis () - pi->emulationTimeout) >= 0) + { + pi->timeoutPending = FALSE; + KdBlockSigio (); + KdReceiveTimeout (pi); + KdUnblockSigio (); + } + } + } + if (kdSwitchPending) + KdProcessSwitch (); +} + +#define KdScreenOrigin(pScreen) (&(KdGetScreenPriv(pScreen)->screen->origin)) + +static Bool +KdCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y) +{ + ScreenPtr pScreen = *ppScreen; + ScreenPtr pNewScreen; + int n; + int dx, dy; + int best_x, best_y; + int n_best_x, n_best_y; + CARD32 ms; + + if (kdDisableZaphod || screenInfo.numScreens <= 1) + return FALSE; + + if (0 <= *x && *x < pScreen->width && 0 <= *y && *y < pScreen->height) + return FALSE; + + ms = GetTimeInMillis (); + if (kdOffScreen && (int) (ms - kdOffScreenTime) < 1000) + return FALSE; + kdOffScreen = TRUE; + kdOffScreenTime = ms; + n_best_x = -1; + best_x = 32767; + n_best_y = -1; + best_y = 32767; + for (n = 0; n < screenInfo.numScreens; n++) + { + pNewScreen = screenInfo.screens[n]; + if (pNewScreen == pScreen) + continue; + dx = KdScreenOrigin(pNewScreen)->x - KdScreenOrigin(pScreen)->x; + dy = KdScreenOrigin(pNewScreen)->y - KdScreenOrigin(pScreen)->y; + if (*x < 0) + { + if (dx <= 0 && -dx < best_x) + { + best_x = -dx; + n_best_x = n; + } + } + else if (*x >= pScreen->width) + { + if (dx >= 0 && dx < best_x) + { + best_x = dx; + n_best_x = n; + } + } + if (*y < 0) + { + if (dy <= 0 && -dy < best_y) + { + best_y = -dy; + n_best_y = n; + } + } + else if (*y >= pScreen->height) + { + if (dy >= 0 && dy < best_y) + { + best_y = dy; + n_best_y = n; + } + } + } + if (best_y < best_x) + n_best_x = n_best_y; + if (n_best_x == -1) + return FALSE; + pNewScreen = screenInfo.screens[n_best_x]; + + if (*x < 0) + *x += pNewScreen->width; + if (*y < 0) + *y += pNewScreen->height; + + if (*x >= pScreen->width) + *x -= pScreen->width; + if (*y >= pScreen->height) + *y -= pScreen->height; + + *ppScreen = pNewScreen; + return TRUE; +} + +static void +KdCrossScreen(ScreenPtr pScreen, Bool entering) +{ +#ifndef XIPAQ + if (entering) + KdEnableScreen (pScreen); + else + KdDisableScreen (pScreen); +#endif +} + +int KdCurScreen; /* current event screen */ + +static void +KdWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + KdBlockSigio (); + KdCurScreen = pScreen->myNum; + miPointerWarpCursor(pDev, pScreen, x, y); + KdUnblockSigio (); +} + +miPointerScreenFuncRec kdPointerScreenFuncs = +{ + KdCursorOffScreen, + KdCrossScreen, + KdWarpCursor +}; + +void +ProcessInputEvents (void) +{ + mieqProcessInputEvents(); + miPointerUpdateSprite(inputInfo.pointer); + if (kdSwitchPending) + KdProcessSwitch (); + KdCheckLock (); +} + +/* At the moment, absolute/relative is up to the client. */ +int +SetDeviceMode(register ClientPtr client, DeviceIntPtr pDev, int mode) +{ + return BadMatch; +} + +int +SetDeviceValuators(register ClientPtr client, DeviceIntPtr pDev, + int *valuators, int first_valuator, int num_valuators) +{ + return BadMatch; +} + +int +ChangeDeviceControl(register ClientPtr client, DeviceIntPtr pDev, + xDeviceCtl *control) +{ + switch (control->control) { + case DEVICE_RESOLUTION: + /* FIXME do something more intelligent here */ + return BadMatch; + + case DEVICE_ABS_CALIB: + case DEVICE_ABS_AREA: + case DEVICE_CORE: + return BadMatch; + case DEVICE_ENABLE: + return Success; + + default: + return BadMatch; + } + + /* NOTREACHED */ + return BadImplementation; +} + +int +NewInputDeviceRequest(InputOption *options, InputAttributes *attrs, + DeviceIntPtr *pdev) +{ + InputOption *option = NULL; + KdPointerInfo *pi = NULL; + KdKeyboardInfo *ki = NULL; + + for (option = options; option; option = option->next) { + if (strcmp(option->key, "type") == 0) { + if (strcmp(option->value, "pointer") == 0) { + pi = KdNewPointer(); + if (!pi) + return BadAlloc; + } + else if (strcmp(option->value, "keyboard") == 0) { + ki = KdNewKeyboard(); + if (!ki) + return BadAlloc; + } + else { + ErrorF("unrecognised device type!\n"); + return BadValue; + } + } +#ifdef CONFIG_HAL + else if (strcmp(option->key, "_source") == 0 && + strcmp(option->value, "server/hal") == 0) + { + ErrorF("Ignoring device from HAL.\n"); + return BadValue; + } +#endif +#ifdef CONFIG_UDEV + else if (strcmp(option->key, "_source") == 0 && + strcmp(option->value, "server/udev") == 0) + { + ErrorF("Ignoring device from udev.\n"); + return BadValue; + } +#endif + } + + if (!ki && !pi) { + ErrorF("unrecognised device identifier!\n"); + return BadValue; + } + + /* FIXME: change this code below to use KdParseKbdOptions and + * KdParsePointerOptions */ + for (option = options; option; option = option->next) { + if (strcmp(option->key, "device") == 0) { + if (pi && option->value) + pi->path = strdup(option->value); + else if (ki && option->value) + ki->path = strdup(option->value); + } + else if (strcmp(option->key, "driver") == 0) { + if (pi) { + pi->driver = KdFindPointerDriver(option->value); + if (!pi->driver) { + ErrorF("couldn't find driver!\n"); + KdFreePointer(pi); + return BadValue; + } + pi->options = options; + } + else if (ki) { + ki->driver = KdFindKeyboardDriver(option->value); + if (!ki->driver) { + ErrorF("couldn't find driver!\n"); + KdFreeKeyboard(ki); + return BadValue; + } + ki->options = options; + } + } + } + + if (pi) { + if (KdAddPointer(pi) != Success || + ActivateDevice(pi->dixdev, TRUE) != Success || + EnableDevice(pi->dixdev, TRUE) != TRUE) { + ErrorF("couldn't add or enable pointer\n"); + return BadImplementation; + } + } + else if (ki) { + if (KdAddKeyboard(ki) != Success || + ActivateDevice(ki->dixdev, TRUE) != Success || + EnableDevice(ki->dixdev, TRUE) != TRUE) { + ErrorF("couldn't add or enable keyboard\n"); + return BadImplementation; + } + } + + if (pi) { + *pdev = pi->dixdev; + } else if(ki) { + *pdev = ki->dixdev; + } + + return Success; +} + +void +DeleteInputDeviceRequest(DeviceIntPtr pDev) +{ + RemoveDevice(pDev, TRUE); +} diff --git a/xorg-server/hw/xfree86/common/xf86Helper.c b/xorg-server/hw/xfree86/common/xf86Helper.c index 1a5bf8a1c..399883886 100644 --- a/xorg-server/hw/xfree86/common/xf86Helper.c +++ b/xorg-server/hw/xfree86/common/xf86Helper.c @@ -983,106 +983,6 @@ xf86SetBlackWhitePixels(ScreenPtr pScreen) } /* - * xf86SetRootClip -- - * Enable or disable rendering to the screen by - * setting the root clip list and revalidating - * all of the windows - */ - -static void -xf86SetRootClip (ScreenPtr pScreen, Bool enable) -{ - WindowPtr pWin = pScreen->root; - WindowPtr pChild; - Bool WasViewable = (Bool)(pWin->viewable); - Bool anyMarked = FALSE; - WindowPtr pLayerWin; - BoxRec box; - - 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 = RegionCreate(NullBox, 1); - RegionSubtract(borderVisible, - &pWin->borderClip, &pWin->winSize); - pWin->valdata->before.borderVisible = borderVisible; - } - pWin->valdata->before.resized = TRUE; - } - } - - /* - * Use REGION_BREAK to avoid optimizations in ValidateTree - * that assume the root borderClip can't change well, normally - * it doesn't...) - */ - if (enable) - { - box.x1 = 0; - box.y1 = 0; - box.x2 = pScreen->width; - box.y2 = pScreen->height; - RegionInit(&pWin->winSize, &box, 1); - RegionInit(&pWin->borderSize, &box, 1); - if (WasViewable) - RegionReset(&pWin->borderClip, &box); - pWin->drawable.width = pScreen->width; - pWin->drawable.height = pScreen->height; - RegionBreak(&pWin->clipList); - } - else - { - RegionEmpty(&pWin->borderClip); - RegionBreak(&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 (); - FlushAllOutput (); -} - -/* * Function to enable/disable access to the frame buffer * * This is used when VT switching and when entering/leaving DGA direct mode. @@ -1115,7 +1015,7 @@ xf86EnableDisableFBAccess(int scrnIndex, Bool enable) * Restore all of the clip lists on the screen */ if (!xf86Resetting) - xf86SetRootClip (pScreen, TRUE); + SetRootClip (pScreen, TRUE); } else @@ -1123,7 +1023,7 @@ xf86EnableDisableFBAccess(int scrnIndex, Bool enable) /* * Empty all of the clip lists on the screen */ - xf86SetRootClip (pScreen, FALSE); + SetRootClip (pScreen, FALSE); } } diff --git a/xorg-server/hw/xfree86/common/xf86Xinput.c b/xorg-server/hw/xfree86/common/xf86Xinput.c index 4166a1c38..ae22ef268 100644 --- a/xorg-server/hw/xfree86/common/xf86Xinput.c +++ b/xorg-server/hw/xfree86/common/xf86Xinput.c @@ -1,1409 +1,1411 @@ -/*
- * Copyright 1995-1999 by Frederic Lepied, France. <Lepied@XFree86.org>
- *
- * 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 Frederic Lepied not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Frederic Lepied makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL FREDERIC LEPIED 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) 2000-2002 by The XFree86 Project, Inc.
- *
- * 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:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of the copyright holder(s)
- * and author(s) 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 copyright holder(s) and author(s).
- */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include <X11/Xfuncproto.h>
-#include <X11/Xmd.h>
-#include <X11/extensions/XI.h>
-#include <X11/extensions/XIproto.h>
-#include <X11/Xatom.h>
-#include "xf86.h"
-#include "xf86Priv.h"
-#include "xf86Config.h"
-#include "xf86Xinput.h"
-#include "xf86Optrec.h"
-#include "mipointer.h"
-#include "extinit.h"
-#include "loaderProcs.h"
-
-#include "exevents.h" /* AddInputDevice */
-#include "exglobals.h"
-#include "eventstr.h"
-#include "inpututils.h"
-
-#include <string.h> /* InputClassMatches */
-#ifdef HAVE_FNMATCH_H
-#include <fnmatch.h>
-#endif
-#ifdef HAVE_SYS_UTSNAME_H
-#include <sys/utsname.h>
-#endif
-
-#include <stdarg.h>
-#include <stdint.h> /* for int64_t */
-
-#include "mi.h"
-
-#include <ptrveloc.h> /* dix pointer acceleration */
-#include <xserver-properties.h>
-
-#ifdef XFreeXDGA
-#include "dgaproc.h"
-#endif
-
-#include "xkbsrv.h"
-
-/* Valuator verification macro */
-#define XI_VERIFY_VALUATORS(num_valuators) \
- if (num_valuators > MAX_VALUATORS) { \
- xf86Msg(X_ERROR, "%s: num_valuator %d is greater than" \
- " MAX_VALUATORS\n", __FUNCTION__, num_valuators); \
- return; \
- }
-
-EventListPtr xf86Events = NULL;
-
-static int
-xf86InputDevicePostInit(DeviceIntPtr dev);
-
-/**
- * Eval config and modify DeviceVelocityRec accordingly
- */
-static void
-ProcessVelocityConfiguration(DeviceIntPtr pDev, char* devname, pointer list,
- DeviceVelocityPtr s)
-{
- int tempi;
- float tempf;
- Atom float_prop = XIGetKnownProperty(XATOM_FLOAT);
- Atom prop;
-
- if(!s)
- return;
-
- /* common settings (available via device properties) */
- tempf = xf86SetRealOption(list, "ConstantDeceleration", 1.0);
- if (tempf > 1.0) {
- xf86Msg(X_CONFIG, "%s: (accel) constant deceleration by %.1f\n",
- devname, tempf);
- prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION);
- XIChangeDeviceProperty(pDev, prop, float_prop, 32,
- PropModeReplace, 1, &tempf, FALSE);
- }
-
- tempf = xf86SetRealOption(list, "AdaptiveDeceleration", 1.0);
- if (tempf > 1.0) {
- xf86Msg(X_CONFIG, "%s: (accel) adaptive deceleration by %.1f\n",
- devname, tempf);
- prop = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION);
- XIChangeDeviceProperty(pDev, prop, float_prop, 32,
- PropModeReplace, 1, &tempf, FALSE);
- }
-
- /* select profile by number */
- tempi = xf86SetIntOption(list, "AccelerationProfile",
- s->statistics.profile_number);
-
- prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER);
- if (XIChangeDeviceProperty(pDev, prop, XA_INTEGER, 32,
- PropModeReplace, 1, &tempi, FALSE) == Success) {
- xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i\n", devname,
- tempi);
- } else {
- xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i is unknown\n",
- devname, tempi);
- }
-
- /* set scaling */
- tempf = xf86SetRealOption(list, "ExpectedRate", 0);
- prop = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING);
- if (tempf > 0) {
- tempf = 1000.0 / tempf;
- XIChangeDeviceProperty(pDev, prop, float_prop, 32,
- PropModeReplace, 1, &tempf, FALSE);
- } else {
- tempf = xf86SetRealOption(list, "VelocityScale", s->corr_mul);
- XIChangeDeviceProperty(pDev, prop, float_prop, 32,
- PropModeReplace, 1, &tempf, FALSE);
- }
-
- tempi = xf86SetIntOption(list, "VelocityTrackerCount", -1);
- if (tempi > 1)
- InitTrackers(s, tempi);
-
- s->initial_range = xf86SetIntOption(list, "VelocityInitialRange",
- s->initial_range);
-
- s->max_diff = xf86SetRealOption(list, "VelocityAbsDiff", s->max_diff);
-
- tempf = xf86SetRealOption(list, "VelocityRelDiff", -1);
- if (tempf >= 0) {
- xf86Msg(X_CONFIG, "%s: (accel) max rel. velocity difference: %.1f%%\n",
- devname, tempf*100.0);
- s->max_rel_diff = tempf;
- }
-
- /* Configure softening. If const deceleration is used, this is expected
- * to provide better subpixel information so we enable
- * softening by default only if ConstantDeceleration is not used
- */
- s->use_softening = xf86SetBoolOption(list, "Softening",
- s->const_acceleration == 1.0);
-
- s->average_accel = xf86SetBoolOption(list, "AccelerationProfileAveraging",
- s->average_accel);
-
- s->reset_time = xf86SetIntOption(list, "VelocityReset", s->reset_time);
-}
-
-static void
-ApplyAccelerationSettings(DeviceIntPtr dev){
- int scheme, i;
- DeviceVelocityPtr pVel;
- InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate;
- char* schemeStr;
-
- if (dev->valuator && dev->ptrfeed) {
- schemeStr = xf86SetStrOption(pInfo->options, "AccelerationScheme", "");
-
- scheme = dev->valuator->accelScheme.number;
-
- if (!xf86NameCmp(schemeStr, "predictable"))
- scheme = PtrAccelPredictable;
-
- if (!xf86NameCmp(schemeStr, "lightweight"))
- scheme = PtrAccelLightweight;
-
- if (!xf86NameCmp(schemeStr, "none"))
- scheme = PtrAccelNoOp;
-
- /* reinit scheme if needed */
- if (dev->valuator->accelScheme.number != scheme) {
- if (dev->valuator->accelScheme.AccelCleanupProc) {
- dev->valuator->accelScheme.AccelCleanupProc(dev);
- }
-
- if (InitPointerAccelerationScheme(dev, scheme)) {
- xf86Msg(X_CONFIG, "%s: (accel) selected scheme %s/%i\n",
- pInfo->name, schemeStr, scheme);
- } else {
- xf86Msg(X_CONFIG, "%s: (accel) could not init scheme %s\n",
- pInfo->name, schemeStr);
- scheme = dev->valuator->accelScheme.number;
- }
- } else {
- xf86Msg(X_CONFIG, "%s: (accel) keeping acceleration scheme %i\n",
- pInfo->name, scheme);
- }
-
- free(schemeStr);
-
- /* process special configuration */
- switch (scheme) {
- case PtrAccelPredictable:
- pVel = GetDevicePredictableAccelData(dev);
- ProcessVelocityConfiguration (dev, pInfo->name, pInfo->options,
- pVel);
- break;
- }
-
- i = xf86SetIntOption(pInfo->options, "AccelerationNumerator",
- dev->ptrfeed->ctrl.num);
- if (i >= 0)
- dev->ptrfeed->ctrl.num = i;
-
- i = xf86SetIntOption(pInfo->options, "AccelerationDenominator",
- dev->ptrfeed->ctrl.den);
- if (i > 0)
- dev->ptrfeed->ctrl.den = i;
-
- i = xf86SetIntOption(pInfo->options, "AccelerationThreshold",
- dev->ptrfeed->ctrl.threshold);
- if (i >= 0)
- dev->ptrfeed->ctrl.threshold = i;
-
- xf86Msg(X_CONFIG, "%s: (accel) acceleration factor: %.3f\n",
- pInfo->name, ((float)dev->ptrfeed->ctrl.num)/
- ((float)dev->ptrfeed->ctrl.den));
- xf86Msg(X_CONFIG, "%s: (accel) acceleration threshold: %i\n",
- pInfo->name, dev->ptrfeed->ctrl.threshold);
- }
-}
-
-/***********************************************************************
- *
- * xf86ProcessCommonOptions --
- *
- * Process global options.
- *
- ***********************************************************************
- */
-void
-xf86ProcessCommonOptions(InputInfoPtr pInfo,
- pointer list)
-{
- if (xf86SetBoolOption(list, "Floating", 0) ||
- !xf86SetBoolOption(list, "AlwaysCore", 1) ||
- !xf86SetBoolOption(list, "SendCoreEvents", 1) ||
- !xf86SetBoolOption(list, "CorePointer", 1) ||
- !xf86SetBoolOption(list, "CoreKeyboard", 1)) {
- xf86Msg(X_CONFIG, "%s: doesn't report core events\n", pInfo->name);
- } else {
- pInfo->flags |= XI86_ALWAYS_CORE;
- xf86Msg(X_CONFIG, "%s: always reports core events\n", pInfo->name);
- }
-}
-
-/***********************************************************************
- *
- * xf86ActivateDevice --
- *
- * Initialize an input device.
- *
- * Returns TRUE on success, or FALSE otherwise.
- ***********************************************************************
- */
-static DeviceIntPtr
-xf86ActivateDevice(InputInfoPtr pInfo)
-{
- DeviceIntPtr dev;
- Atom atom;
-
- dev = AddInputDevice(serverClient, pInfo->device_control, TRUE);
-
- if (dev == NULL)
- {
- xf86Msg(X_ERROR, "Too many input devices. Ignoring %s\n",
- pInfo->name);
- pInfo->dev = NULL;
- return NULL;
- }
-
- atom = MakeAtom(pInfo->type_name, strlen(pInfo->type_name), TRUE);
- AssignTypeAndName(dev, atom, pInfo->name);
- dev->public.devicePrivate = pInfo;
- pInfo->dev = dev;
-
- dev->coreEvents = pInfo->flags & XI86_ALWAYS_CORE;
- dev->type = SLAVE;
- dev->spriteInfo->spriteOwner = FALSE;
-
- dev->config_info = xf86SetStrOption(pInfo->options, "config_info", NULL);
-
- if (serverGeneration == 1)
- xf86Msg(X_INFO, "XINPUT: Adding extended input device \"%s\" (type: %s)\n",
- pInfo->name, pInfo->type_name);
-
- return dev;
-}
-
-/****************************************************************************
- *
- * Caller: ProcXSetDeviceMode
- *
- * Change the mode of an extension device.
- * This function is used to change the mode of a device from reporting
- * relative motion to reporting absolute positional information, and
- * vice versa.
- * The default implementation below is that no such devices are supported.
- *
- ***********************************************************************
- */
-
-int
-SetDeviceMode (ClientPtr client, DeviceIntPtr dev, int mode)
-{
- InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate;
-
- if (pInfo->switch_mode) {
- return (*pInfo->switch_mode)(client, dev, mode);
- }
- else
- return BadMatch;
-}
-
-
-/***********************************************************************
- *
- * Caller: ProcXSetDeviceValuators
- *
- * Set the value of valuators on an extension input device.
- * This function is used to set the initial value of valuators on
- * those input devices that are capable of reporting either relative
- * motion or an absolute position, and allow an initial position to be set.
- * The default implementation below is that no such devices are supported.
- *
- ***********************************************************************
- */
-
-int
-SetDeviceValuators (ClientPtr client, DeviceIntPtr dev, int *valuators,
- int first_valuator, int num_valuators)
-{
- InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate;
-
- if (pInfo->set_device_valuators)
- return (*pInfo->set_device_valuators)(pInfo, valuators, first_valuator,
- num_valuators);
-
- return BadMatch;
-}
-
-
-/***********************************************************************
- *
- * Caller: ProcXChangeDeviceControl
- *
- * Change the specified device controls on an extension input device.
- *
- ***********************************************************************
- */
-
-int
-ChangeDeviceControl (ClientPtr client, DeviceIntPtr dev, xDeviceCtl *control)
-{
- InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate;
-
- if (!pInfo->control_proc) {
- switch (control->control) {
- case DEVICE_CORE:
- return BadMatch;
- case DEVICE_RESOLUTION:
- case DEVICE_ABS_CALIB:
- case DEVICE_ABS_AREA:
- case DEVICE_ENABLE:
- return Success;
- default:
- return BadMatch;
- }
- }
- else {
- return (*pInfo->control_proc)(pInfo, control);
- }
-}
-
-/*
- * Get the operating system name from uname and store it statically to avoid
- * repeating the system call each time MatchOS is checked.
- */
-static const char *
-HostOS(void)
-{
-#ifdef HAVE_SYS_UTSNAME_H
- struct utsname name;
- static char host_os[sizeof(name.sysname)] = "";
-
- if (*host_os == '\0') {
- if (uname(&name) >= 0)
- strcpy(host_os, name.sysname);
- else {
- strncpy(host_os, "unknown", sizeof(host_os));
- host_os[sizeof(host_os)-1] = '\0';
- }
- }
- return host_os;
-#else
- return "";
-#endif
-}
-
-static int
-match_substring(const char *attr, const char *pattern)
-{
- return (strstr(attr, pattern)) ? 0 : -1;
-}
-
-#ifdef HAVE_FNMATCH_H
-static int
-match_pattern(const char *attr, const char *pattern)
-{
- return fnmatch(pattern, attr, 0);
-}
-#else
-#define match_pattern match_substring
-#endif
-
-#ifdef HAVE_FNMATCH_H
-static int
-match_path_pattern(const char *attr, const char *pattern)
-{
- return fnmatch(pattern, attr, FNM_PATHNAME);
-}
-#else
-#define match_path_pattern match_substring
-#endif
-
-/*
- * Match an attribute against a list of NULL terminated arrays of patterns.
- * If a pattern in each list entry is matched, return TRUE.
- */
-static Bool
-MatchAttrToken(const char *attr, struct list *patterns,
- int (*compare)(const char *attr, const char *pattern))
-{
- const xf86MatchGroup *group;
-
- /* If there are no patterns, accept the match */
- if (list_is_empty(patterns))
- return TRUE;
-
- /* If there are patterns but no attribute, reject the match */
- if (!attr)
- return FALSE;
-
- /*
- * Otherwise, iterate the list of patterns ensuring each entry has a
- * match. Each list entry is a separate Match line of the same type.
- */
- list_for_each_entry(group, patterns, entry) {
- char * const *cur;
- Bool match = FALSE;
-
- for (cur = group->values; *cur; cur++)
- if ((*compare)(attr, *cur) == 0) {
- match = TRUE;
- break;
- }
- if (!match)
- return FALSE;
- }
-
- /* All the entries in the list matched the attribute */
- return TRUE;
-}
-
-/*
- * Classes without any Match statements match all devices. Otherwise, all
- * statements must match.
- */
-static Bool
-InputClassMatches(const XF86ConfInputClassPtr iclass, const InputInfoPtr idev,
- const InputAttributes *attrs)
-{
- /* MatchProduct substring */
- if (!MatchAttrToken(attrs->product, &iclass->match_product, match_substring))
- return FALSE;
-
- /* MatchVendor substring */
- if (!MatchAttrToken(attrs->vendor, &iclass->match_vendor, match_substring))
- return FALSE;
-
- /* MatchDevicePath pattern */
- if (!MatchAttrToken(attrs->device, &iclass->match_device, match_path_pattern))
- return FALSE;
-
- /* MatchOS case-insensitive string */
- if (!MatchAttrToken(HostOS(), &iclass->match_os, strcasecmp))
- return FALSE;
-
- /* MatchPnPID pattern */
- if (!MatchAttrToken(attrs->pnp_id, &iclass->match_pnpid, match_pattern))
- return FALSE;
-
- /* MatchUSBID pattern */
- if (!MatchAttrToken(attrs->usb_id, &iclass->match_usbid, match_pattern))
- return FALSE;
-
- /* MatchDriver string */
- if (!MatchAttrToken(idev->driver, &iclass->match_driver, strcmp))
- return FALSE;
-
- /*
- * MatchTag string
- * See if any of the device's tags match any of the MatchTag tokens.
- */
- if (!list_is_empty(&iclass->match_tag)) {
- char * const *tag;
- Bool match;
-
- if (!attrs->tags)
- return FALSE;
- for (tag = attrs->tags, match = FALSE; *tag; tag++) {
- if (MatchAttrToken(*tag, &iclass->match_tag, strcmp)) {
- match = TRUE;
- break;
- }
- }
- if (!match)
- return FALSE;
- }
-
- /* MatchIs* booleans */
- if (iclass->is_keyboard.set &&
- iclass->is_keyboard.val != !!(attrs->flags & ATTR_KEYBOARD))
- return FALSE;
- if (iclass->is_pointer.set &&
- iclass->is_pointer.val != !!(attrs->flags & ATTR_POINTER))
- return FALSE;
- if (iclass->is_joystick.set &&
- iclass->is_joystick.val != !!(attrs->flags & ATTR_JOYSTICK))
- return FALSE;
- if (iclass->is_tablet.set &&
- iclass->is_tablet.val != !!(attrs->flags & ATTR_TABLET))
- return FALSE;
- if (iclass->is_touchpad.set &&
- iclass->is_touchpad.val != !!(attrs->flags & ATTR_TOUCHPAD))
- return FALSE;
- if (iclass->is_touchscreen.set &&
- iclass->is_touchscreen.val != !!(attrs->flags & ATTR_TOUCHSCREEN))
- return FALSE;
-
- return TRUE;
-}
-
-/*
- * Merge in any InputClass configurations. Options in each InputClass
- * section have more priority than the original device configuration as
- * well as any previous InputClass sections.
- */
-static int
-MergeInputClasses(const InputInfoPtr idev, const InputAttributes *attrs)
-{
- XF86ConfInputClassPtr cl;
- XF86OptionPtr classopts;
-
- for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) {
- if (!InputClassMatches(cl, idev, attrs))
- continue;
-
- /* Collect class options and driver settings */
- classopts = xf86optionListDup(cl->option_lst);
- if (cl->driver) {
- free(idev->driver);
- idev->driver = xstrdup(cl->driver);
- if (!idev->driver) {
- xf86Msg(X_ERROR, "Failed to allocate memory while merging "
- "InputClass configuration");
- return BadAlloc;
- }
- classopts = xf86ReplaceStrOption(classopts, "driver",
- idev->driver);
- }
-
- /* Apply options to device with InputClass settings preferred. */
- xf86Msg(X_CONFIG, "%s: Applying InputClass \"%s\"\n",
- idev->name, cl->identifier);
- idev->options = xf86optionListMerge(idev->options, classopts);
- }
-
- return Success;
-}
-
-/*
- * Iterate the list of classes and look for Option "Ignore". Return the
- * value of the last matching class and holler when returning TRUE.
- */
-static Bool
-IgnoreInputClass(const InputInfoPtr idev, const InputAttributes *attrs)
-{
- XF86ConfInputClassPtr cl;
- Bool ignore = FALSE;
- const char *ignore_class;
-
- for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) {
- if (!InputClassMatches(cl, idev, attrs))
- continue;
- if (xf86findOption(cl->option_lst, "Ignore")) {
- ignore = xf86CheckBoolOption(cl->option_lst, "Ignore", FALSE);
- ignore_class = cl->identifier;
- }
- }
-
- if (ignore)
- xf86Msg(X_CONFIG, "%s: Ignoring device from InputClass \"%s\"\n",
- idev->name, ignore_class);
- return ignore;
-}
-
-InputInfoPtr
-xf86AllocateInput(void)
-{
- InputInfoPtr pInfo;
-
- pInfo = calloc(sizeof(*pInfo), 1);
- if (!pInfo)
- return NULL;
-
- pInfo->fd = -1;
- pInfo->type_name = "UNKNOWN";
-
- return pInfo;
-}
-
-/* Append InputInfoRec to the tail of xf86InputDevs. */
-static void
-xf86AddInput(InputDriverPtr drv, InputInfoPtr pInfo)
-{
- InputInfoPtr *prev = NULL;
-
- pInfo->drv = drv;
- pInfo->module = DuplicateModule(drv->module, NULL);
-
- for (prev = &xf86InputDevs; *prev; prev = &(*prev)->next)
- ;
-
- *prev = pInfo;
- pInfo->next = NULL;
-
- xf86CollectInputOptions(pInfo, (const char**)drv->default_options);
- xf86OptionListReport(pInfo->options);
- xf86ProcessCommonOptions(pInfo, pInfo->options);
-}
-
-/*
- * Remove an entry from xf86InputDevs and free all the device's information.
- */
-void
-xf86DeleteInput(InputInfoPtr pInp, int flags)
-{
- /* First check if the inputdev is valid. */
- if (pInp == NULL)
- return;
-
- if (pInp->module)
- UnloadModule(pInp->module);
-
- /* This should *really* be handled in drv->UnInit(dev) call instead, but
- * if the driver forgets about it make sure we free it or at least crash
- * with flying colors */
- free(pInp->private);
-
- FreeInputAttributes(pInp->attrs);
-
- /* Remove the entry from the list. */
- if (pInp == xf86InputDevs)
- xf86InputDevs = pInp->next;
- else {
- InputInfoPtr p = xf86InputDevs;
- while (p && p->next != pInp)
- p = p->next;
- if (p)
- p->next = pInp->next;
- /* Else the entry wasn't in the xf86InputDevs list (ignore this). */
- }
-
- free(pInp->driver);
- free(pInp->name);
- xf86optionListFree(pInp->options);
- free(pInp);
-}
-
-/*
- * Apply backend-specific initialization. Invoked after ActiveteDevice(),
- * i.e. after the driver successfully completed DEVICE_INIT and the device
- * is advertised.
- * @param dev the device
- * @return Success or an error code
- */
-static int
-xf86InputDevicePostInit(DeviceIntPtr dev) {
- ApplyAccelerationSettings(dev);
- return Success;
-}
-
-/**
- * Create a new input device, activate and enable it.
- *
- * Possible return codes:
- * BadName .. a bad driver name was supplied.
- * BadImplementation ... The driver does not have a PreInit function. This
- * is a driver bug.
- * BadMatch .. device initialization failed.
- * BadAlloc .. too many input devices
- *
- * @param idev The device, already set up with identifier, driver, and the
- * options.
- * @param pdev Pointer to the new device, if Success was reported.
- * @param enable Enable the device after activating it.
- *
- * @return Success or an error code
- */
-_X_INTERNAL int
-xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable)
-{
- InputDriverPtr drv = NULL;
- DeviceIntPtr dev = NULL;
- int rval;
-
- /* Memory leak for every attached device if we don't
- * test if the module is already loaded first */
- drv = xf86LookupInputDriver(pInfo->driver);
- if (!drv)
- if (xf86LoadOneModule(pInfo->driver, NULL))
- drv = xf86LookupInputDriver(pInfo->driver);
- if (!drv) {
- xf86Msg(X_ERROR, "No input driver matching `%s'\n", pInfo->driver);
- rval = BadName;
- goto unwind;
- }
-
- if (!drv->PreInit) {
- xf86Msg(X_ERROR,
- "Input driver `%s' has no PreInit function (ignoring)\n",
- drv->driverName);
- rval = BadImplementation;
- goto unwind;
- }
-
- xf86AddInput(drv, pInfo);
-
- rval = drv->PreInit(drv, pInfo, 0);
-
- if (rval != Success) {
- xf86Msg(X_ERROR, "PreInit returned %d for \"%s\"\n", rval, pInfo->name);
- goto unwind;
- }
-
- if (!(dev = xf86ActivateDevice(pInfo)))
- {
- rval = BadAlloc;
- goto unwind;
- }
-
- rval = ActivateDevice(dev, TRUE);
- if (rval != Success)
- {
- xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name);
- RemoveDevice(dev, TRUE);
- goto unwind;
- }
-
- rval = xf86InputDevicePostInit(dev);
- if (rval != Success)
- {
- xf86Msg(X_ERROR, "Couldn't post-init device \"%s\"\n", pInfo->name);
- RemoveDevice(dev, TRUE);
- goto unwind;
- }
-
- /* Enable it if it's properly initialised and we're currently in the VT */
- if (enable && dev->inited && dev->startup && xf86Screens[0]->vtSema)
- {
- OsBlockSignals();
- EnableDevice(dev, TRUE);
- if (!dev->enabled)
- {
- OsReleaseSignals();
- xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name);
- rval = BadMatch;
- goto unwind;
- }
- /* send enter/leave event, update sprite window */
- CheckMotion(NULL, dev);
- OsReleaseSignals();
- }
-
- *pdev = dev;
- return Success;
-
-unwind:
- if(pInfo) {
- if(drv && drv->UnInit)
- drv->UnInit(drv, pInfo, 0);
- else
- xf86DeleteInput(pInfo, 0);
- }
- return rval;
-}
-
-int
-NewInputDeviceRequest (InputOption *options, InputAttributes *attrs,
- DeviceIntPtr *pdev)
-{
- InputInfoPtr pInfo = NULL;
- InputOption *option = NULL;
- int rval = Success;
- int is_auto = 0;
-
- pInfo = xf86AllocateInput();
- if (!pInfo)
- return BadAlloc;
-
- for (option = options; option; option = option->next) {
- if (strcasecmp(option->key, "driver") == 0) {
- if (pInfo->driver) {
- rval = BadRequest;
- goto unwind;
- }
- pInfo->driver = xstrdup(option->value);
- if (!pInfo->driver) {
- rval = BadAlloc;
- goto unwind;
- }
- }
-
- if (strcasecmp(option->key, "name") == 0 ||
- strcasecmp(option->key, "identifier") == 0) {
- if (pInfo->name) {
- rval = BadRequest;
- goto unwind;
- }
- pInfo->name = xstrdup(option->value);
- if (!pInfo->name) {
- rval = BadAlloc;
- goto unwind;
- }
- }
-
- if (strcmp(option->key, "_source") == 0 &&
- (strcmp(option->value, "server/hal") == 0 ||
- strcmp(option->value, "server/udev") == 0)) {
- is_auto = 1;
- if (!xf86Info.autoAddDevices) {
- rval = BadMatch;
- goto unwind;
- }
- }
- }
-
- for (option = options; option; option = option->next) {
- /* Steal option key/value strings from the provided list.
- * We need those strings, the InputOption list doesn't. */
- pInfo->options = xf86addNewOption(pInfo->options,
- option->key, option->value);
- option->key = NULL;
- option->value = NULL;
- }
-
- /* Apply InputClass settings */
- if (attrs) {
- if (IgnoreInputClass(pInfo, attrs)) {
- rval = BadIDChoice;
- goto unwind;
- }
-
- rval = MergeInputClasses(pInfo, attrs);
- if (rval != Success)
- goto unwind;
-
- pInfo->attrs = DuplicateInputAttributes(attrs);
- }
-
- if (!pInfo->driver || !pInfo->name) {
- xf86Msg(X_INFO, "No input driver/identifier specified (ignoring)\n");
- rval = BadRequest;
- goto unwind;
- }
-
- if (!pInfo->name) {
- xf86Msg(X_ERROR, "No device identifier specified (ignoring)\n");
- rval = BadMatch;
- goto unwind;
- }
-
- rval = xf86NewInputDevice(pInfo, pdev,
- (!is_auto || (is_auto && xf86Info.autoEnableDevices)));
-
- return rval;
-
-unwind:
- if (is_auto && !xf86Info.autoAddDevices)
- xf86Msg(X_INFO, "AutoAddDevices is off - not adding device.\n");
- xf86DeleteInput(pInfo, 0);
- return rval;
-}
-
-void
-DeleteInputDeviceRequest(DeviceIntPtr pDev)
-{
- InputInfoPtr pInfo = (InputInfoPtr) pDev->public.devicePrivate;
- InputDriverPtr drv = NULL;
- Bool isMaster = IsMaster(pDev);
-
- if (pInfo) /* need to get these before RemoveDevice */
- drv = pInfo->drv;
-
- OsBlockSignals();
- RemoveDevice(pDev, TRUE);
-
- if (!isMaster && pInfo != NULL)
- {
- if(drv->UnInit)
- drv->UnInit(drv, pInfo, 0);
- else
- xf86DeleteInput(pInfo, 0);
- }
- OsReleaseSignals();
-}
-
-/*
- * convenient functions to post events
- */
-
-void
-xf86PostMotionEvent(DeviceIntPtr device,
- int is_absolute,
- int first_valuator,
- int num_valuators,
- ...)
-{
- va_list var;
- int i = 0;
- ValuatorMask mask;
-
- XI_VERIFY_VALUATORS(num_valuators);
-
- valuator_mask_zero(&mask);
- va_start(var, num_valuators);
- for (i = 0; i < num_valuators; i++)
- valuator_mask_set(&mask, first_valuator + i, va_arg(var, int));
- va_end(var);
-
- xf86PostMotionEventM(device, is_absolute, &mask);
-}
-
-void
-xf86PostMotionEventP(DeviceIntPtr device,
- int is_absolute,
- int first_valuator,
- int num_valuators,
- const int *valuators)
-{
- ValuatorMask mask;
-
- XI_VERIFY_VALUATORS(num_valuators);
-
- valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators);
- xf86PostMotionEventM(device, is_absolute, &mask);
-}
-
-void
-xf86PostMotionEventM(DeviceIntPtr device,
- int is_absolute,
- const ValuatorMask *mask)
-{
- int i = 0, nevents = 0;
- DeviceEvent *event;
- int flags = 0;
-
- if (valuator_mask_num_valuators(mask) > 0)
- {
- if (is_absolute)
- flags = POINTER_ABSOLUTE;
- else
- flags = POINTER_RELATIVE | POINTER_ACCELERATE;
- }
-
-#if XFreeXDGA
- /* The evdev driver may not always send all axes across. */
- if (valuator_mask_isset(mask, 0) ||
- valuator_mask_isset(mask, 1))
- if (miPointerGetScreen(device)) {
- int index = miPointerGetScreen(device)->myNum;
- int dx = 0, dy = 0;
-
- if (valuator_mask_isset(mask, 0))
- {
- dx = valuator_mask_get(mask, 0);
- if (is_absolute)
- dx -= device->last.valuators[0];
- }
-
- if (valuator_mask_isset(mask, 1))
- {
- dy = valuator_mask_get(mask, 1);
- if (is_absolute)
- dy -= device->last.valuators[1];
- }
-
- if (DGAStealMotionEvent(device, index, dx, dy))
- return;
- }
-#endif
-
- nevents = GetPointerEvents(xf86Events, device, MotionNotify, 0, flags, mask);
-
- for (i = 0; i < nevents; i++) {
- event = (DeviceEvent*)((xf86Events + i)->event);
- mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event));
- }
-}
-
-void
-xf86PostProximityEvent(DeviceIntPtr device,
- int is_in,
- int first_valuator,
- int num_valuators,
- ...)
-{
- va_list var;
- int i;
- ValuatorMask mask;
-
- XI_VERIFY_VALUATORS(num_valuators);
-
- valuator_mask_zero(&mask);
- va_start(var, num_valuators);
- for (i = 0; i < num_valuators; i++)
- valuator_mask_set(&mask, first_valuator + i, va_arg(var, int));
- va_end(var);
-
- xf86PostProximityEventM(device, is_in, &mask);
-}
-
-void
-xf86PostProximityEventP(DeviceIntPtr device,
- int is_in,
- int first_valuator,
- int num_valuators,
- const int *valuators)
-{
- ValuatorMask mask;
-
- XI_VERIFY_VALUATORS(num_valuators);
-
- valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators);
- xf86PostProximityEventM(device, is_in, &mask);
-}
-
-void
-xf86PostProximityEventM(DeviceIntPtr device,
- int is_in,
- const ValuatorMask *mask)
-{
- int i, nevents;
-
- nevents = GetProximityEvents(xf86Events, device,
- is_in ? ProximityIn : ProximityOut, mask);
- for (i = 0; i < nevents; i++)
- mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event));
-
-}
-
-void
-xf86PostButtonEvent(DeviceIntPtr device,
- int is_absolute,
- int button,
- int is_down,
- int first_valuator,
- int num_valuators,
- ...)
-{
- va_list var;
- ValuatorMask mask;
- int i = 0;
-
- XI_VERIFY_VALUATORS(num_valuators);
-
- valuator_mask_zero(&mask);
-
- va_start(var, num_valuators);
- for (i = 0; i < num_valuators; i++)
- valuator_mask_set(&mask, first_valuator + i, va_arg(var, int));
- va_end(var);
-
- xf86PostButtonEventM(device, is_absolute, button, is_down, &mask);
-}
-
-void
-xf86PostButtonEventP(DeviceIntPtr device,
- int is_absolute,
- int button,
- int is_down,
- int first_valuator,
- int num_valuators,
- const int *valuators)
-{
- ValuatorMask mask;
-
- XI_VERIFY_VALUATORS(num_valuators);
-
- valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators);
- xf86PostButtonEventM(device, is_absolute, button, is_down, &mask);
-}
-
-void
-xf86PostButtonEventM(DeviceIntPtr device,
- int is_absolute,
- int button,
- int is_down,
- const ValuatorMask *mask)
-{
- int i = 0, nevents = 0;
- int flags = 0;
-
- if (valuator_mask_num_valuators(mask) > 0)
- {
- if (is_absolute)
- flags = POINTER_ABSOLUTE;
- else
- flags = POINTER_RELATIVE | POINTER_ACCELERATE;
- }
-
-#if XFreeXDGA
- if (miPointerGetScreen(device)) {
- int index = miPointerGetScreen(device)->myNum;
-
- if (DGAStealButtonEvent(device, index, button, is_down))
- return;
- }
-#endif
-
- nevents = GetPointerEvents(xf86Events, device,
- is_down ? ButtonPress : ButtonRelease, button,
- flags, mask);
-
- for (i = 0; i < nevents; i++)
- mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event));
-
-}
-
-void
-xf86PostKeyEvent(DeviceIntPtr device,
- unsigned int key_code,
- int is_down,
- int is_absolute,
- int first_valuator,
- int num_valuators,
- ...)
-{
- va_list var;
- int i = 0;
- ValuatorMask mask;
-
- XI_VERIFY_VALUATORS(num_valuators);
-
- valuator_mask_zero(&mask);
-
- va_start(var, num_valuators);
- for (i = 0; i < num_valuators; i++)
- valuator_mask_set(&mask, first_valuator + i, va_arg(var, int));
- va_end(var);
-
- xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask);
-}
-
-void
-xf86PostKeyEventP(DeviceIntPtr device,
- unsigned int key_code,
- int is_down,
- int is_absolute,
- int first_valuator,
- int num_valuators,
- const int *valuators)
-{
- ValuatorMask mask;
-
- XI_VERIFY_VALUATORS(num_valuators);
-
- valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators);
- xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask);
-}
-
-void
-xf86PostKeyEventM(DeviceIntPtr device,
- unsigned int key_code,
- int is_down,
- int is_absolute,
- const ValuatorMask *mask)
-{
- int i = 0, nevents = 0;
-
-#if XFreeXDGA
- DeviceIntPtr pointer;
-
- /* Some pointers send key events, paired device is wrong then. */
- pointer = IsPointerDevice(device) ? device : GetPairedDevice(device);
- if (miPointerGetScreen(pointer)) {
- int index = miPointerGetScreen(pointer)->myNum;
-
- if (DGAStealKeyEvent(device, index, key_code, is_down))
- return;
- }
-#endif
-
- if (is_absolute) {
- nevents = GetKeyboardValuatorEvents(xf86Events, device,
- is_down ? KeyPress : KeyRelease,
- key_code, mask);
- }
- else {
- nevents = GetKeyboardEvents(xf86Events, device,
- is_down ? KeyPress : KeyRelease,
- key_code);
- }
-
- for (i = 0; i < nevents; i++)
- mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event));
-}
-
-void
-xf86PostKeyboardEvent(DeviceIntPtr device,
- unsigned int key_code,
- int is_down)
-{
- ValuatorMask mask;
-
- valuator_mask_zero(&mask);
- xf86PostKeyEventM(device, key_code, is_down, 0, &mask);
-}
-
-InputInfoPtr
-xf86FirstLocalDevice(void)
-{
- return xf86InputDevs;
-}
-
-/*
- * Cx - raw data from touch screen
- * to_max - scaled highest dimension
- * (remember, this is of rows - 1 because of 0 origin)
- * to_min - scaled lowest dimension
- * from_max - highest raw value from touch screen calibration
- * from_min - lowest raw value from touch screen calibration
- *
- * This function is the same for X or Y coordinates.
- * You may have to reverse the high and low values to compensate for
- * different orgins on the touch screen vs X.
- *
- * e.g. to scale from device coordinates into screen coordinates, call
- * xf86ScaleAxis(x, 0, screen_width, dev_min, dev_max);
- */
-
-int
-xf86ScaleAxis(int Cx,
- int to_max,
- int to_min,
- int from_max,
- int from_min )
-{
- int X;
- int64_t to_width = to_max - to_min;
- int64_t from_width = from_max - from_min;
-
- if (from_width) {
- X = (int)(((to_width * (Cx - from_min)) / from_width) + to_min);
- }
- else {
- X = 0;
- ErrorF ("Divide by Zero in xf86ScaleAxis\n");
- }
-
- if (X > to_max)
- X = to_max;
- if (X < to_min)
- X = to_min;
-
- return X;
-}
-
-/*
- * This function checks the given screen against the current screen and
- * makes changes if appropriate. It should be called from an XInput driver's
- * ReadInput function before any events are posted, if the device is screen
- * specific like a touch screen.
- */
-void
-xf86XInputSetScreen(InputInfoPtr pInfo,
- int screen_number,
- int x,
- int y)
-{
- if (miPointerGetScreen(pInfo->dev) !=
- screenInfo.screens[screen_number]) {
- miPointerSetScreen(pInfo->dev, screen_number, x, y);
- }
-}
-
-
-void
-xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
- int resolution, int min_res, int max_res, int mode)
-{
- if (!dev || !dev->valuator)
- return;
-
- InitValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution, min_res,
- max_res, mode);
-}
-
-/*
- * Set the valuator values to be in synch with dix/event.c
- * DefineInitialRootWindow().
- */
-void
-xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum)
-{
- if (axnum == 0) {
- dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
- dev->last.valuators[0] = dev->valuator->axisVal[0];
- }
- else if (axnum == 1) {
- dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
- dev->last.valuators[1] = dev->valuator->axisVal[1];
- }
-}
-
-
-/**
- * Deactivate a device. Call this function from the driver if you receive a
- * read error or something else that spoils your day.
- * Device will be moved to the off_devices list, but it will still be there
- * until you really clean up after it.
- * Notifies the client about an inactive device.
- *
- * @param panic True if device is unrecoverable and needs to be removed.
- */
-void
-xf86DisableDevice(DeviceIntPtr dev, Bool panic)
-{
- if(!panic)
- {
- DisableDevice(dev, TRUE);
- } else
- {
- SendDevicePresenceEvent(dev->id, DeviceUnrecoverable);
- DeleteInputDeviceRequest(dev);
- }
-}
-
-/**
- * Reactivate a device. Call this function from the driver if you just found
- * out that the read error wasn't quite that bad after all.
- * Device will be re-activated, and an event sent to the client.
- */
-void
-xf86EnableDevice(DeviceIntPtr dev)
-{
- EnableDevice(dev, TRUE);
-}
-
-/* end of xf86Xinput.c */
+/* + * Copyright 1995-1999 by Frederic Lepied, France. <Lepied@XFree86.org> + * + * 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 Frederic Lepied not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Frederic Lepied makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL FREDERIC LEPIED 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) 2000-2002 by The XFree86 Project, Inc. + * + * 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: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <X11/Xfuncproto.h> +#include <X11/Xmd.h> +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include <X11/Xatom.h> +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86Config.h" +#include "xf86Xinput.h" +#include "xf86Optrec.h" +#include "mipointer.h" +#include "extinit.h" +#include "loaderProcs.h" + +#include "exevents.h" /* AddInputDevice */ +#include "exglobals.h" +#include "eventstr.h" +#include "inpututils.h" + +#include <string.h> /* InputClassMatches */ +#ifdef HAVE_FNMATCH_H +#include <fnmatch.h> +#endif +#ifdef HAVE_SYS_UTSNAME_H +#include <sys/utsname.h> +#endif + +#include <stdarg.h> +#include <stdint.h> /* for int64_t */ + +#include "mi.h" + +#include <ptrveloc.h> /* dix pointer acceleration */ +#include <xserver-properties.h> + +#ifdef XFreeXDGA +#include "dgaproc.h" +#endif + +#include "xkbsrv.h" + +/* Valuator verification macro */ +#define XI_VERIFY_VALUATORS(num_valuators) \ + if (num_valuators > MAX_VALUATORS) { \ + xf86Msg(X_ERROR, "%s: num_valuator %d is greater than" \ + " MAX_VALUATORS\n", __FUNCTION__, num_valuators); \ + return; \ + } + +EventListPtr xf86Events = NULL; + +static int +xf86InputDevicePostInit(DeviceIntPtr dev); + +/** + * Eval config and modify DeviceVelocityRec accordingly + */ +static void +ProcessVelocityConfiguration(DeviceIntPtr pDev, char* devname, pointer list, + DeviceVelocityPtr s) +{ + int tempi; + float tempf; + Atom float_prop = XIGetKnownProperty(XATOM_FLOAT); + Atom prop; + + if(!s) + return; + + /* common settings (available via device properties) */ + tempf = xf86SetRealOption(list, "ConstantDeceleration", 1.0); + if (tempf > 1.0) { + xf86Msg(X_CONFIG, "%s: (accel) constant deceleration by %.1f\n", + devname, tempf); + prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION); + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } + + tempf = xf86SetRealOption(list, "AdaptiveDeceleration", 1.0); + if (tempf > 1.0) { + xf86Msg(X_CONFIG, "%s: (accel) adaptive deceleration by %.1f\n", + devname, tempf); + prop = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION); + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } + + /* select profile by number */ + tempi = xf86SetIntOption(list, "AccelerationProfile", + s->statistics.profile_number); + + prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER); + if (XIChangeDeviceProperty(pDev, prop, XA_INTEGER, 32, + PropModeReplace, 1, &tempi, FALSE) == Success) { + xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i\n", devname, + tempi); + } else { + xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i is unknown\n", + devname, tempi); + } + + /* set scaling */ + tempf = xf86SetRealOption(list, "ExpectedRate", 0); + prop = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING); + if (tempf > 0) { + tempf = 1000.0 / tempf; + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } else { + tempf = xf86SetRealOption(list, "VelocityScale", s->corr_mul); + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } + + tempi = xf86SetIntOption(list, "VelocityTrackerCount", -1); + if (tempi > 1) + InitTrackers(s, tempi); + + s->initial_range = xf86SetIntOption(list, "VelocityInitialRange", + s->initial_range); + + s->max_diff = xf86SetRealOption(list, "VelocityAbsDiff", s->max_diff); + + tempf = xf86SetRealOption(list, "VelocityRelDiff", -1); + if (tempf >= 0) { + xf86Msg(X_CONFIG, "%s: (accel) max rel. velocity difference: %.1f%%\n", + devname, tempf*100.0); + s->max_rel_diff = tempf; + } + + /* Configure softening. If const deceleration is used, this is expected + * to provide better subpixel information so we enable + * softening by default only if ConstantDeceleration is not used + */ + s->use_softening = xf86SetBoolOption(list, "Softening", + s->const_acceleration == 1.0); + + s->average_accel = xf86SetBoolOption(list, "AccelerationProfileAveraging", + s->average_accel); + + s->reset_time = xf86SetIntOption(list, "VelocityReset", s->reset_time); +} + +static void +ApplyAccelerationSettings(DeviceIntPtr dev){ + int scheme, i; + DeviceVelocityPtr pVel; + InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; + char* schemeStr; + + if (dev->valuator && dev->ptrfeed) { + schemeStr = xf86SetStrOption(pInfo->options, "AccelerationScheme", ""); + + scheme = dev->valuator->accelScheme.number; + + if (!xf86NameCmp(schemeStr, "predictable")) + scheme = PtrAccelPredictable; + + if (!xf86NameCmp(schemeStr, "lightweight")) + scheme = PtrAccelLightweight; + + if (!xf86NameCmp(schemeStr, "none")) + scheme = PtrAccelNoOp; + + /* reinit scheme if needed */ + if (dev->valuator->accelScheme.number != scheme) { + if (dev->valuator->accelScheme.AccelCleanupProc) { + dev->valuator->accelScheme.AccelCleanupProc(dev); + } + + if (InitPointerAccelerationScheme(dev, scheme)) { + xf86Msg(X_CONFIG, "%s: (accel) selected scheme %s/%i\n", + pInfo->name, schemeStr, scheme); + } else { + xf86Msg(X_CONFIG, "%s: (accel) could not init scheme %s\n", + pInfo->name, schemeStr); + scheme = dev->valuator->accelScheme.number; + } + } else { + xf86Msg(X_CONFIG, "%s: (accel) keeping acceleration scheme %i\n", + pInfo->name, scheme); + } + + free(schemeStr); + + /* process special configuration */ + switch (scheme) { + case PtrAccelPredictable: + pVel = GetDevicePredictableAccelData(dev); + ProcessVelocityConfiguration (dev, pInfo->name, pInfo->options, + pVel); + break; + } + + i = xf86SetIntOption(pInfo->options, "AccelerationNumerator", + dev->ptrfeed->ctrl.num); + if (i >= 0) + dev->ptrfeed->ctrl.num = i; + + i = xf86SetIntOption(pInfo->options, "AccelerationDenominator", + dev->ptrfeed->ctrl.den); + if (i > 0) + dev->ptrfeed->ctrl.den = i; + + i = xf86SetIntOption(pInfo->options, "AccelerationThreshold", + dev->ptrfeed->ctrl.threshold); + if (i >= 0) + dev->ptrfeed->ctrl.threshold = i; + + xf86Msg(X_CONFIG, "%s: (accel) acceleration factor: %.3f\n", + pInfo->name, ((float)dev->ptrfeed->ctrl.num)/ + ((float)dev->ptrfeed->ctrl.den)); + xf86Msg(X_CONFIG, "%s: (accel) acceleration threshold: %i\n", + pInfo->name, dev->ptrfeed->ctrl.threshold); + } +} + +/*********************************************************************** + * + * xf86ProcessCommonOptions -- + * + * Process global options. + * + *********************************************************************** + */ +void +xf86ProcessCommonOptions(InputInfoPtr pInfo, + pointer list) +{ + if (xf86SetBoolOption(list, "Floating", 0) || + !xf86SetBoolOption(list, "AlwaysCore", 1) || + !xf86SetBoolOption(list, "SendCoreEvents", 1) || + !xf86SetBoolOption(list, "CorePointer", 1) || + !xf86SetBoolOption(list, "CoreKeyboard", 1)) { + xf86Msg(X_CONFIG, "%s: doesn't report core events\n", pInfo->name); + } else { + pInfo->flags |= XI86_ALWAYS_CORE; + xf86Msg(X_CONFIG, "%s: always reports core events\n", pInfo->name); + } +} + +/*********************************************************************** + * + * xf86ActivateDevice -- + * + * Initialize an input device. + * + * Returns TRUE on success, or FALSE otherwise. + *********************************************************************** + */ +static DeviceIntPtr +xf86ActivateDevice(InputInfoPtr pInfo) +{ + DeviceIntPtr dev; + Atom atom; + + dev = AddInputDevice(serverClient, pInfo->device_control, TRUE); + + if (dev == NULL) + { + xf86Msg(X_ERROR, "Too many input devices. Ignoring %s\n", + pInfo->name); + pInfo->dev = NULL; + return NULL; + } + + atom = MakeAtom(pInfo->type_name, strlen(pInfo->type_name), TRUE); + AssignTypeAndName(dev, atom, pInfo->name); + dev->public.devicePrivate = pInfo; + pInfo->dev = dev; + + dev->coreEvents = pInfo->flags & XI86_ALWAYS_CORE; + dev->type = SLAVE; + dev->spriteInfo->spriteOwner = FALSE; + + dev->config_info = xf86SetStrOption(pInfo->options, "config_info", NULL); + + if (serverGeneration == 1) + xf86Msg(X_INFO, "XINPUT: Adding extended input device \"%s\" (type: %s)\n", + pInfo->name, pInfo->type_name); + + return dev; +} + +/**************************************************************************** + * + * Caller: ProcXSetDeviceMode + * + * Change the mode of an extension device. + * This function is used to change the mode of a device from reporting + * relative motion to reporting absolute positional information, and + * vice versa. + * The default implementation below is that no such devices are supported. + * + *********************************************************************** + */ + +int +SetDeviceMode (ClientPtr client, DeviceIntPtr dev, int mode) +{ + InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; + + if (pInfo->switch_mode) { + return (*pInfo->switch_mode)(client, dev, mode); + } + else + return BadMatch; +} + + +/*********************************************************************** + * + * Caller: ProcXSetDeviceValuators + * + * Set the value of valuators on an extension input device. + * This function is used to set the initial value of valuators on + * those input devices that are capable of reporting either relative + * motion or an absolute position, and allow an initial position to be set. + * The default implementation below is that no such devices are supported. + * + *********************************************************************** + */ + +int +SetDeviceValuators (ClientPtr client, DeviceIntPtr dev, int *valuators, + int first_valuator, int num_valuators) +{ + InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; + + if (pInfo->set_device_valuators) + return (*pInfo->set_device_valuators)(pInfo, valuators, first_valuator, + num_valuators); + + return BadMatch; +} + + +/*********************************************************************** + * + * Caller: ProcXChangeDeviceControl + * + * Change the specified device controls on an extension input device. + * + *********************************************************************** + */ + +int +ChangeDeviceControl (ClientPtr client, DeviceIntPtr dev, xDeviceCtl *control) +{ + InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; + + if (!pInfo->control_proc) { + switch (control->control) { + case DEVICE_CORE: + case DEVICE_ABS_CALIB: + case DEVICE_ABS_AREA: + return BadMatch; + case DEVICE_RESOLUTION: + case DEVICE_ENABLE: + return Success; + default: + return BadMatch; + } + } + else { + return (*pInfo->control_proc)(pInfo, control); + } +} + +/* + * Get the operating system name from uname and store it statically to avoid + * repeating the system call each time MatchOS is checked. + */ +static const char * +HostOS(void) +{ +#ifdef HAVE_SYS_UTSNAME_H + struct utsname name; + static char host_os[sizeof(name.sysname)] = ""; + + if (*host_os == '\0') { + if (uname(&name) >= 0) + strcpy(host_os, name.sysname); + else { + strncpy(host_os, "unknown", sizeof(host_os)); + host_os[sizeof(host_os)-1] = '\0'; + } + } + return host_os; +#else + return ""; +#endif +} + +static int +match_substring(const char *attr, const char *pattern) +{ + return (strstr(attr, pattern)) ? 0 : -1; +} + +#ifdef HAVE_FNMATCH_H +static int +match_pattern(const char *attr, const char *pattern) +{ + return fnmatch(pattern, attr, 0); +} +#else +#define match_pattern match_substring +#endif + +#ifdef HAVE_FNMATCH_H +static int +match_path_pattern(const char *attr, const char *pattern) +{ + return fnmatch(pattern, attr, FNM_PATHNAME); +} +#else +#define match_path_pattern match_substring +#endif + +/* + * Match an attribute against a list of NULL terminated arrays of patterns. + * If a pattern in each list entry is matched, return TRUE. + */ +static Bool +MatchAttrToken(const char *attr, struct list *patterns, + int (*compare)(const char *attr, const char *pattern)) +{ + const xf86MatchGroup *group; + + /* If there are no patterns, accept the match */ + if (list_is_empty(patterns)) + return TRUE; + + /* If there are patterns but no attribute, reject the match */ + if (!attr) + return FALSE; + + /* + * Otherwise, iterate the list of patterns ensuring each entry has a + * match. Each list entry is a separate Match line of the same type. + */ + list_for_each_entry(group, patterns, entry) { + char * const *cur; + Bool match = FALSE; + + for (cur = group->values; *cur; cur++) + if ((*compare)(attr, *cur) == 0) { + match = TRUE; + break; + } + if (!match) + return FALSE; + } + + /* All the entries in the list matched the attribute */ + return TRUE; +} + +/* + * Classes without any Match statements match all devices. Otherwise, all + * statements must match. + */ +static Bool +InputClassMatches(const XF86ConfInputClassPtr iclass, const InputInfoPtr idev, + const InputAttributes *attrs) +{ + /* MatchProduct substring */ + if (!MatchAttrToken(attrs->product, &iclass->match_product, match_substring)) + return FALSE; + + /* MatchVendor substring */ + if (!MatchAttrToken(attrs->vendor, &iclass->match_vendor, match_substring)) + return FALSE; + + /* MatchDevicePath pattern */ + if (!MatchAttrToken(attrs->device, &iclass->match_device, match_path_pattern)) + return FALSE; + + /* MatchOS case-insensitive string */ + if (!MatchAttrToken(HostOS(), &iclass->match_os, strcasecmp)) + return FALSE; + + /* MatchPnPID pattern */ + if (!MatchAttrToken(attrs->pnp_id, &iclass->match_pnpid, match_pattern)) + return FALSE; + + /* MatchUSBID pattern */ + if (!MatchAttrToken(attrs->usb_id, &iclass->match_usbid, match_pattern)) + return FALSE; + + /* MatchDriver string */ + if (!MatchAttrToken(idev->driver, &iclass->match_driver, strcmp)) + return FALSE; + + /* + * MatchTag string + * See if any of the device's tags match any of the MatchTag tokens. + */ + if (!list_is_empty(&iclass->match_tag)) { + char * const *tag; + Bool match; + + if (!attrs->tags) + return FALSE; + for (tag = attrs->tags, match = FALSE; *tag; tag++) { + if (MatchAttrToken(*tag, &iclass->match_tag, strcmp)) { + match = TRUE; + break; + } + } + if (!match) + return FALSE; + } + + /* MatchIs* booleans */ + if (iclass->is_keyboard.set && + iclass->is_keyboard.val != !!(attrs->flags & ATTR_KEYBOARD)) + return FALSE; + if (iclass->is_pointer.set && + iclass->is_pointer.val != !!(attrs->flags & ATTR_POINTER)) + return FALSE; + if (iclass->is_joystick.set && + iclass->is_joystick.val != !!(attrs->flags & ATTR_JOYSTICK)) + return FALSE; + if (iclass->is_tablet.set && + iclass->is_tablet.val != !!(attrs->flags & ATTR_TABLET)) + return FALSE; + if (iclass->is_touchpad.set && + iclass->is_touchpad.val != !!(attrs->flags & ATTR_TOUCHPAD)) + return FALSE; + if (iclass->is_touchscreen.set && + iclass->is_touchscreen.val != !!(attrs->flags & ATTR_TOUCHSCREEN)) + return FALSE; + + return TRUE; +} + +/* + * Merge in any InputClass configurations. Options in each InputClass + * section have more priority than the original device configuration as + * well as any previous InputClass sections. + */ +static int +MergeInputClasses(const InputInfoPtr idev, const InputAttributes *attrs) +{ + XF86ConfInputClassPtr cl; + XF86OptionPtr classopts; + + for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { + if (!InputClassMatches(cl, idev, attrs)) + continue; + + /* Collect class options and driver settings */ + classopts = xf86optionListDup(cl->option_lst); + if (cl->driver) { + free(idev->driver); + idev->driver = xstrdup(cl->driver); + if (!idev->driver) { + xf86Msg(X_ERROR, "Failed to allocate memory while merging " + "InputClass configuration"); + return BadAlloc; + } + classopts = xf86ReplaceStrOption(classopts, "driver", + idev->driver); + } + + /* Apply options to device with InputClass settings preferred. */ + xf86Msg(X_CONFIG, "%s: Applying InputClass \"%s\"\n", + idev->name, cl->identifier); + idev->options = xf86optionListMerge(idev->options, classopts); + } + + return Success; +} + +/* + * Iterate the list of classes and look for Option "Ignore". Return the + * value of the last matching class and holler when returning TRUE. + */ +static Bool +IgnoreInputClass(const InputInfoPtr idev, const InputAttributes *attrs) +{ + XF86ConfInputClassPtr cl; + Bool ignore = FALSE; + const char *ignore_class; + + for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { + if (!InputClassMatches(cl, idev, attrs)) + continue; + if (xf86findOption(cl->option_lst, "Ignore")) { + ignore = xf86CheckBoolOption(cl->option_lst, "Ignore", FALSE); + ignore_class = cl->identifier; + } + } + + if (ignore) + xf86Msg(X_CONFIG, "%s: Ignoring device from InputClass \"%s\"\n", + idev->name, ignore_class); + return ignore; +} + +InputInfoPtr +xf86AllocateInput(void) +{ + InputInfoPtr pInfo; + + pInfo = calloc(sizeof(*pInfo), 1); + if (!pInfo) + return NULL; + + pInfo->fd = -1; + pInfo->type_name = "UNKNOWN"; + + return pInfo; +} + +/* Append InputInfoRec to the tail of xf86InputDevs. */ +static void +xf86AddInput(InputDriverPtr drv, InputInfoPtr pInfo) +{ + InputInfoPtr *prev = NULL; + + pInfo->drv = drv; + pInfo->module = DuplicateModule(drv->module, NULL); + + for (prev = &xf86InputDevs; *prev; prev = &(*prev)->next) + ; + + *prev = pInfo; + pInfo->next = NULL; + + xf86CollectInputOptions(pInfo, (const char**)drv->default_options); + xf86OptionListReport(pInfo->options); + xf86ProcessCommonOptions(pInfo, pInfo->options); +} + +/* + * Remove an entry from xf86InputDevs and free all the device's information. + */ +void +xf86DeleteInput(InputInfoPtr pInp, int flags) +{ + /* First check if the inputdev is valid. */ + if (pInp == NULL) + return; + + if (pInp->module) + UnloadModule(pInp->module); + + /* This should *really* be handled in drv->UnInit(dev) call instead, but + * if the driver forgets about it make sure we free it or at least crash + * with flying colors */ + free(pInp->private); + + FreeInputAttributes(pInp->attrs); + + /* Remove the entry from the list. */ + if (pInp == xf86InputDevs) + xf86InputDevs = pInp->next; + else { + InputInfoPtr p = xf86InputDevs; + while (p && p->next != pInp) + p = p->next; + if (p) + p->next = pInp->next; + /* Else the entry wasn't in the xf86InputDevs list (ignore this). */ + } + + free(pInp->driver); + free(pInp->name); + xf86optionListFree(pInp->options); + free(pInp); +} + +/* + * Apply backend-specific initialization. Invoked after ActiveteDevice(), + * i.e. after the driver successfully completed DEVICE_INIT and the device + * is advertised. + * @param dev the device + * @return Success or an error code + */ +static int +xf86InputDevicePostInit(DeviceIntPtr dev) { + ApplyAccelerationSettings(dev); + return Success; +} + +/** + * Create a new input device, activate and enable it. + * + * Possible return codes: + * BadName .. a bad driver name was supplied. + * BadImplementation ... The driver does not have a PreInit function. This + * is a driver bug. + * BadMatch .. device initialization failed. + * BadAlloc .. too many input devices + * + * @param idev The device, already set up with identifier, driver, and the + * options. + * @param pdev Pointer to the new device, if Success was reported. + * @param enable Enable the device after activating it. + * + * @return Success or an error code + */ +_X_INTERNAL int +xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable) +{ + InputDriverPtr drv = NULL; + DeviceIntPtr dev = NULL; + int rval; + + /* Memory leak for every attached device if we don't + * test if the module is already loaded first */ + drv = xf86LookupInputDriver(pInfo->driver); + if (!drv) + if (xf86LoadOneModule(pInfo->driver, NULL)) + drv = xf86LookupInputDriver(pInfo->driver); + if (!drv) { + xf86Msg(X_ERROR, "No input driver matching `%s'\n", pInfo->driver); + rval = BadName; + goto unwind; + } + + xf86Msg(X_INFO, "Using input driver '%s' for '%s'\n", drv->driverName, pInfo->name); + + if (!drv->PreInit) { + xf86Msg(X_ERROR, + "Input driver `%s' has no PreInit function (ignoring)\n", + drv->driverName); + rval = BadImplementation; + goto unwind; + } + + xf86AddInput(drv, pInfo); + + rval = drv->PreInit(drv, pInfo, 0); + + if (rval != Success) { + xf86Msg(X_ERROR, "PreInit returned %d for \"%s\"\n", rval, pInfo->name); + goto unwind; + } + + if (!(dev = xf86ActivateDevice(pInfo))) + { + rval = BadAlloc; + goto unwind; + } + + rval = ActivateDevice(dev, TRUE); + if (rval != Success) + { + xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); + RemoveDevice(dev, TRUE); + goto unwind; + } + + rval = xf86InputDevicePostInit(dev); + if (rval != Success) + { + xf86Msg(X_ERROR, "Couldn't post-init device \"%s\"\n", pInfo->name); + RemoveDevice(dev, TRUE); + goto unwind; + } + + /* Enable it if it's properly initialised and we're currently in the VT */ + if (enable && dev->inited && dev->startup && xf86Screens[0]->vtSema) + { + OsBlockSignals(); + EnableDevice(dev, TRUE); + if (!dev->enabled) + { + OsReleaseSignals(); + xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); + rval = BadMatch; + goto unwind; + } + /* send enter/leave event, update sprite window */ + CheckMotion(NULL, dev); + OsReleaseSignals(); + } + + *pdev = dev; + return Success; + +unwind: + if(pInfo) { + if(drv && drv->UnInit) + drv->UnInit(drv, pInfo, 0); + else + xf86DeleteInput(pInfo, 0); + } + return rval; +} + +int +NewInputDeviceRequest (InputOption *options, InputAttributes *attrs, + DeviceIntPtr *pdev) +{ + InputInfoPtr pInfo = NULL; + InputOption *option = NULL; + int rval = Success; + int is_auto = 0; + + pInfo = xf86AllocateInput(); + if (!pInfo) + return BadAlloc; + + for (option = options; option; option = option->next) { + if (strcasecmp(option->key, "driver") == 0) { + if (pInfo->driver) { + rval = BadRequest; + goto unwind; + } + pInfo->driver = xstrdup(option->value); + if (!pInfo->driver) { + rval = BadAlloc; + goto unwind; + } + } + + if (strcasecmp(option->key, "name") == 0 || + strcasecmp(option->key, "identifier") == 0) { + if (pInfo->name) { + rval = BadRequest; + goto unwind; + } + pInfo->name = xstrdup(option->value); + if (!pInfo->name) { + rval = BadAlloc; + goto unwind; + } + } + + if (strcmp(option->key, "_source") == 0 && + (strcmp(option->value, "server/hal") == 0 || + strcmp(option->value, "server/udev") == 0)) { + is_auto = 1; + if (!xf86Info.autoAddDevices) { + rval = BadMatch; + goto unwind; + } + } + } + + for (option = options; option; option = option->next) { + /* Steal option key/value strings from the provided list. + * We need those strings, the InputOption list doesn't. */ + pInfo->options = xf86addNewOption(pInfo->options, + option->key, option->value); + option->key = NULL; + option->value = NULL; + } + + /* Apply InputClass settings */ + if (attrs) { + if (IgnoreInputClass(pInfo, attrs)) { + rval = BadIDChoice; + goto unwind; + } + + rval = MergeInputClasses(pInfo, attrs); + if (rval != Success) + goto unwind; + + pInfo->attrs = DuplicateInputAttributes(attrs); + } + + if (!pInfo->driver || !pInfo->name) { + xf86Msg(X_INFO, "No input driver/identifier specified (ignoring)\n"); + rval = BadRequest; + goto unwind; + } + + if (!pInfo->name) { + xf86Msg(X_ERROR, "No device identifier specified (ignoring)\n"); + rval = BadMatch; + goto unwind; + } + + rval = xf86NewInputDevice(pInfo, pdev, + (!is_auto || (is_auto && xf86Info.autoEnableDevices))); + + return rval; + +unwind: + if (is_auto && !xf86Info.autoAddDevices) + xf86Msg(X_INFO, "AutoAddDevices is off - not adding device.\n"); + xf86DeleteInput(pInfo, 0); + return rval; +} + +void +DeleteInputDeviceRequest(DeviceIntPtr pDev) +{ + InputInfoPtr pInfo = (InputInfoPtr) pDev->public.devicePrivate; + InputDriverPtr drv = NULL; + Bool isMaster = IsMaster(pDev); + + if (pInfo) /* need to get these before RemoveDevice */ + drv = pInfo->drv; + + OsBlockSignals(); + RemoveDevice(pDev, TRUE); + + if (!isMaster && pInfo != NULL) + { + if(drv->UnInit) + drv->UnInit(drv, pInfo, 0); + else + xf86DeleteInput(pInfo, 0); + } + OsReleaseSignals(); +} + +/* + * convenient functions to post events + */ + +void +xf86PostMotionEvent(DeviceIntPtr device, + int is_absolute, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + int i = 0; + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_zero(&mask); + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); + va_end(var); + + xf86PostMotionEventM(device, is_absolute, &mask); +} + +void +xf86PostMotionEventP(DeviceIntPtr device, + int is_absolute, + int first_valuator, + int num_valuators, + const int *valuators) +{ + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); + xf86PostMotionEventM(device, is_absolute, &mask); +} + +void +xf86PostMotionEventM(DeviceIntPtr device, + int is_absolute, + const ValuatorMask *mask) +{ + int i = 0, nevents = 0; + DeviceEvent *event; + int flags = 0; + + if (valuator_mask_num_valuators(mask) > 0) + { + if (is_absolute) + flags = POINTER_ABSOLUTE; + else + flags = POINTER_RELATIVE | POINTER_ACCELERATE; + } + +#if XFreeXDGA + /* The evdev driver may not always send all axes across. */ + if (valuator_mask_isset(mask, 0) || + valuator_mask_isset(mask, 1)) + if (miPointerGetScreen(device)) { + int index = miPointerGetScreen(device)->myNum; + int dx = 0, dy = 0; + + if (valuator_mask_isset(mask, 0)) + { + dx = valuator_mask_get(mask, 0); + if (is_absolute) + dx -= device->last.valuators[0]; + } + + if (valuator_mask_isset(mask, 1)) + { + dy = valuator_mask_get(mask, 1); + if (is_absolute) + dy -= device->last.valuators[1]; + } + + if (DGAStealMotionEvent(device, index, dx, dy)) + return; + } +#endif + + nevents = GetPointerEvents(xf86Events, device, MotionNotify, 0, flags, mask); + + for (i = 0; i < nevents; i++) { + event = (DeviceEvent*)((xf86Events + i)->event); + mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); + } +} + +void +xf86PostProximityEvent(DeviceIntPtr device, + int is_in, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + int i; + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_zero(&mask); + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); + va_end(var); + + xf86PostProximityEventM(device, is_in, &mask); +} + +void +xf86PostProximityEventP(DeviceIntPtr device, + int is_in, + int first_valuator, + int num_valuators, + const int *valuators) +{ + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); + xf86PostProximityEventM(device, is_in, &mask); +} + +void +xf86PostProximityEventM(DeviceIntPtr device, + int is_in, + const ValuatorMask *mask) +{ + int i, nevents; + + nevents = GetProximityEvents(xf86Events, device, + is_in ? ProximityIn : ProximityOut, mask); + for (i = 0; i < nevents; i++) + mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); + +} + +void +xf86PostButtonEvent(DeviceIntPtr device, + int is_absolute, + int button, + int is_down, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + ValuatorMask mask; + int i = 0; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_zero(&mask); + + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); + va_end(var); + + xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); +} + +void +xf86PostButtonEventP(DeviceIntPtr device, + int is_absolute, + int button, + int is_down, + int first_valuator, + int num_valuators, + const int *valuators) +{ + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); + xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); +} + +void +xf86PostButtonEventM(DeviceIntPtr device, + int is_absolute, + int button, + int is_down, + const ValuatorMask *mask) +{ + int i = 0, nevents = 0; + int flags = 0; + + if (valuator_mask_num_valuators(mask) > 0) + { + if (is_absolute) + flags = POINTER_ABSOLUTE; + else + flags = POINTER_RELATIVE | POINTER_ACCELERATE; + } + +#if XFreeXDGA + if (miPointerGetScreen(device)) { + int index = miPointerGetScreen(device)->myNum; + + if (DGAStealButtonEvent(device, index, button, is_down)) + return; + } +#endif + + nevents = GetPointerEvents(xf86Events, device, + is_down ? ButtonPress : ButtonRelease, button, + flags, mask); + + for (i = 0; i < nevents; i++) + mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); + +} + +void +xf86PostKeyEvent(DeviceIntPtr device, + unsigned int key_code, + int is_down, + int is_absolute, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + int i = 0; + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_zero(&mask); + + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); + va_end(var); + + xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask); +} + +void +xf86PostKeyEventP(DeviceIntPtr device, + unsigned int key_code, + int is_down, + int is_absolute, + int first_valuator, + int num_valuators, + const int *valuators) +{ + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); + xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask); +} + +void +xf86PostKeyEventM(DeviceIntPtr device, + unsigned int key_code, + int is_down, + int is_absolute, + const ValuatorMask *mask) +{ + int i = 0, nevents = 0; + +#if XFreeXDGA + DeviceIntPtr pointer; + + /* Some pointers send key events, paired device is wrong then. */ + pointer = IsPointerDevice(device) ? device : GetPairedDevice(device); + if (miPointerGetScreen(pointer)) { + int index = miPointerGetScreen(pointer)->myNum; + + if (DGAStealKeyEvent(device, index, key_code, is_down)) + return; + } +#endif + + if (is_absolute) { + nevents = GetKeyboardValuatorEvents(xf86Events, device, + is_down ? KeyPress : KeyRelease, + key_code, mask); + } + else { + nevents = GetKeyboardEvents(xf86Events, device, + is_down ? KeyPress : KeyRelease, + key_code); + } + + for (i = 0; i < nevents; i++) + mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); +} + +void +xf86PostKeyboardEvent(DeviceIntPtr device, + unsigned int key_code, + int is_down) +{ + ValuatorMask mask; + + valuator_mask_zero(&mask); + xf86PostKeyEventM(device, key_code, is_down, 0, &mask); +} + +InputInfoPtr +xf86FirstLocalDevice(void) +{ + return xf86InputDevs; +} + +/* + * Cx - raw data from touch screen + * to_max - scaled highest dimension + * (remember, this is of rows - 1 because of 0 origin) + * to_min - scaled lowest dimension + * from_max - highest raw value from touch screen calibration + * from_min - lowest raw value from touch screen calibration + * + * This function is the same for X or Y coordinates. + * You may have to reverse the high and low values to compensate for + * different orgins on the touch screen vs X. + * + * e.g. to scale from device coordinates into screen coordinates, call + * xf86ScaleAxis(x, 0, screen_width, dev_min, dev_max); + */ + +int +xf86ScaleAxis(int Cx, + int to_max, + int to_min, + int from_max, + int from_min ) +{ + int X; + int64_t to_width = to_max - to_min; + int64_t from_width = from_max - from_min; + + if (from_width) { + X = (int)(((to_width * (Cx - from_min)) / from_width) + to_min); + } + else { + X = 0; + ErrorF ("Divide by Zero in xf86ScaleAxis\n"); + } + + if (X > to_max) + X = to_max; + if (X < to_min) + X = to_min; + + return X; +} + +/* + * This function checks the given screen against the current screen and + * makes changes if appropriate. It should be called from an XInput driver's + * ReadInput function before any events are posted, if the device is screen + * specific like a touch screen. + */ +void +xf86XInputSetScreen(InputInfoPtr pInfo, + int screen_number, + int x, + int y) +{ + if (miPointerGetScreen(pInfo->dev) != + screenInfo.screens[screen_number]) { + miPointerSetScreen(pInfo->dev, screen_number, x, y); + } +} + + +void +xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval, + int resolution, int min_res, int max_res, int mode) +{ + if (!dev || !dev->valuator) + return; + + InitValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution, min_res, + max_res, mode); +} + +/* + * Set the valuator values to be in synch with dix/event.c + * DefineInitialRootWindow(). + */ +void +xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum) +{ + if (axnum == 0) { + dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; + dev->last.valuators[0] = dev->valuator->axisVal[0]; + } + else if (axnum == 1) { + dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; + dev->last.valuators[1] = dev->valuator->axisVal[1]; + } +} + + +/** + * Deactivate a device. Call this function from the driver if you receive a + * read error or something else that spoils your day. + * Device will be moved to the off_devices list, but it will still be there + * until you really clean up after it. + * Notifies the client about an inactive device. + * + * @param panic True if device is unrecoverable and needs to be removed. + */ +void +xf86DisableDevice(DeviceIntPtr dev, Bool panic) +{ + if(!panic) + { + DisableDevice(dev, TRUE); + } else + { + SendDevicePresenceEvent(dev->id, DeviceUnrecoverable); + DeleteInputDeviceRequest(dev); + } +} + +/** + * Reactivate a device. Call this function from the driver if you just found + * out that the read error wasn't quite that bad after all. + * Device will be re-activated, and an event sent to the client. + */ +void +xf86EnableDevice(DeviceIntPtr dev) +{ + EnableDevice(dev, TRUE); +} + +/* end of xf86Xinput.c */ diff --git a/xorg-server/hw/xfree86/dri/dri.c b/xorg-server/hw/xfree86/dri/dri.c index 38241f904..bb5482a0b 100644 --- a/xorg-server/hw/xfree86/dri/dri.c +++ b/xorg-server/hw/xfree86/dri/dri.c @@ -1,2502 +1,2498 @@ -/**************************************************************************
-
-Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
-Copyright 2000 VA Linux Systems, 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, sub license, 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:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
-IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
-ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-/*
- * Authors:
- * Jens Owen <jens@tungstengraphics.com>
- * Rickard E. (Rik) Faith <faith@valinux.com>
- *
- */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include "xf86.h"
-#include <sys/time.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdio.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "xf86drm.h"
-#include "misc.h"
-#include "dixstruct.h"
-#include "extnsionst.h"
-#include "colormapst.h"
-#include "cursorstr.h"
-#include "scrnintstr.h"
-#include "windowstr.h"
-#include "servermd.h"
-#define _XF86DRI_SERVER_
-#include <X11/dri/xf86driproto.h>
-#include "swaprep.h"
-#include "xf86str.h"
-#include "dri.h"
-#include "sarea.h"
-#include "dristruct.h"
-#include "xf86.h"
-#include "xf86drm.h"
-#include "mi.h"
-#include "mipointer.h"
-#include "xf86_OSproc.h"
-#include "inputstr.h"
-#include "xf86VGAarbiter.h"
-
-static int DRIEntPrivIndex = -1;
-static DevPrivateKeyRec DRIScreenPrivKeyRec;
-#define DRIScreenPrivKey (&DRIScreenPrivKeyRec)
-static DevPrivateKeyRec DRIWindowPrivKeyRec;
-#define DRIWindowPrivKey (&DRIWindowPrivKeyRec)
-static unsigned long DRIGeneration = 0;
-static unsigned int DRIDrawableValidationStamp = 0;
-
-static RESTYPE DRIDrawablePrivResType;
-static RESTYPE DRIContextPrivResType;
-static void DRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv);
-
-drmServerInfo DRIDRMServerInfo;
-
- /* Wrapper just like xf86DrvMsg, but
- without the verbosity level checking.
- This will make it easy to turn off some
- messages later, based on verbosity
- level. */
-
-/*
- * Since we're already referencing things from the XFree86 common layer in
- * this file, we'd might as well just call xf86VDrvMsgVerb, and have
- * consistent message formatting. The verbosity of these messages can be
- * easily changed here.
- */
-#define DRI_MSG_VERBOSITY 1
-static void
-DRIDrvMsg(int scrnIndex, MessageType type, const char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- xf86VDrvMsgVerb(scrnIndex, type, DRI_MSG_VERBOSITY, format, ap);
- va_end(ap);
-}
-
-
-static void
-DRIOpenDRMCleanup(DRIEntPrivPtr pDRIEntPriv)
-{
- if (pDRIEntPriv->pLSAREA != NULL) {
- drmUnmap(pDRIEntPriv->pLSAREA, pDRIEntPriv->sAreaSize);
- pDRIEntPriv->pLSAREA = NULL;
- }
- if (pDRIEntPriv->hLSAREA != 0) {
- drmRmMap(pDRIEntPriv->drmFD, pDRIEntPriv->hLSAREA);
- }
- if (pDRIEntPriv->drmFD >= 0) {
- drmClose(pDRIEntPriv->drmFD);
- pDRIEntPriv->drmFD = 0;
- }
-}
-
-int
-DRIMasterFD(ScrnInfoPtr pScrn)
-{
- return DRI_ENT_PRIV(pScrn)->drmFD;
-}
-
-void *
-DRIMasterSareaPointer(ScrnInfoPtr pScrn)
-{
- return DRI_ENT_PRIV(pScrn)->pLSAREA;
-}
-
-drm_handle_t
-DRIMasterSareaHandle(ScrnInfoPtr pScrn)
-{
- return DRI_ENT_PRIV(pScrn)->hLSAREA;
-}
-
-
-Bool
-DRIOpenDRMMaster(ScrnInfoPtr pScrn,
- unsigned long sAreaSize,
- const char *busID,
- const char *drmDriverName)
-{
- drmSetVersion saveSv, sv;
- Bool drmWasAvailable;
- DRIEntPrivPtr pDRIEntPriv;
- DRIEntPrivRec tmp;
- drmVersionPtr drmlibv;
- int drmlibmajor, drmlibminor;
- const char *openBusID;
- int count;
- int err;
-
- if (DRIEntPrivIndex == -1)
- DRIEntPrivIndex = xf86AllocateEntityPrivateIndex();
-
- pDRIEntPriv = DRI_ENT_PRIV(pScrn);
-
- if (pDRIEntPriv && pDRIEntPriv->drmFD != -1)
- return TRUE;
-
- drmWasAvailable = drmAvailable();
-
- memset(&tmp, 0, sizeof(tmp));
-
- /* Check the DRM lib version.
- * drmGetLibVersion was not supported in version 1.0, so check for
- * symbol first to avoid possible crash or hang.
- */
-
- drmlibmajor = 1;
- drmlibminor = 0;
- if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
- drmlibv = drmGetLibVersion(-1);
- if (drmlibv != NULL) {
- drmlibmajor = drmlibv->version_major;
- drmlibminor = drmlibv->version_minor;
- drmFreeVersion(drmlibv);
- }
- }
-
- /* Check if the libdrm can handle falling back to loading based on name
- * if a busid string is passed.
- */
- openBusID = (drmlibmajor == 1 && drmlibminor >= 2) ? busID : NULL;
-
- tmp.drmFD = -1;
- sv.drm_di_major = 1;
- sv.drm_di_minor = 1;
- sv.drm_dd_major = -1;
-
- saveSv = sv;
- count = 10;
- while (count--) {
- tmp.drmFD = drmOpen(drmDriverName, openBusID);
-
- if (tmp.drmFD < 0) {
- DRIDrvMsg(-1, X_ERROR, "[drm] drmOpen failed.\n");
- goto out_err;
- }
-
- err = drmSetInterfaceVersion(tmp.drmFD, &sv);
-
- if (err != -EPERM)
- break;
-
- sv = saveSv;
- drmClose(tmp.drmFD);
- tmp.drmFD = -1;
- usleep(100000);
- }
-
- if (tmp.drmFD <= 0) {
- DRIDrvMsg(-1, X_ERROR, "[drm] DRM was busy with another master.\n");
- goto out_err;
- }
-
- if (!drmWasAvailable) {
- DRIDrvMsg(-1, X_INFO,
- "[drm] loaded kernel module for \"%s\" driver.\n",
- drmDriverName);
- }
-
- if (err != 0) {
- sv.drm_di_major = 1;
- sv.drm_di_minor = 0;
- }
-
- DRIDrvMsg(-1, X_INFO, "[drm] DRM interface version %d.%d\n",
- sv.drm_di_major, sv.drm_di_minor);
-
- if (sv.drm_di_major == 1 && sv.drm_di_minor >= 1)
- err = 0;
- else
- err = drmSetBusid(tmp.drmFD, busID);
-
- if (err) {
- DRIDrvMsg(-1, X_ERROR, "[drm] Could not set DRM device bus ID.\n");
- goto out_err;
- }
-
- /*
- * Create a lock-containing sarea.
- */
-
- if (drmAddMap( tmp.drmFD, 0, sAreaSize, DRM_SHM,
- DRM_CONTAINS_LOCK, &tmp.hLSAREA) < 0) {
- DRIDrvMsg(-1, X_INFO, "[drm] Could not create SAREA for DRM lock.\n");
- tmp.hLSAREA = 0;
- goto out_err;
- }
-
- if (drmMap( tmp.drmFD, tmp.hLSAREA, sAreaSize,
- (drmAddressPtr)(&tmp.pLSAREA)) < 0) {
- DRIDrvMsg(-1, X_INFO, "[drm] Mapping SAREA for DRM lock failed.\n");
- tmp.pLSAREA = NULL;
- goto out_err;
- }
-
- memset(tmp.pLSAREA, 0, sAreaSize);
-
- /*
- * Reserved contexts are handled by the first opened screen.
- */
-
- tmp.resOwner = NULL;
-
- if (!pDRIEntPriv)
- pDRIEntPriv = xnfcalloc(sizeof(*pDRIEntPriv), 1);
-
- if (!pDRIEntPriv) {
- DRIDrvMsg(-1, X_INFO, "[drm] Failed to allocate memory for "
- "DRM device.\n");
- goto out_err;
- }
- *pDRIEntPriv = tmp;
- xf86GetEntityPrivate((pScrn)->entityList[0],DRIEntPrivIndex)->ptr =
- pDRIEntPriv;
-
- DRIDrvMsg(-1, X_INFO, "[drm] DRM open master succeeded.\n");
- return TRUE;
-
- out_err:
-
- DRIOpenDRMCleanup(&tmp);
- return FALSE;
-}
-
-static void
-DRIClipNotifyAllDrawables(ScreenPtr pScreen);
-
-static void
-dri_crtc_notify(ScreenPtr pScreen)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- DRIClipNotifyAllDrawables(pScreen);
- xf86_unwrap_crtc_notify(pScreen, pDRIPriv->xf86_crtc_notify);
- xf86_crtc_notify(pScreen);
- pDRIPriv->xf86_crtc_notify = xf86_wrap_crtc_notify(pScreen, dri_crtc_notify);
-}
-
-Bool
-DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD)
-{
- DRIScreenPrivPtr pDRIPriv;
- drm_context_t * reserved;
- int reserved_count;
- int i;
- DRIEntPrivPtr pDRIEntPriv;
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- DRIContextFlags flags = 0;
- DRIContextPrivPtr pDRIContextPriv;
-
- /* If the DRI extension is disabled, do not initialize the DRI */
- if (noXFree86DRIExtension) {
- DRIDrvMsg(pScreen->myNum, X_WARNING,
- "Direct rendering has been disabled.\n");
- return FALSE;
- }
-
- if (!xf86VGAarbiterAllowDRI(pScreen)) {
- DRIDrvMsg(pScreen->myNum, X_WARNING,
- "Direct rendering is not supported when VGA arb is necessary for the device\n");
- return FALSE;
- }
-
-#ifdef PANORAMIX
- /*
- * If Xinerama is on, don't allow DRI to initialise. It won't be usable
- * anyway.
- */
- if (!noPanoramiXExtension) {
- DRIDrvMsg(pScreen->myNum, X_WARNING,
- "Direct rendering is not supported when Xinerama is enabled\n");
- return FALSE;
- }
-#endif
-
- if (!DRIOpenDRMMaster(pScrn, pDRIInfo->SAREASize,
- pDRIInfo->busIdString,
- pDRIInfo->drmDriverName))
- return FALSE;
-
- pDRIEntPriv = DRI_ENT_PRIV(pScrn);
-
- if (DRIGeneration != serverGeneration)
- DRIGeneration = serverGeneration;
-
- if (!dixRegisterPrivateKey(&DRIScreenPrivKeyRec, PRIVATE_SCREEN, 0))
- return FALSE;
- if (!dixRegisterPrivateKey(&DRIWindowPrivKeyRec, PRIVATE_WINDOW, 0))
- return FALSE;
-
- pDRIPriv = (DRIScreenPrivPtr) calloc(1, sizeof(DRIScreenPrivRec));
- if (!pDRIPriv) {
- dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
- return FALSE;
- }
-
- dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, pDRIPriv);
- pDRIPriv->drmFD = pDRIEntPriv->drmFD;
- pDRIPriv->directRenderingSupport = TRUE;
- pDRIPriv->pDriverInfo = pDRIInfo;
- pDRIPriv->nrWindows = 0;
- pDRIPriv->nrWindowsVisible = 0;
- pDRIPriv->fullscreen = NULL;
-
- pDRIPriv->createDummyCtx = pDRIInfo->createDummyCtx;
- pDRIPriv->createDummyCtxPriv = pDRIInfo->createDummyCtxPriv;
-
- pDRIPriv->grabbedDRILock = FALSE;
- pDRIPriv->drmSIGIOHandlerInstalled = FALSE;
- *pDRMFD = pDRIPriv->drmFD;
-
- if (pDRIEntPriv->sAreaGrabbed || pDRIInfo->allocSarea) {
-
- if (drmAddMap( pDRIPriv->drmFD,
- 0,
- pDRIPriv->pDriverInfo->SAREASize,
- DRM_SHM,
- 0,
- &pDRIPriv->hSAREA) < 0)
- {
- pDRIPriv->directRenderingSupport = FALSE;
- dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
- drmClose(pDRIPriv->drmFD);
- DRIDrvMsg(pScreen->myNum, X_INFO,
- "[drm] drmAddMap failed\n");
- return FALSE;
- }
- DRIDrvMsg(pScreen->myNum, X_INFO,
- "[drm] added %d byte SAREA at %p\n",
- pDRIPriv->pDriverInfo->SAREASize, pDRIPriv->hSAREA);
-
- /* Backwards compat. */
- if (drmMap( pDRIPriv->drmFD,
- pDRIPriv->hSAREA,
- pDRIPriv->pDriverInfo->SAREASize,
- (drmAddressPtr)(&pDRIPriv->pSAREA)) < 0)
- {
- pDRIPriv->directRenderingSupport = FALSE;
- dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
- drmClose(pDRIPriv->drmFD);
- DRIDrvMsg(pScreen->myNum, X_INFO,
- "[drm] drmMap failed\n");
- return FALSE;
- }
- DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] mapped SAREA %p to %p\n",
- pDRIPriv->hSAREA, pDRIPriv->pSAREA);
- memset(pDRIPriv->pSAREA, 0, pDRIPriv->pDriverInfo->SAREASize);
- } else {
- DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] Using the DRM lock "
- "SAREA also for drawables.\n");
- pDRIPriv->hSAREA = pDRIEntPriv->hLSAREA;
- pDRIPriv->pSAREA = (XF86DRISAREAPtr) pDRIEntPriv->pLSAREA;
- pDRIEntPriv->sAreaGrabbed = TRUE;
- }
-
- pDRIPriv->hLSAREA = pDRIEntPriv->hLSAREA;
- pDRIPriv->pLSAREA = pDRIEntPriv->pLSAREA;
-
- if (!pDRIPriv->pDriverInfo->dontMapFrameBuffer)
- {
- if (drmAddMap( pDRIPriv->drmFD,
- (uintptr_t)pDRIPriv->pDriverInfo->frameBufferPhysicalAddress,
- pDRIPriv->pDriverInfo->frameBufferSize,
- DRM_FRAME_BUFFER,
- 0,
- &pDRIPriv->pDriverInfo->hFrameBuffer) < 0)
- {
- pDRIPriv->directRenderingSupport = FALSE;
- dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
- drmUnmap(pDRIPriv->pSAREA, pDRIPriv->pDriverInfo->SAREASize);
- drmClose(pDRIPriv->drmFD);
- DRIDrvMsg(pScreen->myNum, X_INFO,
- "[drm] drmAddMap failed\n");
- return FALSE;
- }
- DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] framebuffer handle = %p\n",
- pDRIPriv->pDriverInfo->hFrameBuffer);
- } else {
- DRIDrvMsg(pScreen->myNum, X_INFO,
- "[drm] framebuffer mapped by ddx driver\n");
- }
-
- if (pDRIEntPriv->resOwner == NULL) {
- pDRIEntPriv->resOwner = pScreen;
-
- /* Add tags for reserved contexts */
- if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD,
- &reserved_count))) {
- int i;
- void *tag;
-
- for (i = 0; i < reserved_count; i++) {
- tag = DRICreateContextPrivFromHandle(pScreen,
- reserved[i],
- DRI_CONTEXT_RESERVED);
- drmAddContextTag(pDRIPriv->drmFD, reserved[i], tag);
- }
- drmFreeReservedContextList(reserved);
- DRIDrvMsg(pScreen->myNum, X_INFO,
- "[drm] added %d reserved context%s for kernel\n",
- reserved_count, reserved_count > 1 ? "s" : "");
- }
- }
-
- /* validate max drawable table entry set by driver */
- if ((pDRIPriv->pDriverInfo->maxDrawableTableEntry <= 0) ||
- (pDRIPriv->pDriverInfo->maxDrawableTableEntry > SAREA_MAX_DRAWABLES)) {
- DRIDrvMsg(pScreen->myNum, X_ERROR,
- "Invalid max drawable table size set by driver: %d\n",
- pDRIPriv->pDriverInfo->maxDrawableTableEntry);
- }
-
- /* Initialize drawable tables (screen private and SAREA) */
- for( i=0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) {
- pDRIPriv->DRIDrawables[i] = NULL;
- pDRIPriv->pSAREA->drawableTable[i].stamp = 0;
- pDRIPriv->pSAREA->drawableTable[i].flags = 0;
- }
-
- pDRIPriv->pLockRefCount = &pDRIEntPriv->lockRefCount;
- pDRIPriv->pLockingContext = &pDRIEntPriv->lockingContext;
-
- if (!pDRIEntPriv->keepFDOpen)
- pDRIEntPriv->keepFDOpen = pDRIInfo->keepFDOpen;
-
- pDRIEntPriv->refCount++;
-
- /* Set up flags for DRICreateContextPriv */
- switch (pDRIInfo->driverSwapMethod) {
- case DRI_KERNEL_SWAP:
- flags = DRI_CONTEXT_2DONLY;
- break;
- case DRI_HIDE_X_CONTEXT:
- flags = DRI_CONTEXT_PRESERVED;
- break;
- }
-
- if (!(pDRIContextPriv = DRICreateContextPriv(pScreen,
- &pDRIPriv->myContext,
- flags))) {
- DRIDrvMsg(pScreen->myNum, X_ERROR,
- "failed to create server context\n");
- return FALSE;
- }
- pDRIPriv->myContextPriv = pDRIContextPriv;
-
- DRIDrvMsg(pScreen->myNum, X_INFO,
- "X context handle = %p\n", pDRIPriv->myContext);
-
- /* Now that we have created the X server's context, we can grab the
- * hardware lock for the X server.
- */
- DRILock(pScreen, 0);
- pDRIPriv->grabbedDRILock = TRUE;
-
- /* pointers so that we can prevent memory leaks later */
- pDRIPriv->hiddenContextStore = NULL;
- pDRIPriv->partial3DContextStore = NULL;
-
- switch(pDRIInfo->driverSwapMethod) {
- case DRI_HIDE_X_CONTEXT:
- /* Server will handle 3D swaps, and hide 2D swaps from kernel.
- * Register server context as a preserved context.
- */
-
- /* allocate memory for hidden context store */
- pDRIPriv->hiddenContextStore
- = (void *)calloc(1, pDRIInfo->contextSize);
- if (!pDRIPriv->hiddenContextStore) {
- DRIDrvMsg(pScreen->myNum, X_ERROR,
- "failed to allocate hidden context\n");
- DRIDestroyContextPriv(pDRIContextPriv);
- return FALSE;
- }
-
- /* allocate memory for partial 3D context store */
- pDRIPriv->partial3DContextStore
- = (void *)calloc(1, pDRIInfo->contextSize);
- if (!pDRIPriv->partial3DContextStore) {
- DRIDrvMsg(pScreen->myNum, X_ERROR,
- "[DRI] failed to allocate partial 3D context\n");
- free(pDRIPriv->hiddenContextStore);
- DRIDestroyContextPriv(pDRIContextPriv);
- return FALSE;
- }
-
- /* save initial context store */
- if (pDRIInfo->SwapContext) {
- (*pDRIInfo->SwapContext)(
- pScreen,
- DRI_NO_SYNC,
- DRI_2D_CONTEXT,
- pDRIPriv->hiddenContextStore,
- DRI_NO_CONTEXT,
- NULL);
- }
- /* fall through */
-
- case DRI_SERVER_SWAP:
- /* For swap methods of DRI_SERVER_SWAP and DRI_HIDE_X_CONTEXT
- * setup signal handler for receiving swap requests from kernel
- */
- if (!(pDRIPriv->drmSIGIOHandlerInstalled =
- drmInstallSIGIOHandler(pDRIPriv->drmFD, DRISwapContext))) {
- DRIDrvMsg(pScreen->myNum, X_ERROR,
- "[drm] failed to setup DRM signal handler\n");
- free(pDRIPriv->hiddenContextStore);
- free(pDRIPriv->partial3DContextStore);
- DRIDestroyContextPriv(pDRIContextPriv);
- return FALSE;
- } else {
- DRIDrvMsg(pScreen->myNum, X_INFO,
- "[drm] installed DRM signal handler\n");
- }
-
- default:
- break;
- }
-
- return TRUE;
-}
-
-Bool
-DRIFinishScreenInit(ScreenPtr pScreen)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo;
-
- /* Wrap DRI support */
- if (pDRIInfo->wrap.ValidateTree) {
- pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree;
- pScreen->ValidateTree = pDRIInfo->wrap.ValidateTree;
- }
- if (pDRIInfo->wrap.PostValidateTree) {
- pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree;
- pScreen->PostValidateTree = pDRIInfo->wrap.PostValidateTree;
- }
- if (pDRIInfo->wrap.WindowExposures) {
- pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures;
- pScreen->WindowExposures = pDRIInfo->wrap.WindowExposures;
- }
-
- pDRIPriv->DestroyWindow = pScreen->DestroyWindow;
- pScreen->DestroyWindow = DRIDestroyWindow;
-
- pDRIPriv->xf86_crtc_notify = xf86_wrap_crtc_notify(pScreen,
- dri_crtc_notify);
-
- if (pDRIInfo->wrap.CopyWindow) {
- pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow;
- pScreen->CopyWindow = pDRIInfo->wrap.CopyWindow;
- }
- if (pDRIInfo->wrap.ClipNotify) {
- pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify;
- pScreen->ClipNotify = pDRIInfo->wrap.ClipNotify;
- }
- if (pDRIInfo->wrap.AdjustFrame) {
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- pDRIPriv->wrap.AdjustFrame = pScrn->AdjustFrame;
- pScrn->AdjustFrame = pDRIInfo->wrap.AdjustFrame;
- }
- pDRIPriv->wrapped = TRUE;
-
- DRIDrvMsg(pScreen->myNum, X_INFO, "[DRI] installation complete\n");
-
- return TRUE;
-}
-
-void
-DRICloseScreen(ScreenPtr pScreen)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- DRIInfoPtr pDRIInfo;
- drm_context_t * reserved;
- int reserved_count;
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- DRIEntPrivPtr pDRIEntPriv = DRI_ENT_PRIV(pScrn);
- Bool closeMaster;
-
- if (pDRIPriv) {
-
- pDRIInfo = pDRIPriv->pDriverInfo;
-
- if (pDRIPriv->wrapped) {
- /* Unwrap DRI Functions */
- if (pDRIInfo->wrap.ValidateTree) {
- pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree;
- pDRIPriv->wrap.ValidateTree = NULL;
- }
- if (pDRIInfo->wrap.PostValidateTree) {
- pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree;
- pDRIPriv->wrap.PostValidateTree = NULL;
- }
- if (pDRIInfo->wrap.WindowExposures) {
- pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures;
- pDRIPriv->wrap.WindowExposures = NULL;
- }
- if (pDRIPriv->DestroyWindow) {
- pScreen->DestroyWindow = pDRIPriv->DestroyWindow;
- pDRIPriv->DestroyWindow = NULL;
- }
-
- xf86_unwrap_crtc_notify(pScreen, pDRIPriv->xf86_crtc_notify);
-
- if (pDRIInfo->wrap.CopyWindow) {
- pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow;
- pDRIPriv->wrap.CopyWindow = NULL;
- }
- if (pDRIInfo->wrap.ClipNotify) {
- pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify;
- pDRIPriv->wrap.ClipNotify = NULL;
- }
- if (pDRIInfo->wrap.AdjustFrame) {
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- pScrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame;
- pDRIPriv->wrap.AdjustFrame = NULL;
- }
-
- pDRIPriv->wrapped = FALSE;
- }
-
- if (pDRIPriv->drmSIGIOHandlerInstalled) {
- if (!drmRemoveSIGIOHandler(pDRIPriv->drmFD)) {
- DRIDrvMsg(pScreen->myNum, X_ERROR,
- "[drm] failed to remove DRM signal handler\n");
- }
- }
-
- if (pDRIPriv->dummyCtxPriv && pDRIPriv->createDummyCtx) {
- DRIDestroyDummyContext(pScreen, pDRIPriv->createDummyCtxPriv);
- }
-
- if (!DRIDestroyContextPriv(pDRIPriv->myContextPriv)) {
- DRIDrvMsg(pScreen->myNum, X_ERROR,
- "failed to destroy server context\n");
- }
-
- /* Remove tags for reserved contexts */
- if (pDRIEntPriv->resOwner == pScreen) {
- pDRIEntPriv->resOwner = NULL;
-
- if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD,
- &reserved_count))) {
- int i;
-
- for (i = 0; i < reserved_count; i++) {
- DRIDestroyContextPriv(drmGetContextTag(pDRIPriv->drmFD,
- reserved[i]));
- }
- drmFreeReservedContextList(reserved);
- DRIDrvMsg(pScreen->myNum, X_INFO,
- "[drm] removed %d reserved context%s for kernel\n",
- reserved_count, reserved_count > 1 ? "s" : "");
- }
- }
-
- /* Make sure signals get unblocked etc. */
- drmUnlock(pDRIPriv->drmFD, pDRIPriv->myContext);
- pDRIPriv->pLockRefCount = NULL;
- closeMaster = (--pDRIEntPriv->refCount == 0) &&
- !pDRIEntPriv->keepFDOpen;
- if (closeMaster || pDRIPriv->hSAREA != pDRIEntPriv->hLSAREA) {
- DRIDrvMsg(pScreen->myNum, X_INFO,
- "[drm] unmapping %d bytes of SAREA %p at %p\n",
- pDRIInfo->SAREASize,
- pDRIPriv->hSAREA,
- pDRIPriv->pSAREA);
- if (drmUnmap(pDRIPriv->pSAREA, pDRIInfo->SAREASize)) {
- DRIDrvMsg(pScreen->myNum, X_ERROR,
- "[drm] unable to unmap %d bytes"
- " of SAREA %p at %p\n",
- pDRIInfo->SAREASize,
- pDRIPriv->hSAREA,
- pDRIPriv->pSAREA);
- }
- } else {
- pDRIEntPriv->sAreaGrabbed = FALSE;
- }
-
- if (closeMaster || (pDRIEntPriv->drmFD != pDRIPriv->drmFD)) {
- drmClose(pDRIPriv->drmFD);
- if (pDRIEntPriv->drmFD == pDRIPriv->drmFD) {
- DRIDrvMsg(pScreen->myNum, X_INFO,
- "[drm] Closed DRM master.\n");
- pDRIEntPriv->drmFD = -1;
- }
- }
-
- free(pDRIPriv);
- dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
- }
-}
-
-#define DRM_MSG_VERBOSITY 3
-
-static int dri_drm_debug_print(const char *format, va_list ap)
-{
- xf86VDrvMsgVerb(-1, X_NONE, DRM_MSG_VERBOSITY, format, ap);
- return 0;
-}
-
-static void dri_drm_get_perms(gid_t *group, mode_t *mode)
-{
- *group = xf86ConfigDRI.group;
- *mode = xf86ConfigDRI.mode;
-}
-
-drmServerInfo DRIDRMServerInfo = {
- dri_drm_debug_print,
- xf86LoadKernelModule,
- dri_drm_get_perms,
-};
-
-Bool
-DRIExtensionInit(void)
-{
- if (DRIGeneration != serverGeneration) {
- return FALSE;
- }
-
- DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete,
- "DRIDrawable");
- DRIContextPrivResType = CreateNewResourceType(DRIContextPrivDelete,
- "DRIContext");
-
- if (!DRIDrawablePrivResType || !DRIContextPrivResType)
- return FALSE;
-
- RegisterBlockAndWakeupHandlers(DRIBlockHandler, DRIWakeupHandler, NULL);
-
- return TRUE;
-}
-
-void
-DRIReset(void)
-{
- /*
- * This stub routine is called when the X Server recycles, resources
- * allocated by DRIExtensionInit need to be managed here.
- *
- * Currently this routine is a stub because all the interesting resources
- * are managed via the screen init process.
- */
-}
-
-Bool
-DRIQueryDirectRenderingCapable(ScreenPtr pScreen, Bool* isCapable)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- if (pDRIPriv)
- *isCapable = pDRIPriv->directRenderingSupport;
- else
- *isCapable = FALSE;
-
- return TRUE;
-}
-
-Bool
-DRIOpenConnection(ScreenPtr pScreen, drm_handle_t * hSAREA, char **busIdString)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- *hSAREA = pDRIPriv->hSAREA;
- *busIdString = pDRIPriv->pDriverInfo->busIdString;
-
- return TRUE;
-}
-
-Bool
-DRIAuthConnection(ScreenPtr pScreen, drm_magic_t magic)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- if (drmAuthMagic(pDRIPriv->drmFD, magic)) return FALSE;
- return TRUE;
-}
-
-Bool
-DRICloseConnection(ScreenPtr pScreen)
-{
- return TRUE;
-}
-
-Bool
-DRIGetClientDriverName(ScreenPtr pScreen,
- int *ddxDriverMajorVersion,
- int *ddxDriverMinorVersion,
- int *ddxDriverPatchVersion,
- char **clientDriverName)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- *ddxDriverMajorVersion = pDRIPriv->pDriverInfo->ddxDriverMajorVersion;
- *ddxDriverMinorVersion = pDRIPriv->pDriverInfo->ddxDriverMinorVersion;
- *ddxDriverPatchVersion = pDRIPriv->pDriverInfo->ddxDriverPatchVersion;
- *clientDriverName = pDRIPriv->pDriverInfo->clientDriverName;
-
- return TRUE;
-}
-
-/* DRICreateContextPriv and DRICreateContextPrivFromHandle are helper
- functions that layer on drmCreateContext and drmAddContextTag.
-
- DRICreateContextPriv always creates a kernel drm_context_t and then calls
- DRICreateContextPrivFromHandle to create a DRIContextPriv structure for
- DRI tracking. For the SIGIO handler, the drm_context_t is associated with
- DRIContextPrivPtr. Any special flags are stored in the DRIContextPriv
- area and are passed to the kernel (if necessary).
-
- DRICreateContextPriv returns a pointer to newly allocated
- DRIContextPriv, and returns the kernel drm_context_t in pHWContext. */
-
-DRIContextPrivPtr
-DRICreateContextPriv(ScreenPtr pScreen,
- drm_context_t * pHWContext,
- DRIContextFlags flags)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- if (drmCreateContext(pDRIPriv->drmFD, pHWContext)) {
- return NULL;
- }
-
- return DRICreateContextPrivFromHandle(pScreen, *pHWContext, flags);
-}
-
-DRIContextPrivPtr
-DRICreateContextPrivFromHandle(ScreenPtr pScreen,
- drm_context_t hHWContext,
- DRIContextFlags flags)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- DRIContextPrivPtr pDRIContextPriv;
- int contextPrivSize;
-
- contextPrivSize = sizeof(DRIContextPrivRec) +
- pDRIPriv->pDriverInfo->contextSize;
- if (!(pDRIContextPriv = calloc(1, contextPrivSize))) {
- return NULL;
- }
- pDRIContextPriv->pContextStore = (void *)(pDRIContextPriv + 1);
-
- drmAddContextTag(pDRIPriv->drmFD, hHWContext, pDRIContextPriv);
-
- pDRIContextPriv->hwContext = hHWContext;
- pDRIContextPriv->pScreen = pScreen;
- pDRIContextPriv->flags = flags;
- pDRIContextPriv->valid3D = FALSE;
-
- if (flags & DRI_CONTEXT_2DONLY) {
- if (drmSetContextFlags(pDRIPriv->drmFD,
- hHWContext,
- DRM_CONTEXT_2DONLY)) {
- DRIDrvMsg(pScreen->myNum, X_ERROR,
- "[drm] failed to set 2D context flag\n");
- DRIDestroyContextPriv(pDRIContextPriv);
- return NULL;
- }
- }
- if (flags & DRI_CONTEXT_PRESERVED) {
- if (drmSetContextFlags(pDRIPriv->drmFD,
- hHWContext,
- DRM_CONTEXT_PRESERVED)) {
- DRIDrvMsg(pScreen->myNum, X_ERROR,
- "[drm] failed to set preserved flag\n");
- DRIDestroyContextPriv(pDRIContextPriv);
- return NULL;
- }
- }
- return pDRIContextPriv;
-}
-
-Bool
-DRIDestroyContextPriv(DRIContextPrivPtr pDRIContextPriv)
-{
- DRIScreenPrivPtr pDRIPriv;
-
- if (!pDRIContextPriv) return TRUE;
-
- pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen);
-
- if (!(pDRIContextPriv->flags & DRI_CONTEXT_RESERVED)) {
- /* Don't delete reserved contexts from
- kernel area -- the kernel manages its
- reserved contexts itself. */
- if (drmDestroyContext(pDRIPriv->drmFD, pDRIContextPriv->hwContext))
- return FALSE;
- }
-
- /* Remove the tag last to prevent a race
- condition where the context has pending
- buffers. The context can't be re-used
- while in this thread, but buffers can be
- dispatched asynchronously. */
- drmDelContextTag(pDRIPriv->drmFD, pDRIContextPriv->hwContext);
- free(pDRIContextPriv);
- return TRUE;
-}
-
-static Bool
-DRICreateDummyContext(ScreenPtr pScreen, Bool needCtxPriv)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- DRIContextPrivPtr pDRIContextPriv;
- void *contextStore;
-
- if (!(pDRIContextPriv =
- DRICreateContextPriv(pScreen,
- &pDRIPriv->pSAREA->dummy_context, 0))) {
- return FALSE;
- }
-
- contextStore = DRIGetContextStore(pDRIContextPriv);
- if (pDRIPriv->pDriverInfo->CreateContext && needCtxPriv) {
- if (!pDRIPriv->pDriverInfo->CreateContext(pScreen, NULL,
- pDRIPriv->pSAREA->dummy_context,
- NULL,
- (DRIContextType)(long)contextStore)) {
- DRIDestroyContextPriv(pDRIContextPriv);
- return FALSE;
- }
- }
-
- pDRIPriv->dummyCtxPriv = pDRIContextPriv;
- return TRUE;
-}
-
-static void
-DRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- DRIContextPrivPtr pDRIContextPriv = pDRIPriv->dummyCtxPriv;
- void *contextStore;
-
- if (!pDRIContextPriv) return;
- if (pDRIPriv->pDriverInfo->DestroyContext && hasCtxPriv) {
- contextStore = DRIGetContextStore(pDRIContextPriv);
- pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen,
- pDRIContextPriv->hwContext,
- (DRIContextType)(long)contextStore);
- }
-
- DRIDestroyContextPriv(pDRIPriv->dummyCtxPriv);
- pDRIPriv->dummyCtxPriv = NULL;
-}
-
-Bool
-DRICreateContext(ScreenPtr pScreen, VisualPtr visual,
- XID context, drm_context_t * pHWContext)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- DRIContextPrivPtr pDRIContextPriv;
- void *contextStore;
-
- if (pDRIPriv->createDummyCtx && !pDRIPriv->dummyCtxPriv) {
- if (!DRICreateDummyContext(pScreen, pDRIPriv->createDummyCtxPriv)) {
- DRIDrvMsg(pScreen->myNum, X_INFO,
- "[drm] Could not create dummy context\n");
- return FALSE;
- }
- }
-
- if (!(pDRIContextPriv = DRICreateContextPriv(pScreen, pHWContext, 0))) {
- return FALSE;
- }
-
- contextStore = DRIGetContextStore(pDRIContextPriv);
- if (pDRIPriv->pDriverInfo->CreateContext) {
- if (!((*pDRIPriv->pDriverInfo->CreateContext)(pScreen, NULL,
- *pHWContext, NULL,
- (DRIContextType)(long)contextStore))) {
- DRIDestroyContextPriv(pDRIContextPriv);
- return FALSE;
- }
- }
-
- /* track this in case the client dies before cleanup */
- AddResource(context, DRIContextPrivResType, (pointer)pDRIContextPriv);
-
- return TRUE;
-}
-
-Bool
-DRIDestroyContext(ScreenPtr pScreen, XID context)
-{
- FreeResourceByType(context, DRIContextPrivResType, FALSE);
-
- return TRUE;
-}
-
-/* DRIContextPrivDelete is called by the resource manager. */
-Bool
-DRIContextPrivDelete(pointer pResource, XID id)
-{
- DRIContextPrivPtr pDRIContextPriv = (DRIContextPrivPtr)pResource;
- DRIScreenPrivPtr pDRIPriv;
- void *contextStore;
-
- pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen);
- if (pDRIPriv->pDriverInfo->DestroyContext) {
- contextStore = DRIGetContextStore(pDRIContextPriv);
- pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen,
- pDRIContextPriv->hwContext,
- (DRIContextType)(long)contextStore);
- }
- return DRIDestroyContextPriv(pDRIContextPriv);
-}
-
-
-/* This walks the drawable timestamp array and invalidates all of them
- * in the case of transition from private to shared backbuffers. It's
- * not necessary for correctness, because DRIClipNotify gets called in
- * time to prevent any conflict, but the transition from
- * shared->private is sometimes missed if we don't do this.
- */
-static void
-DRIClipNotifyAllDrawables(ScreenPtr pScreen)
-{
- int i;
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- for( i=0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) {
- pDRIPriv->pSAREA->drawableTable[i].stamp = DRIDrawableValidationStamp++;
- }
-}
-
-
-static void
-DRITransitionToSharedBuffers(ScreenPtr pScreen)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo;
-
- DRIClipNotifyAllDrawables( pScreen );
-
- if (pDRIInfo->TransitionSingleToMulti3D)
- pDRIInfo->TransitionSingleToMulti3D( pScreen );
-}
-
-
-static void
-DRITransitionToPrivateBuffers(ScreenPtr pScreen)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo;
-
- DRIClipNotifyAllDrawables( pScreen );
-
- if (pDRIInfo->TransitionMultiToSingle3D)
- pDRIInfo->TransitionMultiToSingle3D( pScreen );
-}
-
-
-static void
-DRITransitionTo3d(ScreenPtr pScreen)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo;
-
- DRIClipNotifyAllDrawables( pScreen );
-
- if (pDRIInfo->TransitionTo3d)
- pDRIInfo->TransitionTo3d( pScreen );
-}
-
-static void
-DRITransitionTo2d(ScreenPtr pScreen)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo;
-
- DRIClipNotifyAllDrawables( pScreen );
-
- if (pDRIInfo->TransitionTo2d)
- pDRIInfo->TransitionTo2d( pScreen );
-}
-
-
-static int
-DRIDCNTreeTraversal(WindowPtr pWin, pointer data)
-{
- DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
-
- if (pDRIDrawablePriv) {
- ScreenPtr pScreen = pWin->drawable.pScreen;
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- if (RegionNumRects(&pWin->clipList) > 0) {
- WindowPtr *pDRIWindows = (WindowPtr*)data;
- int i = 0;
-
- while (pDRIWindows[i])
- i++;
-
- pDRIWindows[i] = pWin;
-
- pDRIPriv->nrWalked++;
- }
-
- if (pDRIPriv->nrWindows == pDRIPriv->nrWalked)
- return WT_STOPWALKING;
- }
-
- return WT_WALKCHILDREN;
-}
-
-static void
-DRIDriverClipNotify(ScreenPtr pScreen)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- if (pDRIPriv->pDriverInfo->ClipNotify) {
- WindowPtr *pDRIWindows = calloc(sizeof(WindowPtr), pDRIPriv->nrWindows);
- DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo;
-
- if (pDRIPriv->nrWindows > 0) {
- pDRIPriv->nrWalked = 0;
- TraverseTree(pScreen->root, DRIDCNTreeTraversal,
- (pointer)pDRIWindows);
- }
-
- pDRIInfo->ClipNotify(pScreen, pDRIWindows, pDRIPriv->nrWindows);
-
- free(pDRIWindows);
- }
-}
-
-static void
-DRIIncreaseNumberVisible(ScreenPtr pScreen)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- switch (++pDRIPriv->nrWindowsVisible) {
- case 1:
- DRITransitionTo3d( pScreen );
- break;
- case 2:
- DRITransitionToSharedBuffers( pScreen );
- break;
- default:
- break;
- }
-
- DRIDriverClipNotify(pScreen);
-}
-
-static void
-DRIDecreaseNumberVisible(ScreenPtr pScreen)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- switch (--pDRIPriv->nrWindowsVisible) {
- case 0:
- DRITransitionTo2d( pScreen );
- break;
- case 1:
- DRITransitionToPrivateBuffers( pScreen );
- break;
- default:
- break;
- }
-
- DRIDriverClipNotify(pScreen);
-}
-
-Bool
-DRICreateDrawable(ScreenPtr pScreen, ClientPtr client, DrawablePtr pDrawable,
- drm_drawable_t * hHWDrawable)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- DRIDrawablePrivPtr pDRIDrawablePriv;
- WindowPtr pWin;
-
- if (pDrawable->type == DRAWABLE_WINDOW) {
- pWin = (WindowPtr)pDrawable;
- if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) {
- pDRIDrawablePriv->refCount++;
-
- if (!pDRIDrawablePriv->hwDrawable) {
- drmCreateDrawable(pDRIPriv->drmFD, &pDRIDrawablePriv->hwDrawable);
- }
- }
- else {
- /* allocate a DRI Window Private record */
- if (!(pDRIDrawablePriv = malloc(sizeof(DRIDrawablePrivRec)))) {
- return FALSE;
- }
-
- /* Only create a drm_drawable_t once */
- if (drmCreateDrawable(pDRIPriv->drmFD,
- &pDRIDrawablePriv->hwDrawable)) {
- free(pDRIDrawablePriv);
- return FALSE;
- }
-
- /* add it to the list of DRI drawables for this screen */
- pDRIDrawablePriv->pScreen = pScreen;
- pDRIDrawablePriv->refCount = 1;
- pDRIDrawablePriv->drawableIndex = -1;
- pDRIDrawablePriv->nrects = RegionNumRects(&pWin->clipList);
-
- /* save private off of preallocated index */
- dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey,
- pDRIDrawablePriv);
- pDRIPriv->nrWindows++;
-
- if (pDRIDrawablePriv->nrects)
- DRIIncreaseNumberVisible(pScreen);
- }
-
- /* track this in case the client dies */
- AddResource(FakeClientID(client->index), DRIDrawablePrivResType,
- (pointer)(intptr_t)pDrawable->id);
-
- if (pDRIDrawablePriv->hwDrawable) {
- drmUpdateDrawableInfo(pDRIPriv->drmFD,
- pDRIDrawablePriv->hwDrawable,
- DRM_DRAWABLE_CLIPRECTS,
- RegionNumRects(&pWin->clipList),
- RegionRects(&pWin->clipList));
- *hHWDrawable = pDRIDrawablePriv->hwDrawable;
- }
- }
- else if (pDrawable->type != DRAWABLE_PIXMAP) { /* PBuffer */
- /* NOT_DONE */
- return FALSE;
- }
-
- return TRUE;
-}
-
-static void
-DRIDrawablePrivDestroy(WindowPtr pWin)
-{
- DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
- ScreenPtr pScreen;
- DRIScreenPrivPtr pDRIPriv;
-
- if (!pDRIDrawablePriv)
- return;
-
- pScreen = pWin->drawable.pScreen;
- pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- if (pDRIDrawablePriv->drawableIndex != -1) {
- /* bump stamp to force outstanding 3D requests to resync */
- pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp
- = DRIDrawableValidationStamp++;
-
- /* release drawable table entry */
- pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL;
- }
-
- pDRIPriv->nrWindows--;
-
- if (pDRIDrawablePriv->nrects)
- DRIDecreaseNumberVisible(pScreen);
-
- drmDestroyDrawable(pDRIPriv->drmFD, pDRIDrawablePriv->hwDrawable);
-
- free(pDRIDrawablePriv);
- dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL);
-}
-
-static Bool
-DRIDestroyDrawableCB(pointer value, XID id, pointer data)
-{
- if (value == data) {
- /* This calls back DRIDrawablePrivDelete which frees private area */
- FreeResourceByType(id, DRIDrawablePrivResType, FALSE);
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-Bool
-DRIDestroyDrawable(ScreenPtr pScreen, ClientPtr client, DrawablePtr pDrawable)
-{
- if (pDrawable->type == DRAWABLE_WINDOW) {
- LookupClientResourceComplex(client, DRIDrawablePrivResType,
- DRIDestroyDrawableCB,
- (pointer)(intptr_t)pDrawable->id);
- }
- else { /* pixmap (or for GLX 1.3, a PBuffer) */
- /* NOT_DONE */
- return FALSE;
- }
-
- return TRUE;
-}
-
-Bool
-DRIDrawablePrivDelete(pointer pResource, XID id)
-{
- WindowPtr pWin;
- int rc;
-
- /* For DRIDrawablePrivResType, the XID is the client's fake ID. The
- * important XID is the value in pResource. */
- id = (XID)(intptr_t)pResource;
- rc = dixLookupWindow(&pWin, id, serverClient, DixGetAttrAccess);
-
- if (rc == Success) {
- DRIDrawablePrivPtr pDRIDrwPriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
-
- if (!pDRIDrwPriv)
- return FALSE;
-
- if (--pDRIDrwPriv->refCount == 0)
- DRIDrawablePrivDestroy(pWin);
-
- return TRUE;
- }
- else { /* pixmap (or for GLX 1.3, a PBuffer) */
- /* NOT_DONE */
- return FALSE;
- }
-}
-
-Bool
-DRIGetDrawableInfo(ScreenPtr pScreen,
- DrawablePtr pDrawable,
- unsigned int* index,
- unsigned int* stamp,
- int* X,
- int* Y,
- int* W,
- int* H,
- int* numClipRects,
- drm_clip_rect_t ** pClipRects,
- int* backX,
- int* backY,
- int* numBackClipRects,
- drm_clip_rect_t ** pBackClipRects)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- DRIDrawablePrivPtr pDRIDrawablePriv, pOldDrawPriv;
- WindowPtr pWin, pOldWin;
- int i;
-
-#if 0
- printf("maxDrawableTableEntry = %d\n", pDRIPriv->pDriverInfo->maxDrawableTableEntry);
-#endif
-
- if (pDrawable->type == DRAWABLE_WINDOW) {
- pWin = (WindowPtr)pDrawable;
- if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) {
-
- /* Manage drawable table */
- if (pDRIDrawablePriv->drawableIndex == -1) { /* load SAREA table */
-
- /* Search table for empty entry */
- i = 0;
- while (i < pDRIPriv->pDriverInfo->maxDrawableTableEntry) {
- if (!(pDRIPriv->DRIDrawables[i])) {
- pDRIPriv->DRIDrawables[i] = pDrawable;
- pDRIDrawablePriv->drawableIndex = i;
- pDRIPriv->pSAREA->drawableTable[i].stamp =
- DRIDrawableValidationStamp++;
- break;
- }
- i++;
- }
-
- /* Search table for oldest entry */
- if (i == pDRIPriv->pDriverInfo->maxDrawableTableEntry) {
- unsigned int oldestStamp = ~0;
- int oldestIndex = 0;
- i = pDRIPriv->pDriverInfo->maxDrawableTableEntry;
- while (i--) {
- if (pDRIPriv->pSAREA->drawableTable[i].stamp <
- oldestStamp) {
- oldestIndex = i;
- oldestStamp =
- pDRIPriv->pSAREA->drawableTable[i].stamp;
- }
- }
- pDRIDrawablePriv->drawableIndex = oldestIndex;
-
- /* release oldest drawable table entry */
- pOldWin = (WindowPtr)pDRIPriv->DRIDrawables[oldestIndex];
- pOldDrawPriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pOldWin);
- pOldDrawPriv->drawableIndex = -1;
-
- /* claim drawable table entry */
- pDRIPriv->DRIDrawables[oldestIndex] = pDrawable;
-
- /* validate SAREA entry */
- pDRIPriv->pSAREA->drawableTable[oldestIndex].stamp =
- DRIDrawableValidationStamp++;
-
- /* check for stamp wrap around */
- if (oldestStamp > DRIDrawableValidationStamp) {
-
- /* walk SAREA table and invalidate all drawables */
- for( i=0;
- i < pDRIPriv->pDriverInfo->maxDrawableTableEntry;
- i++) {
- pDRIPriv->pSAREA->drawableTable[i].stamp =
- DRIDrawableValidationStamp++;
- }
- }
- }
-
- /* If the driver wants to be notified when the index is
- * set for a drawable, let it know now.
- */
- if (pDRIPriv->pDriverInfo->SetDrawableIndex)
- pDRIPriv->pDriverInfo->SetDrawableIndex(pWin,
- pDRIDrawablePriv->drawableIndex);
-
- /* reinit drawable ID if window is visible */
- if ((pWin->viewable) &&
- (pDRIPriv->pDriverInfo->bufferRequests != DRI_NO_WINDOWS))
- {
- (*pDRIPriv->pDriverInfo->InitBuffers)(pWin,
- &pWin->clipList, pDRIDrawablePriv->drawableIndex);
- }
- }
-
- *index = pDRIDrawablePriv->drawableIndex;
- *stamp = pDRIPriv->pSAREA->drawableTable[*index].stamp;
- *X = (int)(pWin->drawable.x);
- *Y = (int)(pWin->drawable.y);
-#if 0
- *W = (int)(pWin->winSize.extents.x2 - pWin->winSize.extents.x1);
- *H = (int)(pWin->winSize.extents.y2 - pWin->winSize.extents.y1);
-#endif
- *W = (int)(pWin->drawable.width);
- *H = (int)(pWin->drawable.height);
- *numClipRects = RegionNumRects(&pWin->clipList);
- *pClipRects = (drm_clip_rect_t *)RegionRects(&pWin->clipList);
-
- if (!*numClipRects && pDRIPriv->fullscreen) {
- /* use fake full-screen clip rect */
- pDRIPriv->fullscreen_rect.x1 = *X;
- pDRIPriv->fullscreen_rect.y1 = *Y;
- pDRIPriv->fullscreen_rect.x2 = *X + *W;
- pDRIPriv->fullscreen_rect.y2 = *Y + *H;
-
- *numClipRects = 1;
- *pClipRects = &pDRIPriv->fullscreen_rect;
- }
-
- *backX = *X;
- *backY = *Y;
-
- if (pDRIPriv->nrWindowsVisible == 1 && *numClipRects) {
- /* Use a single cliprect. */
-
- int x0 = *X;
- int y0 = *Y;
- int x1 = x0 + *W;
- int y1 = y0 + *H;
-
- if (x0 < 0) x0 = 0;
- if (y0 < 0) y0 = 0;
- if (x1 > pScreen->width) x1 = pScreen->width;
- if (y1 > pScreen->height) y1 = pScreen->height;
-
- if (y0 >= y1 || x0 >= x1) {
- *numBackClipRects = 0;
- *pBackClipRects = NULL;
- } else {
- pDRIPriv->private_buffer_rect.x1 = x0;
- pDRIPriv->private_buffer_rect.y1 = y0;
- pDRIPriv->private_buffer_rect.x2 = x1;
- pDRIPriv->private_buffer_rect.y2 = y1;
-
- *numBackClipRects = 1;
- *pBackClipRects = &(pDRIPriv->private_buffer_rect);
- }
- } else {
- /* Use the frontbuffer cliprects for back buffers. */
- *numBackClipRects = 0;
- *pBackClipRects = 0;
- }
- }
- else {
- /* Not a DRIDrawable */
- return FALSE;
- }
- }
- else { /* pixmap (or for GLX 1.3, a PBuffer) */
- /* NOT_DONE */
- return FALSE;
- }
-
- return TRUE;
-}
-
-Bool
-DRIGetDeviceInfo(ScreenPtr pScreen,
- drm_handle_t * hFrameBuffer,
- int* fbOrigin,
- int* fbSize,
- int* fbStride,
- int* devPrivateSize,
- void** pDevPrivate)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- *hFrameBuffer = pDRIPriv->pDriverInfo->hFrameBuffer;
- *fbOrigin = 0;
- *fbSize = pDRIPriv->pDriverInfo->frameBufferSize;
- *fbStride = pDRIPriv->pDriverInfo->frameBufferStride;
- *devPrivateSize = pDRIPriv->pDriverInfo->devPrivateSize;
- *pDevPrivate = pDRIPriv->pDriverInfo->devPrivate;
-
- return TRUE;
-}
-
-DRIInfoPtr
-DRICreateInfoRec(void)
-{
- DRIInfoPtr inforec = (DRIInfoPtr)calloc(1, sizeof(DRIInfoRec));
- if (!inforec) return NULL;
-
- /* Initialize defaults */
- inforec->busIdString = NULL;
-
- /* Wrapped function defaults */
- inforec->wrap.WakeupHandler = DRIDoWakeupHandler;
- inforec->wrap.BlockHandler = DRIDoBlockHandler;
- inforec->wrap.WindowExposures = DRIWindowExposures;
- inforec->wrap.CopyWindow = DRICopyWindow;
- inforec->wrap.ValidateTree = DRIValidateTree;
- inforec->wrap.PostValidateTree = DRIPostValidateTree;
- inforec->wrap.ClipNotify = DRIClipNotify;
- inforec->wrap.AdjustFrame = DRIAdjustFrame;
-
- inforec->TransitionTo2d = 0;
- inforec->TransitionTo3d = 0;
- inforec->SetDrawableIndex = 0;
-
- return inforec;
-}
-
-void
-DRIDestroyInfoRec(DRIInfoPtr DRIInfo)
-{
- free(DRIInfo->busIdString);
- free((char*)DRIInfo);
-}
-
-
-void
-DRIWakeupHandler(pointer wakeupData, int result, pointer pReadmask)
-{
- int i;
-
- for (i = 0; i < screenInfo.numScreens; i++) {
- ScreenPtr pScreen = screenInfo.screens[i];
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- if (pDRIPriv &&
- pDRIPriv->pDriverInfo->wrap.WakeupHandler)
- (*pDRIPriv->pDriverInfo->wrap.WakeupHandler)(i, wakeupData,
- result, pReadmask);
- }
-}
-
-void
-DRIBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask)
-{
- int i;
-
- for (i = 0; i < screenInfo.numScreens; i++) {
- ScreenPtr pScreen = screenInfo.screens[i];
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- if (pDRIPriv &&
- pDRIPriv->pDriverInfo->wrap.BlockHandler)
- (*pDRIPriv->pDriverInfo->wrap.BlockHandler)(i, blockData,
- pTimeout, pReadmask);
- }
-}
-
-void
-DRIDoWakeupHandler(int screenNum, pointer wakeupData,
- unsigned long result, pointer pReadmask)
-{
- ScreenPtr pScreen = screenInfo.screens[screenNum];
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- DRILock(pScreen, 0);
- if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) {
- /* hide X context by swapping 2D component here */
- (*pDRIPriv->pDriverInfo->SwapContext)(pScreen,
- DRI_3D_SYNC,
- DRI_2D_CONTEXT,
- pDRIPriv->partial3DContextStore,
- DRI_2D_CONTEXT,
- pDRIPriv->hiddenContextStore);
- }
-}
-
-void
-DRIDoBlockHandler(int screenNum, pointer blockData,
- pointer pTimeout, pointer pReadmask)
-{
- ScreenPtr pScreen = screenInfo.screens[screenNum];
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) {
- /* hide X context by swapping 2D component here */
- (*pDRIPriv->pDriverInfo->SwapContext)(pScreen,
- DRI_2D_SYNC,
- DRI_NO_CONTEXT,
- NULL,
- DRI_2D_CONTEXT,
- pDRIPriv->partial3DContextStore);
- }
-
- if (pDRIPriv->windowsTouched)
- DRM_SPINUNLOCK(&pDRIPriv->pSAREA->drawable_lock, 1);
- pDRIPriv->windowsTouched = FALSE;
-
- DRIUnlock(pScreen);
-}
-
-void
-DRISwapContext(int drmFD, void *oldctx, void *newctx)
-{
- DRIContextPrivPtr oldContext = (DRIContextPrivPtr)oldctx;
- DRIContextPrivPtr newContext = (DRIContextPrivPtr)newctx;
- ScreenPtr pScreen = newContext->pScreen;
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- void* oldContextStore = NULL;
- DRIContextType oldContextType;
- void* newContextStore = NULL;
- DRIContextType newContextType;
- DRISyncType syncType;
-#ifdef DEBUG
- static int count = 0;
-
- if (!newContext) {
- DRIDrvMsg(pScreen->myNum, X_ERROR,
- "[DRI] Context Switch Error: oldContext=%x, newContext=%x\n",
- oldContext, newContext);
- return;
- }
-
- /* usefull for debugging, just print out after n context switches */
- if (!count || !(count % 1)) {
- DRIDrvMsg(pScreen->myNum, X_INFO,
- "[DRI] Context switch %5d from %p/0x%08x (%d)\n",
- count,
- oldContext,
- oldContext ? oldContext->flags : 0,
- oldContext ? oldContext->hwContext : -1);
- DRIDrvMsg(pScreen->myNum, X_INFO,
- "[DRI] Context switch %5d to %p/0x%08x (%d)\n",
- count,
- newContext,
- newContext ? newContext->flags : 0,
- newContext ? newContext->hwContext : -1);
- }
- ++count;
-#endif
-
- if (!pDRIPriv->pDriverInfo->SwapContext) {
- DRIDrvMsg(pScreen->myNum, X_ERROR,
- "[DRI] DDX driver missing context swap call back\n");
- return;
- }
-
- if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) {
-
- /* only 3D contexts are swapped in this case */
- if (oldContext) {
- oldContextStore = DRIGetContextStore(oldContext);
- oldContext->valid3D = TRUE;
- oldContextType = DRI_3D_CONTEXT;
- } else {
- oldContextType = DRI_NO_CONTEXT;
- }
- newContextStore = DRIGetContextStore(newContext);
- if ((newContext->valid3D) &&
- (newContext->hwContext != pDRIPriv->myContext)) {
- newContextType = DRI_3D_CONTEXT;
- }
- else {
- newContextType = DRI_2D_CONTEXT;
- }
- syncType = DRI_3D_SYNC;
- }
- else /* default: driverSwapMethod == DRI_SERVER_SWAP */ {
-
- /* optimize 2D context swaps */
-
- if (newContext->flags & DRI_CONTEXT_2DONLY) {
- /* go from 3D context to 2D context and only save 2D
- * subset of 3D state
- */
- oldContextStore = DRIGetContextStore(oldContext);
- oldContextType = DRI_2D_CONTEXT;
- newContextStore = DRIGetContextStore(newContext);
- newContextType = DRI_2D_CONTEXT;
- syncType = DRI_3D_SYNC;
- pDRIPriv->lastPartial3DContext = oldContext;
- }
- else if (oldContext->flags & DRI_CONTEXT_2DONLY) {
- if (pDRIPriv->lastPartial3DContext == newContext) {
- /* go from 2D context back to previous 3D context and
- * only restore 2D subset of previous 3D state
- */
- oldContextStore = DRIGetContextStore(oldContext);
- oldContextType = DRI_2D_CONTEXT;
- newContextStore = DRIGetContextStore(newContext);
- newContextType = DRI_2D_CONTEXT;
- syncType = DRI_2D_SYNC;
- }
- else {
- /* go from 2D context to a different 3D context */
-
- /* call DDX driver to do partial restore */
- oldContextStore = DRIGetContextStore(oldContext);
- newContextStore =
- DRIGetContextStore(pDRIPriv->lastPartial3DContext);
- (*pDRIPriv->pDriverInfo->SwapContext)(pScreen,
- DRI_2D_SYNC,
- DRI_2D_CONTEXT,
- oldContextStore,
- DRI_2D_CONTEXT,
- newContextStore);
-
- /* now setup for a complete 3D swap */
- oldContextStore = newContextStore;
- oldContext->valid3D = TRUE;
- oldContextType = DRI_3D_CONTEXT;
- newContextStore = DRIGetContextStore(newContext);
- if ((newContext->valid3D) &&
- (newContext->hwContext != pDRIPriv->myContext)) {
- newContextType = DRI_3D_CONTEXT;
- }
- else {
- newContextType = DRI_2D_CONTEXT;
- }
- syncType = DRI_NO_SYNC;
- }
- }
- else {
- /* now setup for a complete 3D swap */
- oldContextStore = newContextStore;
- oldContext->valid3D = TRUE;
- oldContextType = DRI_3D_CONTEXT;
- newContextStore = DRIGetContextStore(newContext);
- if ((newContext->valid3D) &&
- (newContext->hwContext != pDRIPriv->myContext)) {
- newContextType = DRI_3D_CONTEXT;
- }
- else {
- newContextType = DRI_2D_CONTEXT;
- }
- syncType = DRI_3D_SYNC;
- }
- }
-
- /* call DDX driver to perform the swap */
- (*pDRIPriv->pDriverInfo->SwapContext)(pScreen,
- syncType,
- oldContextType,
- oldContextStore,
- newContextType,
- newContextStore);
-}
-
-void*
-DRIGetContextStore(DRIContextPrivPtr context)
-{
- return((void *)context->pContextStore);
-}
-
-void
-DRIWindowExposures(WindowPtr pWin, RegionPtr prgn, RegionPtr bsreg)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
-
- if(pDRIDrawablePriv) {
- (*pDRIPriv->pDriverInfo->InitBuffers)(pWin, prgn,
- pDRIDrawablePriv->drawableIndex);
- }
-
- /* call lower wrapped functions */
- if (pDRIPriv && pDRIPriv->wrap.WindowExposures) {
-
- /* unwrap */
- pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures;
-
- /* call lower layers */
- (*pScreen->WindowExposures)(pWin, prgn, bsreg);
-
- /* rewrap */
- pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures;
- pScreen->WindowExposures = DRIWindowExposures;
- }
-}
-
-
-static int
-DRITreeTraversal(WindowPtr pWin, pointer data)
-{
- DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
-
- if(pDRIDrawablePriv) {
- ScreenPtr pScreen = pWin->drawable.pScreen;
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- if(RegionNumRects(&(pWin->clipList)) > 0) {
- RegionPtr reg = (RegionPtr)data;
-
- RegionUnion(reg, reg, &(pWin->clipList));
- pDRIPriv->nrWalked++;
- }
-
- if(pDRIPriv->nrWindows == pDRIPriv->nrWalked)
- return WT_STOPWALKING;
- }
- return WT_WALKCHILDREN;
-}
-
-Bool
-DRIDestroyWindow(WindowPtr pWin)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- Bool retval = TRUE;
-
- DRIDrawablePrivDestroy(pWin);
-
- /* call lower wrapped functions */
- if(pDRIPriv->DestroyWindow) {
- /* unwrap */
- pScreen->DestroyWindow = pDRIPriv->DestroyWindow;
-
- /* call lower layers */
- retval = (*pScreen->DestroyWindow)(pWin);
-
- /* rewrap */
- pDRIPriv->DestroyWindow = pScreen->DestroyWindow;
- pScreen->DestroyWindow = DRIDestroyWindow;
- }
-
- return retval;
-}
-
-void
-DRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- if(!pDRIPriv) return;
-
- if(pDRIPriv->nrWindowsVisible > 0) {
- RegionRec reg;
-
- RegionNull(®);
- pDRIPriv->nrWalked = 0;
- TraverseTree(pWin, DRITreeTraversal, (pointer)(®));
-
- if(RegionNotEmpty(®)) {
- RegionTranslate(®, ptOldOrg.x - pWin->drawable.x,
- ptOldOrg.y - pWin->drawable.y);
- RegionIntersect(®, ®, prgnSrc);
-
- /* The MoveBuffers interface is not ideal */
- (*pDRIPriv->pDriverInfo->MoveBuffers)(pWin, ptOldOrg, ®,
- pDRIPriv->pDriverInfo->ddxDrawableTableEntry);
- }
-
- RegionUninit(®);
- }
-
- /* call lower wrapped functions */
- if(pDRIPriv->wrap.CopyWindow) {
- /* unwrap */
- pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow;
-
- /* call lower layers */
- (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc);
-
- /* rewrap */
- pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow;
- pScreen->CopyWindow = DRICopyWindow;
- }
-}
-
-static void
-DRIGetSecs(long *secs, long *usecs)
-{
- struct timeval tv;
-
- gettimeofday(&tv, NULL);
-
- *secs = tv.tv_sec;
- *usecs = tv.tv_usec;
-}
-
-static unsigned long
-DRIComputeMilliSeconds(unsigned long s_secs, unsigned long s_usecs,
- unsigned long f_secs, unsigned long f_usecs)
-{
- if (f_usecs < s_usecs) {
- --f_secs;
- f_usecs += 1000000;
- }
- return (f_secs - s_secs) * 1000 + (f_usecs - s_usecs) / 1000;
-}
-
-static void
-DRISpinLockTimeout(drmLock *lock, int val, unsigned long timeout /* in mS */)
-{
- int count = 10000;
-#if !defined(__alpha__) && !defined(__powerpc__)
- char ret;
-#else
- int ret;
-#endif
- long s_secs, s_usecs;
- long f_secs, f_usecs;
- long msecs;
- long prev = 0;
-
- DRIGetSecs(&s_secs, &s_usecs);
-
- do {
- DRM_SPINLOCK_COUNT(lock, val, count, ret);
- if (!ret) return; /* Got lock */
- DRIGetSecs(&f_secs, &f_usecs);
- msecs = DRIComputeMilliSeconds(s_secs, s_usecs, f_secs, f_usecs);
- if (msecs - prev < 250) count *= 2; /* Not more than 0.5S */
- } while (msecs < timeout);
-
- /* Didn't get lock, so take it. The worst
- that can happen is that there is some
- garbage written to the wrong part of the
- framebuffer that a refresh will repair.
- That's undesirable, but better than
- locking the server. This should be a
- very rare event. */
- DRM_SPINLOCK_TAKE(lock, val);
-}
-
-static void
-DRILockTree(ScreenPtr pScreen)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- if(!pDRIPriv) return;
-
- /* Restore the last known 3D context if the X context is hidden */
- if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) {
- (*pDRIPriv->pDriverInfo->SwapContext)(pScreen,
- DRI_2D_SYNC,
- DRI_NO_CONTEXT,
- NULL,
- DRI_2D_CONTEXT,
- pDRIPriv->partial3DContextStore);
- }
-
- /* Call kernel to release lock */
- DRIUnlock(pScreen);
-
- /* Grab drawable spin lock: a time out between 10 and 30 seconds is
- appropriate, since this should never time out except in the case of
- client death while the lock is being held. The timeout must be
- greater than any reasonable rendering time. */
- DRISpinLockTimeout(&pDRIPriv->pSAREA->drawable_lock, 1, 10000); /*10 secs*/
-
- /* Call kernel flush outstanding buffers and relock */
- DRILock(pScreen, DRM_LOCK_QUIESCENT|DRM_LOCK_FLUSH_ALL);
-
- /* Switch back to our 2D context if the X context is hidden */
- if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) {
- /* hide X context by swapping 2D component here */
- (*pDRIPriv->pDriverInfo->SwapContext)(pScreen,
- DRI_3D_SYNC,
- DRI_2D_CONTEXT,
- pDRIPriv->partial3DContextStore,
- DRI_2D_CONTEXT,
- pDRIPriv->hiddenContextStore);
- }
-}
-
-int
-DRIValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
-{
- ScreenPtr pScreen = pParent->drawable.pScreen;
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- int returnValue = 1; /* always return 1, not checked by dix/window.c */
-
- if(!pDRIPriv) return returnValue;
-
- /* call lower wrapped functions */
- if(pDRIPriv->wrap.ValidateTree) {
- /* unwrap */
- pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree;
-
- /* call lower layers */
- returnValue = (*pScreen->ValidateTree)(pParent, pChild, kind);
-
- /* rewrap */
- pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree;
- pScreen->ValidateTree = DRIValidateTree;
- }
-
- return returnValue;
-}
-
-void
-DRIPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
-{
- ScreenPtr pScreen;
- DRIScreenPrivPtr pDRIPriv;
-
- if (pParent) {
- pScreen = pParent->drawable.pScreen;
- } else {
- pScreen = pChild->drawable.pScreen;
- }
- if(!(pDRIPriv = DRI_SCREEN_PRIV(pScreen))) return;
-
- if (pDRIPriv->wrap.PostValidateTree) {
- /* unwrap */
- pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree;
-
- /* call lower layers */
- (*pScreen->PostValidateTree)(pParent, pChild, kind);
-
- /* rewrap */
- pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree;
- pScreen->PostValidateTree = DRIPostValidateTree;
- }
-}
-
-void
-DRIClipNotify(WindowPtr pWin, int dx, int dy)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- DRIDrawablePrivPtr pDRIDrawablePriv;
-
- if(!pDRIPriv) return;
-
- if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) {
- int nrects = RegionNumRects(&pWin->clipList);
-
- if(!pDRIPriv->windowsTouched) {
- DRILockTree(pScreen);
- pDRIPriv->windowsTouched = TRUE;
- }
-
- if (nrects && !pDRIDrawablePriv->nrects)
- DRIIncreaseNumberVisible(pScreen);
- else if (!nrects && pDRIDrawablePriv->nrects)
- DRIDecreaseNumberVisible(pScreen);
- else
- DRIDriverClipNotify(pScreen);
-
- pDRIDrawablePriv->nrects = nrects;
-
- pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp
- = DRIDrawableValidationStamp++;
-
- drmUpdateDrawableInfo(pDRIPriv->drmFD, pDRIDrawablePriv->hwDrawable,
- DRM_DRAWABLE_CLIPRECTS,
- nrects, RegionRects(&pWin->clipList));
- }
-
- /* call lower wrapped functions */
- if(pDRIPriv->wrap.ClipNotify) {
-
- /* unwrap */
- pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify;
-
- /* call lower layers */
- (*pScreen->ClipNotify)(pWin, dx, dy);
-
- /* rewrap */
- pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify;
- pScreen->ClipNotify = DRIClipNotify;
- }
-}
-
-CARD32
-DRIGetDrawableIndex(WindowPtr pWin)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
- CARD32 index;
-
- if (pDRIDrawablePriv) {
- index = pDRIDrawablePriv->drawableIndex;
- }
- else {
- index = pDRIPriv->pDriverInfo->ddxDrawableTableEntry;
- }
-
- return index;
-}
-
-unsigned int
-DRIGetDrawableStamp(ScreenPtr pScreen, CARD32 drawable_index)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- return pDRIPriv->pSAREA->drawableTable[drawable_index].stamp;
-}
-
-
-void
-DRIPrintDrawableLock(ScreenPtr pScreen, char *msg)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- ErrorF("%s: %d\n", msg, pDRIPriv->pSAREA->drawable_lock.lock);
-}
-
-void
-DRILock(ScreenPtr pScreen, int flags)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- if(!pDRIPriv || !pDRIPriv->pLockRefCount) return;
-
- if (!*pDRIPriv->pLockRefCount) {
- DRM_LOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext, flags);
- *pDRIPriv->pLockingContext = pDRIPriv->myContext;
- } else if (*pDRIPriv->pLockingContext != pDRIPriv->myContext) {
- DRIDrvMsg(pScreen->myNum, X_ERROR,
- "[DRI] Locking deadlock.\n"
- "\tAlready locked with context %d,\n"
- "\ttrying to lock with context %d.\n",
- pDRIPriv->pLockingContext,
- pDRIPriv->myContext);
- }
- (*pDRIPriv->pLockRefCount)++;
-}
-
-void
-DRIUnlock(ScreenPtr pScreen)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- if(!pDRIPriv || !pDRIPriv->pLockRefCount) return;
-
- if (*pDRIPriv->pLockRefCount > 0) {
- if (pDRIPriv->myContext != *pDRIPriv->pLockingContext) {
- DRIDrvMsg(pScreen->myNum, X_ERROR,
- "[DRI] Unlocking inconsistency:\n"
- "\tContext %d trying to unlock lock held by context %d\n",
- pDRIPriv->pLockingContext,
- pDRIPriv->myContext);
- }
- (*pDRIPriv->pLockRefCount)--;
- } else {
- DRIDrvMsg(pScreen->myNum, X_ERROR,
- "DRIUnlock called when not locked.\n");
- return;
- }
- if (! *pDRIPriv->pLockRefCount)
- DRM_UNLOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext);
-}
-
-void *
-DRIGetSAREAPrivate(ScreenPtr pScreen)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- if (!pDRIPriv) return 0;
-
- return (void *)(((char*)pDRIPriv->pSAREA)+sizeof(XF86DRISAREARec));
-}
-
-drm_context_t
-DRIGetContext(ScreenPtr pScreen)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- if (!pDRIPriv) return 0;
-
- return pDRIPriv->myContext;
-}
-
-void
-DRIGetTexOffsetFuncs(ScreenPtr pScreen,
- DRITexOffsetStartProcPtr *texOffsetStartFunc,
- DRITexOffsetFinishProcPtr *texOffsetFinishFunc)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- if (!pDRIPriv) return;
-
- *texOffsetStartFunc = pDRIPriv->pDriverInfo->texOffsetStart;
- *texOffsetFinishFunc = pDRIPriv->pDriverInfo->texOffsetFinish;
-}
-
-/* This lets get at the unwrapped functions so that they can correctly
- * call the lowerlevel functions, and choose whether they will be
- * called at every level of recursion (eg in validatetree).
- */
-DRIWrappedFuncsRec *
-DRIGetWrappedFuncs(ScreenPtr pScreen)
-{
- return &(DRI_SCREEN_PRIV(pScreen)->wrap);
-}
-
-/* note that this returns the library version, not the protocol version */
-void
-DRIQueryVersion(int *majorVersion,
- int *minorVersion,
- int *patchVersion)
-{
- *majorVersion = DRIINFO_MAJOR_VERSION;
- *minorVersion = DRIINFO_MINOR_VERSION;
- *patchVersion = DRIINFO_PATCH_VERSION;
-}
-
-static void
-_DRIAdjustFrame(ScrnInfoPtr pScrn, DRIScreenPrivPtr pDRIPriv, int x, int y)
-{
- pDRIPriv->pSAREA->frame.x = x;
- pDRIPriv->pSAREA->frame.y = y;
- pDRIPriv->pSAREA->frame.width = pScrn->frameX1 - x + 1;
- pDRIPriv->pSAREA->frame.height = pScrn->frameY1 - y + 1;
-}
-
-void
-DRIAdjustFrame(int scrnIndex, int x, int y, int flags)
-{
- ScreenPtr pScreen = screenInfo.screens[scrnIndex];
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- int px, py;
-
- if (!pDRIPriv || !pDRIPriv->pSAREA) {
- DRIDrvMsg(scrnIndex, X_ERROR, "[DRI] No SAREA (%p %p)\n",
- pDRIPriv, pDRIPriv ? pDRIPriv->pSAREA : NULL);
- return;
- }
-
- if (pDRIPriv->fullscreen) {
- /* Fix up frame */
- pScrn->frameX0 = pDRIPriv->pSAREA->frame.x;
- pScrn->frameY0 = pDRIPriv->pSAREA->frame.y;
- pScrn->frameX1 = pScrn->frameX0 + pDRIPriv->pSAREA->frame.width - 1;
- pScrn->frameY1 = pScrn->frameY0 + pDRIPriv->pSAREA->frame.height - 1;
-
- /* Fix up cursor */
- miPointerGetPosition(inputInfo.pointer, &px, &py);
- if (px < pScrn->frameX0) px = pScrn->frameX0;
- if (px > pScrn->frameX1) px = pScrn->frameX1;
- if (py < pScrn->frameY0) py = pScrn->frameY0;
- if (py > pScrn->frameY1) py = pScrn->frameY1;
- pScreen->SetCursorPosition(inputInfo.pointer, pScreen, px, py, TRUE);
- return;
- }
-
- if (pDRIPriv->wrap.AdjustFrame) {
- /* unwrap */
- pScrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame;
- /* call lower layers */
- (*pScrn->AdjustFrame)(scrnIndex, x, y, flags);
- /* rewrap */
- pDRIPriv->wrap.AdjustFrame = pScrn->AdjustFrame;
- pScrn->AdjustFrame = DRIAdjustFrame;
- }
-
- _DRIAdjustFrame(pScrn, pDRIPriv, x, y);
-}
-
-/*
- * DRIMoveBuffersHelper swaps the regions rects in place leaving you
- * a region with the rects in the order that you need to blit them,
- * but it is possibly (likely) an invalid region afterwards. If you
- * need to use the region again for anything you have to call
- * REGION_VALIDATE on it, or better yet, save a copy first.
- */
-
-void
-DRIMoveBuffersHelper(
- ScreenPtr pScreen,
- int dx,
- int dy,
- int *xdir,
- int *ydir,
- RegionPtr reg
-)
-{
- BoxPtr extents, pbox, firstBox, lastBox;
- BoxRec tmpBox;
- int y, nbox;
-
- extents = RegionExtents(reg);
- nbox = RegionNumRects(reg);
- pbox = RegionRects(reg);
-
- if((dy > 0) && (dy < (extents->y2 - extents->y1))) {
- *ydir = -1;
- if(nbox > 1) {
- firstBox = pbox;
- lastBox = pbox + nbox - 1;
- while((unsigned long)firstBox < (unsigned long)lastBox) {
- tmpBox = *firstBox;
- *firstBox = *lastBox;
- *lastBox = tmpBox;
- firstBox++;
- lastBox--;
- }
- }
- } else *ydir = 1;
-
- if((dx > 0) && (dx < (extents->x2 - extents->x1))) {
- *xdir = -1;
- if(nbox > 1) {
- firstBox = lastBox = pbox;
- y = pbox->y1;
- while(--nbox) {
- pbox++;
- if(pbox->y1 == y) lastBox++;
- else {
- while((unsigned long)firstBox < (unsigned long)lastBox) {
- tmpBox = *firstBox;
- *firstBox = *lastBox;
- *lastBox = tmpBox;
- firstBox++;
- lastBox--;
- }
-
- firstBox = lastBox = pbox;
- y = pbox->y1;
- }
- }
- while((unsigned long)firstBox < (unsigned long)lastBox) {
- tmpBox = *firstBox;
- *firstBox = *lastBox;
- *lastBox = tmpBox;
- firstBox++;
- lastBox--;
- }
- }
- } else *xdir = 1;
-
-}
-
-char *
-DRICreatePCIBusID(const struct pci_device * dev)
-{
- char *busID;
-
- if (asprintf(&busID, "pci:%04x:%02x:%02x.%d",
- dev->domain, dev->bus, dev->dev, dev->func) == -1)
- return NULL;
-
- return busID;
-}
-
-static void drmSIGIOHandler(int interrupt, void *closure)
-{
- unsigned long key;
- void *value;
- ssize_t count;
- drm_ctx_t ctx;
- typedef void (*_drmCallback)(int, void *, void *);
- char buf[256];
- drm_context_t old;
- drm_context_t new;
- void *oldctx;
- void *newctx;
- char *pt;
- drmHashEntry *entry;
- void *hash_table;
-
- hash_table = drmGetHashTable();
-
- if (!hash_table) return;
- if (drmHashFirst(hash_table, &key, &value)) {
- entry = value;
- do {
-#if 0
- fprintf(stderr, "Trying %d\n", entry->fd);
-#endif
- if ((count = read(entry->fd, buf, sizeof(buf) - 1)) > 0) {
- buf[count] = '\0';
-#if 0
- fprintf(stderr, "Got %s\n", buf);
-#endif
-
- for (pt = buf; *pt != ' '; ++pt); /* Find first space */
- ++pt;
- old = strtol(pt, &pt, 0);
- new = strtol(pt, NULL, 0);
- oldctx = drmGetContextTag(entry->fd, old);
- newctx = drmGetContextTag(entry->fd, new);
-#if 0
- fprintf(stderr, "%d %d %p %p\n", old, new, oldctx, newctx);
-#endif
- ((_drmCallback)entry->f)(entry->fd, oldctx, newctx);
- ctx.handle = new;
- ioctl(entry->fd, DRM_IOCTL_NEW_CTX, &ctx);
- }
- } while (drmHashNext(hash_table, &key, &value));
- }
-}
-
-
-int drmInstallSIGIOHandler(int fd, void (*f)(int, void *, void *))
-{
- drmHashEntry *entry;
-
- entry = drmGetEntry(fd);
- entry->f = f;
-
- return xf86InstallSIGIOHandler(fd, drmSIGIOHandler, 0);
-}
-
-int drmRemoveSIGIOHandler(int fd)
-{
- drmHashEntry *entry = drmGetEntry(fd);
-
- entry->f = NULL;
-
- return xf86RemoveSIGIOHandler(fd);
-}
+/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +Copyright 2000 VA Linux Systems, 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, sub license, 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: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Jens Owen <jens@tungstengraphics.com> + * Rickard E. (Rik) Faith <faith@valinux.com> + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf86.h" +#include <sys/time.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> +#include <sys/ioctl.h> +#include <errno.h> + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "xf86drm.h" +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "servermd.h" +#define _XF86DRI_SERVER_ +#include <X11/dri/xf86driproto.h> +#include "swaprep.h" +#include "xf86str.h" +#include "dri.h" +#include "sarea.h" +#include "dristruct.h" +#include "xf86.h" +#include "xf86drm.h" +#include "mi.h" +#include "mipointer.h" +#include "xf86_OSproc.h" +#include "inputstr.h" +#include "xf86VGAarbiter.h" + +static int DRIEntPrivIndex = -1; +static DevPrivateKeyRec DRIScreenPrivKeyRec; +#define DRIScreenPrivKey (&DRIScreenPrivKeyRec) +static DevPrivateKeyRec DRIWindowPrivKeyRec; +#define DRIWindowPrivKey (&DRIWindowPrivKeyRec) +static unsigned long DRIGeneration = 0; +static unsigned int DRIDrawableValidationStamp = 0; + +static RESTYPE DRIDrawablePrivResType; +static RESTYPE DRIContextPrivResType; +static void DRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv); + +drmServerInfo DRIDRMServerInfo; + + /* Wrapper just like xf86DrvMsg, but + without the verbosity level checking. + This will make it easy to turn off some + messages later, based on verbosity + level. */ + +/* + * Since we're already referencing things from the XFree86 common layer in + * this file, we'd might as well just call xf86VDrvMsgVerb, and have + * consistent message formatting. The verbosity of these messages can be + * easily changed here. + */ +#define DRI_MSG_VERBOSITY 1 +static void +DRIDrvMsg(int scrnIndex, MessageType type, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + xf86VDrvMsgVerb(scrnIndex, type, DRI_MSG_VERBOSITY, format, ap); + va_end(ap); +} + + +static void +DRIOpenDRMCleanup(DRIEntPrivPtr pDRIEntPriv) +{ + if (pDRIEntPriv->pLSAREA != NULL) { + drmUnmap(pDRIEntPriv->pLSAREA, pDRIEntPriv->sAreaSize); + pDRIEntPriv->pLSAREA = NULL; + } + if (pDRIEntPriv->hLSAREA != 0) { + drmRmMap(pDRIEntPriv->drmFD, pDRIEntPriv->hLSAREA); + } + if (pDRIEntPriv->drmFD >= 0) { + drmClose(pDRIEntPriv->drmFD); + pDRIEntPriv->drmFD = 0; + } +} + +int +DRIMasterFD(ScrnInfoPtr pScrn) +{ + return DRI_ENT_PRIV(pScrn)->drmFD; +} + +void * +DRIMasterSareaPointer(ScrnInfoPtr pScrn) +{ + return DRI_ENT_PRIV(pScrn)->pLSAREA; +} + +drm_handle_t +DRIMasterSareaHandle(ScrnInfoPtr pScrn) +{ + return DRI_ENT_PRIV(pScrn)->hLSAREA; +} + + +Bool +DRIOpenDRMMaster(ScrnInfoPtr pScrn, + unsigned long sAreaSize, + const char *busID, + const char *drmDriverName) +{ + drmSetVersion saveSv, sv; + Bool drmWasAvailable; + DRIEntPrivPtr pDRIEntPriv; + DRIEntPrivRec tmp; + drmVersionPtr drmlibv; + int drmlibmajor, drmlibminor; + const char *openBusID; + int count; + int err; + + if (DRIEntPrivIndex == -1) + DRIEntPrivIndex = xf86AllocateEntityPrivateIndex(); + + pDRIEntPriv = DRI_ENT_PRIV(pScrn); + + if (pDRIEntPriv && pDRIEntPriv->drmFD != -1) + return TRUE; + + drmWasAvailable = drmAvailable(); + + memset(&tmp, 0, sizeof(tmp)); + + /* Check the DRM lib version. + * drmGetLibVersion was not supported in version 1.0, so check for + * symbol first to avoid possible crash or hang. + */ + + drmlibmajor = 1; + drmlibminor = 0; + if (xf86LoaderCheckSymbol("drmGetLibVersion")) { + drmlibv = drmGetLibVersion(-1); + if (drmlibv != NULL) { + drmlibmajor = drmlibv->version_major; + drmlibminor = drmlibv->version_minor; + drmFreeVersion(drmlibv); + } + } + + /* Check if the libdrm can handle falling back to loading based on name + * if a busid string is passed. + */ + openBusID = (drmlibmajor == 1 && drmlibminor >= 2) ? busID : NULL; + + tmp.drmFD = -1; + sv.drm_di_major = 1; + sv.drm_di_minor = 1; + sv.drm_dd_major = -1; + + saveSv = sv; + count = 10; + while (count--) { + tmp.drmFD = drmOpen(drmDriverName, openBusID); + + if (tmp.drmFD < 0) { + DRIDrvMsg(-1, X_ERROR, "[drm] drmOpen failed.\n"); + goto out_err; + } + + err = drmSetInterfaceVersion(tmp.drmFD, &sv); + + if (err != -EPERM) + break; + + sv = saveSv; + drmClose(tmp.drmFD); + tmp.drmFD = -1; + usleep(100000); + } + + if (tmp.drmFD <= 0) { + DRIDrvMsg(-1, X_ERROR, "[drm] DRM was busy with another master.\n"); + goto out_err; + } + + if (!drmWasAvailable) { + DRIDrvMsg(-1, X_INFO, + "[drm] loaded kernel module for \"%s\" driver.\n", + drmDriverName); + } + + if (err != 0) { + sv.drm_di_major = 1; + sv.drm_di_minor = 0; + } + + DRIDrvMsg(-1, X_INFO, "[drm] DRM interface version %d.%d\n", + sv.drm_di_major, sv.drm_di_minor); + + if (sv.drm_di_major == 1 && sv.drm_di_minor >= 1) + err = 0; + else + err = drmSetBusid(tmp.drmFD, busID); + + if (err) { + DRIDrvMsg(-1, X_ERROR, "[drm] Could not set DRM device bus ID.\n"); + goto out_err; + } + + /* + * Create a lock-containing sarea. + */ + + if (drmAddMap( tmp.drmFD, 0, sAreaSize, DRM_SHM, + DRM_CONTAINS_LOCK, &tmp.hLSAREA) < 0) { + DRIDrvMsg(-1, X_INFO, "[drm] Could not create SAREA for DRM lock.\n"); + tmp.hLSAREA = 0; + goto out_err; + } + + if (drmMap( tmp.drmFD, tmp.hLSAREA, sAreaSize, + (drmAddressPtr)(&tmp.pLSAREA)) < 0) { + DRIDrvMsg(-1, X_INFO, "[drm] Mapping SAREA for DRM lock failed.\n"); + tmp.pLSAREA = NULL; + goto out_err; + } + + memset(tmp.pLSAREA, 0, sAreaSize); + + /* + * Reserved contexts are handled by the first opened screen. + */ + + tmp.resOwner = NULL; + + if (!pDRIEntPriv) + pDRIEntPriv = xnfcalloc(sizeof(*pDRIEntPriv), 1); + + if (!pDRIEntPriv) { + DRIDrvMsg(-1, X_INFO, "[drm] Failed to allocate memory for " + "DRM device.\n"); + goto out_err; + } + *pDRIEntPriv = tmp; + xf86GetEntityPrivate((pScrn)->entityList[0],DRIEntPrivIndex)->ptr = + pDRIEntPriv; + + DRIDrvMsg(-1, X_INFO, "[drm] DRM open master succeeded.\n"); + return TRUE; + + out_err: + + DRIOpenDRMCleanup(&tmp); + return FALSE; +} + +static void +DRIClipNotifyAllDrawables(ScreenPtr pScreen); + +static void +dri_crtc_notify(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIClipNotifyAllDrawables(pScreen); + xf86_unwrap_crtc_notify(pScreen, pDRIPriv->xf86_crtc_notify); + xf86_crtc_notify(pScreen); + pDRIPriv->xf86_crtc_notify = xf86_wrap_crtc_notify(pScreen, dri_crtc_notify); +} + +Bool +DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD) +{ + DRIScreenPrivPtr pDRIPriv; + drm_context_t * reserved; + int reserved_count; + int i; + DRIEntPrivPtr pDRIEntPriv; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + DRIContextFlags flags = 0; + DRIContextPrivPtr pDRIContextPriv; + + /* If the DRI extension is disabled, do not initialize the DRI */ + if (noXFree86DRIExtension) { + DRIDrvMsg(pScreen->myNum, X_WARNING, + "Direct rendering has been disabled.\n"); + return FALSE; + } + + if (!xf86VGAarbiterAllowDRI(pScreen)) { + DRIDrvMsg(pScreen->myNum, X_WARNING, + "Direct rendering is not supported when VGA arb is necessary for the device\n"); + return FALSE; + } + +#ifdef PANORAMIX + /* + * If Xinerama is on, don't allow DRI to initialise. It won't be usable + * anyway. + */ + if (!noPanoramiXExtension) { + DRIDrvMsg(pScreen->myNum, X_WARNING, + "Direct rendering is not supported when Xinerama is enabled\n"); + return FALSE; + } +#endif + + if (!DRIOpenDRMMaster(pScrn, pDRIInfo->SAREASize, + pDRIInfo->busIdString, + pDRIInfo->drmDriverName)) + return FALSE; + + pDRIEntPriv = DRI_ENT_PRIV(pScrn); + + if (DRIGeneration != serverGeneration) + DRIGeneration = serverGeneration; + + if (!dixRegisterPrivateKey(&DRIScreenPrivKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + if (!dixRegisterPrivateKey(&DRIWindowPrivKeyRec, PRIVATE_WINDOW, 0)) + return FALSE; + + pDRIPriv = (DRIScreenPrivPtr) calloc(1, sizeof(DRIScreenPrivRec)); + if (!pDRIPriv) { + dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); + return FALSE; + } + + dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, pDRIPriv); + pDRIPriv->drmFD = pDRIEntPriv->drmFD; + pDRIPriv->directRenderingSupport = TRUE; + pDRIPriv->pDriverInfo = pDRIInfo; + pDRIPriv->nrWindows = 0; + pDRIPriv->nrWindowsVisible = 0; + pDRIPriv->fullscreen = NULL; + + pDRIPriv->createDummyCtx = pDRIInfo->createDummyCtx; + pDRIPriv->createDummyCtxPriv = pDRIInfo->createDummyCtxPriv; + + pDRIPriv->grabbedDRILock = FALSE; + pDRIPriv->drmSIGIOHandlerInstalled = FALSE; + *pDRMFD = pDRIPriv->drmFD; + + if (pDRIEntPriv->sAreaGrabbed || pDRIInfo->allocSarea) { + + if (drmAddMap( pDRIPriv->drmFD, + 0, + pDRIPriv->pDriverInfo->SAREASize, + DRM_SHM, + 0, + &pDRIPriv->hSAREA) < 0) + { + pDRIPriv->directRenderingSupport = FALSE; + dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); + drmClose(pDRIPriv->drmFD); + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] drmAddMap failed\n"); + return FALSE; + } + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] added %d byte SAREA at %p\n", + pDRIPriv->pDriverInfo->SAREASize, pDRIPriv->hSAREA); + + /* Backwards compat. */ + if (drmMap( pDRIPriv->drmFD, + pDRIPriv->hSAREA, + pDRIPriv->pDriverInfo->SAREASize, + (drmAddressPtr)(&pDRIPriv->pSAREA)) < 0) + { + pDRIPriv->directRenderingSupport = FALSE; + dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); + drmClose(pDRIPriv->drmFD); + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] drmMap failed\n"); + return FALSE; + } + DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] mapped SAREA %p to %p\n", + pDRIPriv->hSAREA, pDRIPriv->pSAREA); + memset(pDRIPriv->pSAREA, 0, pDRIPriv->pDriverInfo->SAREASize); + } else { + DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] Using the DRM lock " + "SAREA also for drawables.\n"); + pDRIPriv->hSAREA = pDRIEntPriv->hLSAREA; + pDRIPriv->pSAREA = (XF86DRISAREAPtr) pDRIEntPriv->pLSAREA; + pDRIEntPriv->sAreaGrabbed = TRUE; + } + + pDRIPriv->hLSAREA = pDRIEntPriv->hLSAREA; + pDRIPriv->pLSAREA = pDRIEntPriv->pLSAREA; + + if (!pDRIPriv->pDriverInfo->dontMapFrameBuffer) + { + if (drmAddMap( pDRIPriv->drmFD, + (uintptr_t)pDRIPriv->pDriverInfo->frameBufferPhysicalAddress, + pDRIPriv->pDriverInfo->frameBufferSize, + DRM_FRAME_BUFFER, + 0, + &pDRIPriv->pDriverInfo->hFrameBuffer) < 0) + { + pDRIPriv->directRenderingSupport = FALSE; + dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); + drmUnmap(pDRIPriv->pSAREA, pDRIPriv->pDriverInfo->SAREASize); + drmClose(pDRIPriv->drmFD); + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] drmAddMap failed\n"); + return FALSE; + } + DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] framebuffer handle = %p\n", + pDRIPriv->pDriverInfo->hFrameBuffer); + } else { + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] framebuffer mapped by ddx driver\n"); + } + + if (pDRIEntPriv->resOwner == NULL) { + pDRIEntPriv->resOwner = pScreen; + + /* Add tags for reserved contexts */ + if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD, + &reserved_count))) { + int i; + void *tag; + + for (i = 0; i < reserved_count; i++) { + tag = DRICreateContextPrivFromHandle(pScreen, + reserved[i], + DRI_CONTEXT_RESERVED); + drmAddContextTag(pDRIPriv->drmFD, reserved[i], tag); + } + drmFreeReservedContextList(reserved); + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] added %d reserved context%s for kernel\n", + reserved_count, reserved_count > 1 ? "s" : ""); + } + } + + /* validate max drawable table entry set by driver */ + if ((pDRIPriv->pDriverInfo->maxDrawableTableEntry <= 0) || + (pDRIPriv->pDriverInfo->maxDrawableTableEntry > SAREA_MAX_DRAWABLES)) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "Invalid max drawable table size set by driver: %d\n", + pDRIPriv->pDriverInfo->maxDrawableTableEntry); + } + + /* Initialize drawable tables (screen private and SAREA) */ + for( i=0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) { + pDRIPriv->DRIDrawables[i] = NULL; + pDRIPriv->pSAREA->drawableTable[i].stamp = 0; + pDRIPriv->pSAREA->drawableTable[i].flags = 0; + } + + pDRIPriv->pLockRefCount = &pDRIEntPriv->lockRefCount; + pDRIPriv->pLockingContext = &pDRIEntPriv->lockingContext; + + if (!pDRIEntPriv->keepFDOpen) + pDRIEntPriv->keepFDOpen = pDRIInfo->keepFDOpen; + + pDRIEntPriv->refCount++; + + /* Set up flags for DRICreateContextPriv */ + switch (pDRIInfo->driverSwapMethod) { + case DRI_KERNEL_SWAP: + flags = DRI_CONTEXT_2DONLY; + break; + case DRI_HIDE_X_CONTEXT: + flags = DRI_CONTEXT_PRESERVED; + break; + } + + if (!(pDRIContextPriv = DRICreateContextPriv(pScreen, + &pDRIPriv->myContext, + flags))) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "failed to create server context\n"); + return FALSE; + } + pDRIPriv->myContextPriv = pDRIContextPriv; + + DRIDrvMsg(pScreen->myNum, X_INFO, + "X context handle = %p\n", pDRIPriv->myContext); + + /* Now that we have created the X server's context, we can grab the + * hardware lock for the X server. + */ + DRILock(pScreen, 0); + pDRIPriv->grabbedDRILock = TRUE; + + /* pointers so that we can prevent memory leaks later */ + pDRIPriv->hiddenContextStore = NULL; + pDRIPriv->partial3DContextStore = NULL; + + switch(pDRIInfo->driverSwapMethod) { + case DRI_HIDE_X_CONTEXT: + /* Server will handle 3D swaps, and hide 2D swaps from kernel. + * Register server context as a preserved context. + */ + + /* allocate memory for hidden context store */ + pDRIPriv->hiddenContextStore + = (void *)calloc(1, pDRIInfo->contextSize); + if (!pDRIPriv->hiddenContextStore) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "failed to allocate hidden context\n"); + DRIDestroyContextPriv(pDRIContextPriv); + return FALSE; + } + + /* allocate memory for partial 3D context store */ + pDRIPriv->partial3DContextStore + = (void *)calloc(1, pDRIInfo->contextSize); + if (!pDRIPriv->partial3DContextStore) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[DRI] failed to allocate partial 3D context\n"); + free(pDRIPriv->hiddenContextStore); + DRIDestroyContextPriv(pDRIContextPriv); + return FALSE; + } + + /* save initial context store */ + if (pDRIInfo->SwapContext) { + (*pDRIInfo->SwapContext)( + pScreen, + DRI_NO_SYNC, + DRI_2D_CONTEXT, + pDRIPriv->hiddenContextStore, + DRI_NO_CONTEXT, + NULL); + } + /* fall through */ + + case DRI_SERVER_SWAP: + /* For swap methods of DRI_SERVER_SWAP and DRI_HIDE_X_CONTEXT + * setup signal handler for receiving swap requests from kernel + */ + if (!(pDRIPriv->drmSIGIOHandlerInstalled = + drmInstallSIGIOHandler(pDRIPriv->drmFD, DRISwapContext))) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[drm] failed to setup DRM signal handler\n"); + free(pDRIPriv->hiddenContextStore); + free(pDRIPriv->partial3DContextStore); + DRIDestroyContextPriv(pDRIContextPriv); + return FALSE; + } else { + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] installed DRM signal handler\n"); + } + + default: + break; + } + + return TRUE; +} + +Bool +DRIFinishScreenInit(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; + + /* Wrap DRI support */ + if (pDRIInfo->wrap.ValidateTree) { + pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree; + pScreen->ValidateTree = pDRIInfo->wrap.ValidateTree; + } + if (pDRIInfo->wrap.PostValidateTree) { + pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree; + pScreen->PostValidateTree = pDRIInfo->wrap.PostValidateTree; + } + if (pDRIInfo->wrap.WindowExposures) { + pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; + pScreen->WindowExposures = pDRIInfo->wrap.WindowExposures; + } + + pDRIPriv->DestroyWindow = pScreen->DestroyWindow; + pScreen->DestroyWindow = DRIDestroyWindow; + + pDRIPriv->xf86_crtc_notify = xf86_wrap_crtc_notify(pScreen, + dri_crtc_notify); + + if (pDRIInfo->wrap.CopyWindow) { + pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; + pScreen->CopyWindow = pDRIInfo->wrap.CopyWindow; + } + if (pDRIInfo->wrap.ClipNotify) { + pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; + pScreen->ClipNotify = pDRIInfo->wrap.ClipNotify; + } + if (pDRIInfo->wrap.AdjustFrame) { + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + pDRIPriv->wrap.AdjustFrame = pScrn->AdjustFrame; + pScrn->AdjustFrame = pDRIInfo->wrap.AdjustFrame; + } + pDRIPriv->wrapped = TRUE; + + DRIDrvMsg(pScreen->myNum, X_INFO, "[DRI] installation complete\n"); + + return TRUE; +} + +void +DRICloseScreen(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIInfoPtr pDRIInfo; + drm_context_t * reserved; + int reserved_count; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + DRIEntPrivPtr pDRIEntPriv = DRI_ENT_PRIV(pScrn); + Bool closeMaster; + + if (pDRIPriv) { + + pDRIInfo = pDRIPriv->pDriverInfo; + + if (pDRIPriv->wrapped) { + /* Unwrap DRI Functions */ + if (pDRIInfo->wrap.ValidateTree) { + pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree; + pDRIPriv->wrap.ValidateTree = NULL; + } + if (pDRIInfo->wrap.PostValidateTree) { + pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree; + pDRIPriv->wrap.PostValidateTree = NULL; + } + if (pDRIInfo->wrap.WindowExposures) { + pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures; + pDRIPriv->wrap.WindowExposures = NULL; + } + if (pDRIPriv->DestroyWindow) { + pScreen->DestroyWindow = pDRIPriv->DestroyWindow; + pDRIPriv->DestroyWindow = NULL; + } + + xf86_unwrap_crtc_notify(pScreen, pDRIPriv->xf86_crtc_notify); + + if (pDRIInfo->wrap.CopyWindow) { + pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow; + pDRIPriv->wrap.CopyWindow = NULL; + } + if (pDRIInfo->wrap.ClipNotify) { + pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify; + pDRIPriv->wrap.ClipNotify = NULL; + } + if (pDRIInfo->wrap.AdjustFrame) { + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + pScrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame; + pDRIPriv->wrap.AdjustFrame = NULL; + } + + pDRIPriv->wrapped = FALSE; + } + + if (pDRIPriv->drmSIGIOHandlerInstalled) { + if (!drmRemoveSIGIOHandler(pDRIPriv->drmFD)) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[drm] failed to remove DRM signal handler\n"); + } + } + + if (pDRIPriv->dummyCtxPriv && pDRIPriv->createDummyCtx) { + DRIDestroyDummyContext(pScreen, pDRIPriv->createDummyCtxPriv); + } + + if (!DRIDestroyContextPriv(pDRIPriv->myContextPriv)) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "failed to destroy server context\n"); + } + + /* Remove tags for reserved contexts */ + if (pDRIEntPriv->resOwner == pScreen) { + pDRIEntPriv->resOwner = NULL; + + if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD, + &reserved_count))) { + int i; + + for (i = 0; i < reserved_count; i++) { + DRIDestroyContextPriv(drmGetContextTag(pDRIPriv->drmFD, + reserved[i])); + } + drmFreeReservedContextList(reserved); + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] removed %d reserved context%s for kernel\n", + reserved_count, reserved_count > 1 ? "s" : ""); + } + } + + /* Make sure signals get unblocked etc. */ + drmUnlock(pDRIPriv->drmFD, pDRIPriv->myContext); + pDRIPriv->pLockRefCount = NULL; + closeMaster = (--pDRIEntPriv->refCount == 0) && + !pDRIEntPriv->keepFDOpen; + if (closeMaster || pDRIPriv->hSAREA != pDRIEntPriv->hLSAREA) { + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] unmapping %d bytes of SAREA %p at %p\n", + pDRIInfo->SAREASize, + pDRIPriv->hSAREA, + pDRIPriv->pSAREA); + if (drmUnmap(pDRIPriv->pSAREA, pDRIInfo->SAREASize)) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[drm] unable to unmap %d bytes" + " of SAREA %p at %p\n", + pDRIInfo->SAREASize, + pDRIPriv->hSAREA, + pDRIPriv->pSAREA); + } + } else { + pDRIEntPriv->sAreaGrabbed = FALSE; + } + + if (closeMaster || (pDRIEntPriv->drmFD != pDRIPriv->drmFD)) { + drmClose(pDRIPriv->drmFD); + if (pDRIEntPriv->drmFD == pDRIPriv->drmFD) { + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] Closed DRM master.\n"); + pDRIEntPriv->drmFD = -1; + } + } + + free(pDRIPriv); + dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); + } +} + +#define DRM_MSG_VERBOSITY 3 + +static int dri_drm_debug_print(const char *format, va_list ap) +{ + xf86VDrvMsgVerb(-1, X_NONE, DRM_MSG_VERBOSITY, format, ap); + return 0; +} + +static void dri_drm_get_perms(gid_t *group, mode_t *mode) +{ + *group = xf86ConfigDRI.group; + *mode = xf86ConfigDRI.mode; +} + +drmServerInfo DRIDRMServerInfo = { + dri_drm_debug_print, + xf86LoadKernelModule, + dri_drm_get_perms, +}; + +Bool +DRIExtensionInit(void) +{ + if (DRIGeneration != serverGeneration) { + return FALSE; + } + + DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete, + "DRIDrawable"); + DRIContextPrivResType = CreateNewResourceType(DRIContextPrivDelete, + "DRIContext"); + + if (!DRIDrawablePrivResType || !DRIContextPrivResType) + return FALSE; + + RegisterBlockAndWakeupHandlers(DRIBlockHandler, DRIWakeupHandler, NULL); + + return TRUE; +} + +void +DRIReset(void) +{ + /* + * This stub routine is called when the X Server recycles, resources + * allocated by DRIExtensionInit need to be managed here. + * + * Currently this routine is a stub because all the interesting resources + * are managed via the screen init process. + */ +} + +Bool +DRIQueryDirectRenderingCapable(ScreenPtr pScreen, Bool* isCapable) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (pDRIPriv) + *isCapable = pDRIPriv->directRenderingSupport; + else + *isCapable = FALSE; + + return TRUE; +} + +Bool +DRIOpenConnection(ScreenPtr pScreen, drm_handle_t * hSAREA, char **busIdString) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + *hSAREA = pDRIPriv->hSAREA; + *busIdString = pDRIPriv->pDriverInfo->busIdString; + + return TRUE; +} + +Bool +DRIAuthConnection(ScreenPtr pScreen, drm_magic_t magic) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (drmAuthMagic(pDRIPriv->drmFD, magic)) return FALSE; + return TRUE; +} + +Bool +DRICloseConnection(ScreenPtr pScreen) +{ + return TRUE; +} + +Bool +DRIGetClientDriverName(ScreenPtr pScreen, + int *ddxDriverMajorVersion, + int *ddxDriverMinorVersion, + int *ddxDriverPatchVersion, + char **clientDriverName) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + *ddxDriverMajorVersion = pDRIPriv->pDriverInfo->ddxDriverMajorVersion; + *ddxDriverMinorVersion = pDRIPriv->pDriverInfo->ddxDriverMinorVersion; + *ddxDriverPatchVersion = pDRIPriv->pDriverInfo->ddxDriverPatchVersion; + *clientDriverName = pDRIPriv->pDriverInfo->clientDriverName; + + return TRUE; +} + +/* DRICreateContextPriv and DRICreateContextPrivFromHandle are helper + functions that layer on drmCreateContext and drmAddContextTag. + + DRICreateContextPriv always creates a kernel drm_context_t and then calls + DRICreateContextPrivFromHandle to create a DRIContextPriv structure for + DRI tracking. For the SIGIO handler, the drm_context_t is associated with + DRIContextPrivPtr. Any special flags are stored in the DRIContextPriv + area and are passed to the kernel (if necessary). + + DRICreateContextPriv returns a pointer to newly allocated + DRIContextPriv, and returns the kernel drm_context_t in pHWContext. */ + +DRIContextPrivPtr +DRICreateContextPriv(ScreenPtr pScreen, + drm_context_t * pHWContext, + DRIContextFlags flags) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (drmCreateContext(pDRIPriv->drmFD, pHWContext)) { + return NULL; + } + + return DRICreateContextPrivFromHandle(pScreen, *pHWContext, flags); +} + +DRIContextPrivPtr +DRICreateContextPrivFromHandle(ScreenPtr pScreen, + drm_context_t hHWContext, + DRIContextFlags flags) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIContextPrivPtr pDRIContextPriv; + int contextPrivSize; + + contextPrivSize = sizeof(DRIContextPrivRec) + + pDRIPriv->pDriverInfo->contextSize; + if (!(pDRIContextPriv = calloc(1, contextPrivSize))) { + return NULL; + } + pDRIContextPriv->pContextStore = (void *)(pDRIContextPriv + 1); + + drmAddContextTag(pDRIPriv->drmFD, hHWContext, pDRIContextPriv); + + pDRIContextPriv->hwContext = hHWContext; + pDRIContextPriv->pScreen = pScreen; + pDRIContextPriv->flags = flags; + pDRIContextPriv->valid3D = FALSE; + + if (flags & DRI_CONTEXT_2DONLY) { + if (drmSetContextFlags(pDRIPriv->drmFD, + hHWContext, + DRM_CONTEXT_2DONLY)) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[drm] failed to set 2D context flag\n"); + DRIDestroyContextPriv(pDRIContextPriv); + return NULL; + } + } + if (flags & DRI_CONTEXT_PRESERVED) { + if (drmSetContextFlags(pDRIPriv->drmFD, + hHWContext, + DRM_CONTEXT_PRESERVED)) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[drm] failed to set preserved flag\n"); + DRIDestroyContextPriv(pDRIContextPriv); + return NULL; + } + } + return pDRIContextPriv; +} + +Bool +DRIDestroyContextPriv(DRIContextPrivPtr pDRIContextPriv) +{ + DRIScreenPrivPtr pDRIPriv; + + if (!pDRIContextPriv) return TRUE; + + pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen); + + if (!(pDRIContextPriv->flags & DRI_CONTEXT_RESERVED)) { + /* Don't delete reserved contexts from + kernel area -- the kernel manages its + reserved contexts itself. */ + if (drmDestroyContext(pDRIPriv->drmFD, pDRIContextPriv->hwContext)) + return FALSE; + } + + /* Remove the tag last to prevent a race + condition where the context has pending + buffers. The context can't be re-used + while in this thread, but buffers can be + dispatched asynchronously. */ + drmDelContextTag(pDRIPriv->drmFD, pDRIContextPriv->hwContext); + free(pDRIContextPriv); + return TRUE; +} + +static Bool +DRICreateDummyContext(ScreenPtr pScreen, Bool needCtxPriv) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIContextPrivPtr pDRIContextPriv; + void *contextStore; + + if (!(pDRIContextPriv = + DRICreateContextPriv(pScreen, + &pDRIPriv->pSAREA->dummy_context, 0))) { + return FALSE; + } + + contextStore = DRIGetContextStore(pDRIContextPriv); + if (pDRIPriv->pDriverInfo->CreateContext && needCtxPriv) { + if (!pDRIPriv->pDriverInfo->CreateContext(pScreen, NULL, + pDRIPriv->pSAREA->dummy_context, + NULL, + (DRIContextType)(long)contextStore)) { + DRIDestroyContextPriv(pDRIContextPriv); + return FALSE; + } + } + + pDRIPriv->dummyCtxPriv = pDRIContextPriv; + return TRUE; +} + +static void +DRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIContextPrivPtr pDRIContextPriv = pDRIPriv->dummyCtxPriv; + void *contextStore; + + if (!pDRIContextPriv) return; + if (pDRIPriv->pDriverInfo->DestroyContext && hasCtxPriv) { + contextStore = DRIGetContextStore(pDRIContextPriv); + pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen, + pDRIContextPriv->hwContext, + (DRIContextType)(long)contextStore); + } + + DRIDestroyContextPriv(pDRIPriv->dummyCtxPriv); + pDRIPriv->dummyCtxPriv = NULL; +} + +Bool +DRICreateContext(ScreenPtr pScreen, VisualPtr visual, + XID context, drm_context_t * pHWContext) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIContextPrivPtr pDRIContextPriv; + void *contextStore; + + if (pDRIPriv->createDummyCtx && !pDRIPriv->dummyCtxPriv) { + if (!DRICreateDummyContext(pScreen, pDRIPriv->createDummyCtxPriv)) { + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] Could not create dummy context\n"); + return FALSE; + } + } + + if (!(pDRIContextPriv = DRICreateContextPriv(pScreen, pHWContext, 0))) { + return FALSE; + } + + contextStore = DRIGetContextStore(pDRIContextPriv); + if (pDRIPriv->pDriverInfo->CreateContext) { + if (!((*pDRIPriv->pDriverInfo->CreateContext)(pScreen, NULL, + *pHWContext, NULL, + (DRIContextType)(long)contextStore))) { + DRIDestroyContextPriv(pDRIContextPriv); + return FALSE; + } + } + + /* track this in case the client dies before cleanup */ + AddResource(context, DRIContextPrivResType, (pointer)pDRIContextPriv); + + return TRUE; +} + +Bool +DRIDestroyContext(ScreenPtr pScreen, XID context) +{ + FreeResourceByType(context, DRIContextPrivResType, FALSE); + + return TRUE; +} + +/* DRIContextPrivDelete is called by the resource manager. */ +Bool +DRIContextPrivDelete(pointer pResource, XID id) +{ + DRIContextPrivPtr pDRIContextPriv = (DRIContextPrivPtr)pResource; + DRIScreenPrivPtr pDRIPriv; + void *contextStore; + + pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen); + if (pDRIPriv->pDriverInfo->DestroyContext) { + contextStore = DRIGetContextStore(pDRIContextPriv); + pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen, + pDRIContextPriv->hwContext, + (DRIContextType)(long)contextStore); + } + return DRIDestroyContextPriv(pDRIContextPriv); +} + + +/* This walks the drawable timestamp array and invalidates all of them + * in the case of transition from private to shared backbuffers. It's + * not necessary for correctness, because DRIClipNotify gets called in + * time to prevent any conflict, but the transition from + * shared->private is sometimes missed if we don't do this. + */ +static void +DRIClipNotifyAllDrawables(ScreenPtr pScreen) +{ + int i; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + for( i=0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) { + pDRIPriv->pSAREA->drawableTable[i].stamp = DRIDrawableValidationStamp++; + } +} + + +static void +DRITransitionToSharedBuffers(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; + + DRIClipNotifyAllDrawables( pScreen ); + + if (pDRIInfo->TransitionSingleToMulti3D) + pDRIInfo->TransitionSingleToMulti3D( pScreen ); +} + + +static void +DRITransitionToPrivateBuffers(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; + + DRIClipNotifyAllDrawables( pScreen ); + + if (pDRIInfo->TransitionMultiToSingle3D) + pDRIInfo->TransitionMultiToSingle3D( pScreen ); +} + + +static void +DRITransitionTo3d(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; + + DRIClipNotifyAllDrawables( pScreen ); + + if (pDRIInfo->TransitionTo3d) + pDRIInfo->TransitionTo3d( pScreen ); +} + +static void +DRITransitionTo2d(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; + + DRIClipNotifyAllDrawables( pScreen ); + + if (pDRIInfo->TransitionTo2d) + pDRIInfo->TransitionTo2d( pScreen ); +} + + +static int +DRIDCNTreeTraversal(WindowPtr pWin, pointer data) +{ + DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); + + if (pDRIDrawablePriv) { + ScreenPtr pScreen = pWin->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (RegionNumRects(&pWin->clipList) > 0) { + WindowPtr *pDRIWindows = (WindowPtr*)data; + int i = 0; + + while (pDRIWindows[i]) + i++; + + pDRIWindows[i] = pWin; + + pDRIPriv->nrWalked++; + } + + if (pDRIPriv->nrWindows == pDRIPriv->nrWalked) + return WT_STOPWALKING; + } + + return WT_WALKCHILDREN; +} + +static void +DRIDriverClipNotify(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (pDRIPriv->pDriverInfo->ClipNotify) { + WindowPtr *pDRIWindows = calloc(sizeof(WindowPtr), pDRIPriv->nrWindows); + DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; + + if (pDRIPriv->nrWindows > 0) { + pDRIPriv->nrWalked = 0; + TraverseTree(pScreen->root, DRIDCNTreeTraversal, + (pointer)pDRIWindows); + } + + pDRIInfo->ClipNotify(pScreen, pDRIWindows, pDRIPriv->nrWindows); + + free(pDRIWindows); + } +} + +static void +DRIIncreaseNumberVisible(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + switch (++pDRIPriv->nrWindowsVisible) { + case 1: + DRITransitionTo3d( pScreen ); + break; + case 2: + DRITransitionToSharedBuffers( pScreen ); + break; + default: + break; + } + + DRIDriverClipNotify(pScreen); +} + +static void +DRIDecreaseNumberVisible(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + switch (--pDRIPriv->nrWindowsVisible) { + case 0: + DRITransitionTo2d( pScreen ); + break; + case 1: + DRITransitionToPrivateBuffers( pScreen ); + break; + default: + break; + } + + DRIDriverClipNotify(pScreen); +} + +Bool +DRICreateDrawable(ScreenPtr pScreen, ClientPtr client, DrawablePtr pDrawable, + drm_drawable_t * hHWDrawable) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIDrawablePrivPtr pDRIDrawablePriv; + WindowPtr pWin; + + if (pDrawable->type == DRAWABLE_WINDOW) { + pWin = (WindowPtr)pDrawable; + if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { + pDRIDrawablePriv->refCount++; + + if (!pDRIDrawablePriv->hwDrawable) { + drmCreateDrawable(pDRIPriv->drmFD, &pDRIDrawablePriv->hwDrawable); + } + } + else { + /* allocate a DRI Window Private record */ + if (!(pDRIDrawablePriv = malloc(sizeof(DRIDrawablePrivRec)))) { + return FALSE; + } + + /* Only create a drm_drawable_t once */ + if (drmCreateDrawable(pDRIPriv->drmFD, + &pDRIDrawablePriv->hwDrawable)) { + free(pDRIDrawablePriv); + return FALSE; + } + + /* add it to the list of DRI drawables for this screen */ + pDRIDrawablePriv->pScreen = pScreen; + pDRIDrawablePriv->refCount = 1; + pDRIDrawablePriv->drawableIndex = -1; + pDRIDrawablePriv->nrects = RegionNumRects(&pWin->clipList); + + /* save private off of preallocated index */ + dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, + pDRIDrawablePriv); + pDRIPriv->nrWindows++; + + if (pDRIDrawablePriv->nrects) + DRIIncreaseNumberVisible(pScreen); + } + + /* track this in case the client dies */ + AddResource(FakeClientID(client->index), DRIDrawablePrivResType, + (pointer)(intptr_t)pDrawable->id); + + if (pDRIDrawablePriv->hwDrawable) { + drmUpdateDrawableInfo(pDRIPriv->drmFD, + pDRIDrawablePriv->hwDrawable, + DRM_DRAWABLE_CLIPRECTS, + RegionNumRects(&pWin->clipList), + RegionRects(&pWin->clipList)); + *hHWDrawable = pDRIDrawablePriv->hwDrawable; + } + } + else if (pDrawable->type != DRAWABLE_PIXMAP) { /* PBuffer */ + /* NOT_DONE */ + return FALSE; + } + + return TRUE; +} + +static void +DRIDrawablePrivDestroy(WindowPtr pWin) +{ + DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); + ScreenPtr pScreen; + DRIScreenPrivPtr pDRIPriv; + + if (!pDRIDrawablePriv) + return; + + pScreen = pWin->drawable.pScreen; + pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (pDRIDrawablePriv->drawableIndex != -1) { + /* bump stamp to force outstanding 3D requests to resync */ + pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp + = DRIDrawableValidationStamp++; + + /* release drawable table entry */ + pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL; + } + + pDRIPriv->nrWindows--; + + if (pDRIDrawablePriv->nrects) + DRIDecreaseNumberVisible(pScreen); + + drmDestroyDrawable(pDRIPriv->drmFD, pDRIDrawablePriv->hwDrawable); + + free(pDRIDrawablePriv); + dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL); +} + +static Bool +DRIDestroyDrawableCB(pointer value, XID id, pointer data) +{ + if (value == data) { + /* This calls back DRIDrawablePrivDelete which frees private area */ + FreeResourceByType(id, DRIDrawablePrivResType, FALSE); + + return TRUE; + } + + return FALSE; +} + +Bool +DRIDestroyDrawable(ScreenPtr pScreen, ClientPtr client, DrawablePtr pDrawable) +{ + if (pDrawable->type == DRAWABLE_WINDOW) { + LookupClientResourceComplex(client, DRIDrawablePrivResType, + DRIDestroyDrawableCB, + (pointer)(intptr_t)pDrawable->id); + } + else { /* pixmap (or for GLX 1.3, a PBuffer) */ + /* NOT_DONE */ + return FALSE; + } + + return TRUE; +} + +Bool +DRIDrawablePrivDelete(pointer pResource, XID id) +{ + WindowPtr pWin; + int rc; + + /* For DRIDrawablePrivResType, the XID is the client's fake ID. The + * important XID is the value in pResource. */ + id = (XID)(intptr_t)pResource; + rc = dixLookupWindow(&pWin, id, serverClient, DixGetAttrAccess); + + if (rc == Success) { + DRIDrawablePrivPtr pDRIDrwPriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); + + if (!pDRIDrwPriv) + return FALSE; + + if (--pDRIDrwPriv->refCount == 0) + DRIDrawablePrivDestroy(pWin); + + return TRUE; + } + else { /* pixmap (or for GLX 1.3, a PBuffer) */ + /* NOT_DONE */ + return FALSE; + } +} + +Bool +DRIGetDrawableInfo(ScreenPtr pScreen, + DrawablePtr pDrawable, + unsigned int* index, + unsigned int* stamp, + int* X, + int* Y, + int* W, + int* H, + int* numClipRects, + drm_clip_rect_t ** pClipRects, + int* backX, + int* backY, + int* numBackClipRects, + drm_clip_rect_t ** pBackClipRects) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIDrawablePrivPtr pDRIDrawablePriv, pOldDrawPriv; + WindowPtr pWin, pOldWin; + int i; + +#if 0 + printf("maxDrawableTableEntry = %d\n", pDRIPriv->pDriverInfo->maxDrawableTableEntry); +#endif + + if (pDrawable->type == DRAWABLE_WINDOW) { + pWin = (WindowPtr)pDrawable; + if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { + + /* Manage drawable table */ + if (pDRIDrawablePriv->drawableIndex == -1) { /* load SAREA table */ + + /* Search table for empty entry */ + i = 0; + while (i < pDRIPriv->pDriverInfo->maxDrawableTableEntry) { + if (!(pDRIPriv->DRIDrawables[i])) { + pDRIPriv->DRIDrawables[i] = pDrawable; + pDRIDrawablePriv->drawableIndex = i; + pDRIPriv->pSAREA->drawableTable[i].stamp = + DRIDrawableValidationStamp++; + break; + } + i++; + } + + /* Search table for oldest entry */ + if (i == pDRIPriv->pDriverInfo->maxDrawableTableEntry) { + unsigned int oldestStamp = ~0; + int oldestIndex = 0; + i = pDRIPriv->pDriverInfo->maxDrawableTableEntry; + while (i--) { + if (pDRIPriv->pSAREA->drawableTable[i].stamp < + oldestStamp) { + oldestIndex = i; + oldestStamp = + pDRIPriv->pSAREA->drawableTable[i].stamp; + } + } + pDRIDrawablePriv->drawableIndex = oldestIndex; + + /* release oldest drawable table entry */ + pOldWin = (WindowPtr)pDRIPriv->DRIDrawables[oldestIndex]; + pOldDrawPriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pOldWin); + pOldDrawPriv->drawableIndex = -1; + + /* claim drawable table entry */ + pDRIPriv->DRIDrawables[oldestIndex] = pDrawable; + + /* validate SAREA entry */ + pDRIPriv->pSAREA->drawableTable[oldestIndex].stamp = + DRIDrawableValidationStamp++; + + /* check for stamp wrap around */ + if (oldestStamp > DRIDrawableValidationStamp) { + + /* walk SAREA table and invalidate all drawables */ + for( i=0; + i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; + i++) { + pDRIPriv->pSAREA->drawableTable[i].stamp = + DRIDrawableValidationStamp++; + } + } + } + + /* If the driver wants to be notified when the index is + * set for a drawable, let it know now. + */ + if (pDRIPriv->pDriverInfo->SetDrawableIndex) + pDRIPriv->pDriverInfo->SetDrawableIndex(pWin, + pDRIDrawablePriv->drawableIndex); + + /* reinit drawable ID if window is visible */ + if ((pWin->viewable) && + (pDRIPriv->pDriverInfo->bufferRequests != DRI_NO_WINDOWS)) + { + (*pDRIPriv->pDriverInfo->InitBuffers)(pWin, + &pWin->clipList, pDRIDrawablePriv->drawableIndex); + } + } + + *index = pDRIDrawablePriv->drawableIndex; + *stamp = pDRIPriv->pSAREA->drawableTable[*index].stamp; + *X = (int)(pWin->drawable.x); + *Y = (int)(pWin->drawable.y); + *W = (int)(pWin->drawable.width); + *H = (int)(pWin->drawable.height); + *numClipRects = RegionNumRects(&pWin->clipList); + *pClipRects = (drm_clip_rect_t *)RegionRects(&pWin->clipList); + + if (!*numClipRects && pDRIPriv->fullscreen) { + /* use fake full-screen clip rect */ + pDRIPriv->fullscreen_rect.x1 = *X; + pDRIPriv->fullscreen_rect.y1 = *Y; + pDRIPriv->fullscreen_rect.x2 = *X + *W; + pDRIPriv->fullscreen_rect.y2 = *Y + *H; + + *numClipRects = 1; + *pClipRects = &pDRIPriv->fullscreen_rect; + } + + *backX = *X; + *backY = *Y; + + if (pDRIPriv->nrWindowsVisible == 1 && *numClipRects) { + /* Use a single cliprect. */ + + int x0 = *X; + int y0 = *Y; + int x1 = x0 + *W; + int y1 = y0 + *H; + + if (x0 < 0) x0 = 0; + if (y0 < 0) y0 = 0; + if (x1 > pScreen->width) x1 = pScreen->width; + if (y1 > pScreen->height) y1 = pScreen->height; + + if (y0 >= y1 || x0 >= x1) { + *numBackClipRects = 0; + *pBackClipRects = NULL; + } else { + pDRIPriv->private_buffer_rect.x1 = x0; + pDRIPriv->private_buffer_rect.y1 = y0; + pDRIPriv->private_buffer_rect.x2 = x1; + pDRIPriv->private_buffer_rect.y2 = y1; + + *numBackClipRects = 1; + *pBackClipRects = &(pDRIPriv->private_buffer_rect); + } + } else { + /* Use the frontbuffer cliprects for back buffers. */ + *numBackClipRects = 0; + *pBackClipRects = 0; + } + } + else { + /* Not a DRIDrawable */ + return FALSE; + } + } + else { /* pixmap (or for GLX 1.3, a PBuffer) */ + /* NOT_DONE */ + return FALSE; + } + + return TRUE; +} + +Bool +DRIGetDeviceInfo(ScreenPtr pScreen, + drm_handle_t * hFrameBuffer, + int* fbOrigin, + int* fbSize, + int* fbStride, + int* devPrivateSize, + void** pDevPrivate) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + *hFrameBuffer = pDRIPriv->pDriverInfo->hFrameBuffer; + *fbOrigin = 0; + *fbSize = pDRIPriv->pDriverInfo->frameBufferSize; + *fbStride = pDRIPriv->pDriverInfo->frameBufferStride; + *devPrivateSize = pDRIPriv->pDriverInfo->devPrivateSize; + *pDevPrivate = pDRIPriv->pDriverInfo->devPrivate; + + return TRUE; +} + +DRIInfoPtr +DRICreateInfoRec(void) +{ + DRIInfoPtr inforec = (DRIInfoPtr)calloc(1, sizeof(DRIInfoRec)); + if (!inforec) return NULL; + + /* Initialize defaults */ + inforec->busIdString = NULL; + + /* Wrapped function defaults */ + inforec->wrap.WakeupHandler = DRIDoWakeupHandler; + inforec->wrap.BlockHandler = DRIDoBlockHandler; + inforec->wrap.WindowExposures = DRIWindowExposures; + inforec->wrap.CopyWindow = DRICopyWindow; + inforec->wrap.ValidateTree = DRIValidateTree; + inforec->wrap.PostValidateTree = DRIPostValidateTree; + inforec->wrap.ClipNotify = DRIClipNotify; + inforec->wrap.AdjustFrame = DRIAdjustFrame; + + inforec->TransitionTo2d = 0; + inforec->TransitionTo3d = 0; + inforec->SetDrawableIndex = 0; + + return inforec; +} + +void +DRIDestroyInfoRec(DRIInfoPtr DRIInfo) +{ + free(DRIInfo->busIdString); + free((char*)DRIInfo); +} + + +void +DRIWakeupHandler(pointer wakeupData, int result, pointer pReadmask) +{ + int i; + + for (i = 0; i < screenInfo.numScreens; i++) { + ScreenPtr pScreen = screenInfo.screens[i]; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (pDRIPriv && + pDRIPriv->pDriverInfo->wrap.WakeupHandler) + (*pDRIPriv->pDriverInfo->wrap.WakeupHandler)(i, wakeupData, + result, pReadmask); + } +} + +void +DRIBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask) +{ + int i; + + for (i = 0; i < screenInfo.numScreens; i++) { + ScreenPtr pScreen = screenInfo.screens[i]; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (pDRIPriv && + pDRIPriv->pDriverInfo->wrap.BlockHandler) + (*pDRIPriv->pDriverInfo->wrap.BlockHandler)(i, blockData, + pTimeout, pReadmask); + } +} + +void +DRIDoWakeupHandler(int screenNum, pointer wakeupData, + unsigned long result, pointer pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[screenNum]; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + DRILock(pScreen, 0); + if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { + /* hide X context by swapping 2D component here */ + (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, + DRI_3D_SYNC, + DRI_2D_CONTEXT, + pDRIPriv->partial3DContextStore, + DRI_2D_CONTEXT, + pDRIPriv->hiddenContextStore); + } +} + +void +DRIDoBlockHandler(int screenNum, pointer blockData, + pointer pTimeout, pointer pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[screenNum]; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { + /* hide X context by swapping 2D component here */ + (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, + DRI_2D_SYNC, + DRI_NO_CONTEXT, + NULL, + DRI_2D_CONTEXT, + pDRIPriv->partial3DContextStore); + } + + if (pDRIPriv->windowsTouched) + DRM_SPINUNLOCK(&pDRIPriv->pSAREA->drawable_lock, 1); + pDRIPriv->windowsTouched = FALSE; + + DRIUnlock(pScreen); +} + +void +DRISwapContext(int drmFD, void *oldctx, void *newctx) +{ + DRIContextPrivPtr oldContext = (DRIContextPrivPtr)oldctx; + DRIContextPrivPtr newContext = (DRIContextPrivPtr)newctx; + ScreenPtr pScreen = newContext->pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + void* oldContextStore = NULL; + DRIContextType oldContextType; + void* newContextStore = NULL; + DRIContextType newContextType; + DRISyncType syncType; +#ifdef DEBUG + static int count = 0; + + if (!newContext) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[DRI] Context Switch Error: oldContext=%x, newContext=%x\n", + oldContext, newContext); + return; + } + + /* usefull for debugging, just print out after n context switches */ + if (!count || !(count % 1)) { + DRIDrvMsg(pScreen->myNum, X_INFO, + "[DRI] Context switch %5d from %p/0x%08x (%d)\n", + count, + oldContext, + oldContext ? oldContext->flags : 0, + oldContext ? oldContext->hwContext : -1); + DRIDrvMsg(pScreen->myNum, X_INFO, + "[DRI] Context switch %5d to %p/0x%08x (%d)\n", + count, + newContext, + newContext ? newContext->flags : 0, + newContext ? newContext->hwContext : -1); + } + ++count; +#endif + + if (!pDRIPriv->pDriverInfo->SwapContext) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[DRI] DDX driver missing context swap call back\n"); + return; + } + + if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { + + /* only 3D contexts are swapped in this case */ + if (oldContext) { + oldContextStore = DRIGetContextStore(oldContext); + oldContext->valid3D = TRUE; + oldContextType = DRI_3D_CONTEXT; + } else { + oldContextType = DRI_NO_CONTEXT; + } + newContextStore = DRIGetContextStore(newContext); + if ((newContext->valid3D) && + (newContext->hwContext != pDRIPriv->myContext)) { + newContextType = DRI_3D_CONTEXT; + } + else { + newContextType = DRI_2D_CONTEXT; + } + syncType = DRI_3D_SYNC; + } + else /* default: driverSwapMethod == DRI_SERVER_SWAP */ { + + /* optimize 2D context swaps */ + + if (newContext->flags & DRI_CONTEXT_2DONLY) { + /* go from 3D context to 2D context and only save 2D + * subset of 3D state + */ + oldContextStore = DRIGetContextStore(oldContext); + oldContextType = DRI_2D_CONTEXT; + newContextStore = DRIGetContextStore(newContext); + newContextType = DRI_2D_CONTEXT; + syncType = DRI_3D_SYNC; + pDRIPriv->lastPartial3DContext = oldContext; + } + else if (oldContext->flags & DRI_CONTEXT_2DONLY) { + if (pDRIPriv->lastPartial3DContext == newContext) { + /* go from 2D context back to previous 3D context and + * only restore 2D subset of previous 3D state + */ + oldContextStore = DRIGetContextStore(oldContext); + oldContextType = DRI_2D_CONTEXT; + newContextStore = DRIGetContextStore(newContext); + newContextType = DRI_2D_CONTEXT; + syncType = DRI_2D_SYNC; + } + else { + /* go from 2D context to a different 3D context */ + + /* call DDX driver to do partial restore */ + oldContextStore = DRIGetContextStore(oldContext); + newContextStore = + DRIGetContextStore(pDRIPriv->lastPartial3DContext); + (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, + DRI_2D_SYNC, + DRI_2D_CONTEXT, + oldContextStore, + DRI_2D_CONTEXT, + newContextStore); + + /* now setup for a complete 3D swap */ + oldContextStore = newContextStore; + oldContext->valid3D = TRUE; + oldContextType = DRI_3D_CONTEXT; + newContextStore = DRIGetContextStore(newContext); + if ((newContext->valid3D) && + (newContext->hwContext != pDRIPriv->myContext)) { + newContextType = DRI_3D_CONTEXT; + } + else { + newContextType = DRI_2D_CONTEXT; + } + syncType = DRI_NO_SYNC; + } + } + else { + /* now setup for a complete 3D swap */ + oldContextStore = newContextStore; + oldContext->valid3D = TRUE; + oldContextType = DRI_3D_CONTEXT; + newContextStore = DRIGetContextStore(newContext); + if ((newContext->valid3D) && + (newContext->hwContext != pDRIPriv->myContext)) { + newContextType = DRI_3D_CONTEXT; + } + else { + newContextType = DRI_2D_CONTEXT; + } + syncType = DRI_3D_SYNC; + } + } + + /* call DDX driver to perform the swap */ + (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, + syncType, + oldContextType, + oldContextStore, + newContextType, + newContextStore); +} + +void* +DRIGetContextStore(DRIContextPrivPtr context) +{ + return((void *)context->pContextStore); +} + +void +DRIWindowExposures(WindowPtr pWin, RegionPtr prgn, RegionPtr bsreg) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); + + if(pDRIDrawablePriv) { + (*pDRIPriv->pDriverInfo->InitBuffers)(pWin, prgn, + pDRIDrawablePriv->drawableIndex); + } + + /* call lower wrapped functions */ + if (pDRIPriv && pDRIPriv->wrap.WindowExposures) { + + /* unwrap */ + pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures; + + /* call lower layers */ + (*pScreen->WindowExposures)(pWin, prgn, bsreg); + + /* rewrap */ + pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; + pScreen->WindowExposures = DRIWindowExposures; + } +} + + +static int +DRITreeTraversal(WindowPtr pWin, pointer data) +{ + DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); + + if(pDRIDrawablePriv) { + ScreenPtr pScreen = pWin->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if(RegionNumRects(&(pWin->clipList)) > 0) { + RegionPtr reg = (RegionPtr)data; + + RegionUnion(reg, reg, &(pWin->clipList)); + pDRIPriv->nrWalked++; + } + + if(pDRIPriv->nrWindows == pDRIPriv->nrWalked) + return WT_STOPWALKING; + } + return WT_WALKCHILDREN; +} + +Bool +DRIDestroyWindow(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + Bool retval = TRUE; + + DRIDrawablePrivDestroy(pWin); + + /* call lower wrapped functions */ + if(pDRIPriv->DestroyWindow) { + /* unwrap */ + pScreen->DestroyWindow = pDRIPriv->DestroyWindow; + + /* call lower layers */ + retval = (*pScreen->DestroyWindow)(pWin); + + /* rewrap */ + pDRIPriv->DestroyWindow = pScreen->DestroyWindow; + pScreen->DestroyWindow = DRIDestroyWindow; + } + + return retval; +} + +void +DRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if(!pDRIPriv) return; + + if(pDRIPriv->nrWindowsVisible > 0) { + RegionRec reg; + + RegionNull(®); + pDRIPriv->nrWalked = 0; + TraverseTree(pWin, DRITreeTraversal, (pointer)(®)); + + if(RegionNotEmpty(®)) { + RegionTranslate(®, ptOldOrg.x - pWin->drawable.x, + ptOldOrg.y - pWin->drawable.y); + RegionIntersect(®, ®, prgnSrc); + + /* The MoveBuffers interface is not ideal */ + (*pDRIPriv->pDriverInfo->MoveBuffers)(pWin, ptOldOrg, ®, + pDRIPriv->pDriverInfo->ddxDrawableTableEntry); + } + + RegionUninit(®); + } + + /* call lower wrapped functions */ + if(pDRIPriv->wrap.CopyWindow) { + /* unwrap */ + pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow; + + /* call lower layers */ + (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc); + + /* rewrap */ + pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; + pScreen->CopyWindow = DRICopyWindow; + } +} + +static void +DRIGetSecs(long *secs, long *usecs) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + *secs = tv.tv_sec; + *usecs = tv.tv_usec; +} + +static unsigned long +DRIComputeMilliSeconds(unsigned long s_secs, unsigned long s_usecs, + unsigned long f_secs, unsigned long f_usecs) +{ + if (f_usecs < s_usecs) { + --f_secs; + f_usecs += 1000000; + } + return (f_secs - s_secs) * 1000 + (f_usecs - s_usecs) / 1000; +} + +static void +DRISpinLockTimeout(drmLock *lock, int val, unsigned long timeout /* in mS */) +{ + int count = 10000; +#if !defined(__alpha__) && !defined(__powerpc__) + char ret; +#else + int ret; +#endif + long s_secs, s_usecs; + long f_secs, f_usecs; + long msecs; + long prev = 0; + + DRIGetSecs(&s_secs, &s_usecs); + + do { + DRM_SPINLOCK_COUNT(lock, val, count, ret); + if (!ret) return; /* Got lock */ + DRIGetSecs(&f_secs, &f_usecs); + msecs = DRIComputeMilliSeconds(s_secs, s_usecs, f_secs, f_usecs); + if (msecs - prev < 250) count *= 2; /* Not more than 0.5S */ + } while (msecs < timeout); + + /* Didn't get lock, so take it. The worst + that can happen is that there is some + garbage written to the wrong part of the + framebuffer that a refresh will repair. + That's undesirable, but better than + locking the server. This should be a + very rare event. */ + DRM_SPINLOCK_TAKE(lock, val); +} + +static void +DRILockTree(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if(!pDRIPriv) return; + + /* Restore the last known 3D context if the X context is hidden */ + if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { + (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, + DRI_2D_SYNC, + DRI_NO_CONTEXT, + NULL, + DRI_2D_CONTEXT, + pDRIPriv->partial3DContextStore); + } + + /* Call kernel to release lock */ + DRIUnlock(pScreen); + + /* Grab drawable spin lock: a time out between 10 and 30 seconds is + appropriate, since this should never time out except in the case of + client death while the lock is being held. The timeout must be + greater than any reasonable rendering time. */ + DRISpinLockTimeout(&pDRIPriv->pSAREA->drawable_lock, 1, 10000); /*10 secs*/ + + /* Call kernel flush outstanding buffers and relock */ + DRILock(pScreen, DRM_LOCK_QUIESCENT|DRM_LOCK_FLUSH_ALL); + + /* Switch back to our 2D context if the X context is hidden */ + if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { + /* hide X context by swapping 2D component here */ + (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, + DRI_3D_SYNC, + DRI_2D_CONTEXT, + pDRIPriv->partial3DContextStore, + DRI_2D_CONTEXT, + pDRIPriv->hiddenContextStore); + } +} + +int +DRIValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) +{ + ScreenPtr pScreen = pParent->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + int returnValue = 1; /* always return 1, not checked by dix/window.c */ + + if(!pDRIPriv) return returnValue; + + /* call lower wrapped functions */ + if(pDRIPriv->wrap.ValidateTree) { + /* unwrap */ + pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree; + + /* call lower layers */ + returnValue = (*pScreen->ValidateTree)(pParent, pChild, kind); + + /* rewrap */ + pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree; + pScreen->ValidateTree = DRIValidateTree; + } + + return returnValue; +} + +void +DRIPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) +{ + ScreenPtr pScreen; + DRIScreenPrivPtr pDRIPriv; + + if (pParent) { + pScreen = pParent->drawable.pScreen; + } else { + pScreen = pChild->drawable.pScreen; + } + if(!(pDRIPriv = DRI_SCREEN_PRIV(pScreen))) return; + + if (pDRIPriv->wrap.PostValidateTree) { + /* unwrap */ + pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree; + + /* call lower layers */ + (*pScreen->PostValidateTree)(pParent, pChild, kind); + + /* rewrap */ + pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree; + pScreen->PostValidateTree = DRIPostValidateTree; + } +} + +void +DRIClipNotify(WindowPtr pWin, int dx, int dy) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIDrawablePrivPtr pDRIDrawablePriv; + + if(!pDRIPriv) return; + + if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { + int nrects = RegionNumRects(&pWin->clipList); + + if(!pDRIPriv->windowsTouched) { + DRILockTree(pScreen); + pDRIPriv->windowsTouched = TRUE; + } + + if (nrects && !pDRIDrawablePriv->nrects) + DRIIncreaseNumberVisible(pScreen); + else if (!nrects && pDRIDrawablePriv->nrects) + DRIDecreaseNumberVisible(pScreen); + else + DRIDriverClipNotify(pScreen); + + pDRIDrawablePriv->nrects = nrects; + + pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp + = DRIDrawableValidationStamp++; + + drmUpdateDrawableInfo(pDRIPriv->drmFD, pDRIDrawablePriv->hwDrawable, + DRM_DRAWABLE_CLIPRECTS, + nrects, RegionRects(&pWin->clipList)); + } + + /* call lower wrapped functions */ + if(pDRIPriv->wrap.ClipNotify) { + + /* unwrap */ + pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify; + + /* call lower layers */ + (*pScreen->ClipNotify)(pWin, dx, dy); + + /* rewrap */ + pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; + pScreen->ClipNotify = DRIClipNotify; + } +} + +CARD32 +DRIGetDrawableIndex(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); + CARD32 index; + + if (pDRIDrawablePriv) { + index = pDRIDrawablePriv->drawableIndex; + } + else { + index = pDRIPriv->pDriverInfo->ddxDrawableTableEntry; + } + + return index; +} + +unsigned int +DRIGetDrawableStamp(ScreenPtr pScreen, CARD32 drawable_index) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + return pDRIPriv->pSAREA->drawableTable[drawable_index].stamp; +} + + +void +DRIPrintDrawableLock(ScreenPtr pScreen, char *msg) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + ErrorF("%s: %d\n", msg, pDRIPriv->pSAREA->drawable_lock.lock); +} + +void +DRILock(ScreenPtr pScreen, int flags) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if(!pDRIPriv || !pDRIPriv->pLockRefCount) return; + + if (!*pDRIPriv->pLockRefCount) { + DRM_LOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext, flags); + *pDRIPriv->pLockingContext = pDRIPriv->myContext; + } else if (*pDRIPriv->pLockingContext != pDRIPriv->myContext) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[DRI] Locking deadlock.\n" + "\tAlready locked with context %d,\n" + "\ttrying to lock with context %d.\n", + pDRIPriv->pLockingContext, + pDRIPriv->myContext); + } + (*pDRIPriv->pLockRefCount)++; +} + +void +DRIUnlock(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if(!pDRIPriv || !pDRIPriv->pLockRefCount) return; + + if (*pDRIPriv->pLockRefCount > 0) { + if (pDRIPriv->myContext != *pDRIPriv->pLockingContext) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[DRI] Unlocking inconsistency:\n" + "\tContext %d trying to unlock lock held by context %d\n", + pDRIPriv->pLockingContext, + pDRIPriv->myContext); + } + (*pDRIPriv->pLockRefCount)--; + } else { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "DRIUnlock called when not locked.\n"); + return; + } + if (! *pDRIPriv->pLockRefCount) + DRM_UNLOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext); +} + +void * +DRIGetSAREAPrivate(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + if (!pDRIPriv) return 0; + + return (void *)(((char*)pDRIPriv->pSAREA)+sizeof(XF86DRISAREARec)); +} + +drm_context_t +DRIGetContext(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + if (!pDRIPriv) return 0; + + return pDRIPriv->myContext; +} + +void +DRIGetTexOffsetFuncs(ScreenPtr pScreen, + DRITexOffsetStartProcPtr *texOffsetStartFunc, + DRITexOffsetFinishProcPtr *texOffsetFinishFunc) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (!pDRIPriv) return; + + *texOffsetStartFunc = pDRIPriv->pDriverInfo->texOffsetStart; + *texOffsetFinishFunc = pDRIPriv->pDriverInfo->texOffsetFinish; +} + +/* This lets get at the unwrapped functions so that they can correctly + * call the lowerlevel functions, and choose whether they will be + * called at every level of recursion (eg in validatetree). + */ +DRIWrappedFuncsRec * +DRIGetWrappedFuncs(ScreenPtr pScreen) +{ + return &(DRI_SCREEN_PRIV(pScreen)->wrap); +} + +/* note that this returns the library version, not the protocol version */ +void +DRIQueryVersion(int *majorVersion, + int *minorVersion, + int *patchVersion) +{ + *majorVersion = DRIINFO_MAJOR_VERSION; + *minorVersion = DRIINFO_MINOR_VERSION; + *patchVersion = DRIINFO_PATCH_VERSION; +} + +static void +_DRIAdjustFrame(ScrnInfoPtr pScrn, DRIScreenPrivPtr pDRIPriv, int x, int y) +{ + pDRIPriv->pSAREA->frame.x = x; + pDRIPriv->pSAREA->frame.y = y; + pDRIPriv->pSAREA->frame.width = pScrn->frameX1 - x + 1; + pDRIPriv->pSAREA->frame.height = pScrn->frameY1 - y + 1; +} + +void +DRIAdjustFrame(int scrnIndex, int x, int y, int flags) +{ + ScreenPtr pScreen = screenInfo.screens[scrnIndex]; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + int px, py; + + if (!pDRIPriv || !pDRIPriv->pSAREA) { + DRIDrvMsg(scrnIndex, X_ERROR, "[DRI] No SAREA (%p %p)\n", + pDRIPriv, pDRIPriv ? pDRIPriv->pSAREA : NULL); + return; + } + + if (pDRIPriv->fullscreen) { + /* Fix up frame */ + pScrn->frameX0 = pDRIPriv->pSAREA->frame.x; + pScrn->frameY0 = pDRIPriv->pSAREA->frame.y; + pScrn->frameX1 = pScrn->frameX0 + pDRIPriv->pSAREA->frame.width - 1; + pScrn->frameY1 = pScrn->frameY0 + pDRIPriv->pSAREA->frame.height - 1; + + /* Fix up cursor */ + miPointerGetPosition(inputInfo.pointer, &px, &py); + if (px < pScrn->frameX0) px = pScrn->frameX0; + if (px > pScrn->frameX1) px = pScrn->frameX1; + if (py < pScrn->frameY0) py = pScrn->frameY0; + if (py > pScrn->frameY1) py = pScrn->frameY1; + pScreen->SetCursorPosition(inputInfo.pointer, pScreen, px, py, TRUE); + return; + } + + if (pDRIPriv->wrap.AdjustFrame) { + /* unwrap */ + pScrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame; + /* call lower layers */ + (*pScrn->AdjustFrame)(scrnIndex, x, y, flags); + /* rewrap */ + pDRIPriv->wrap.AdjustFrame = pScrn->AdjustFrame; + pScrn->AdjustFrame = DRIAdjustFrame; + } + + _DRIAdjustFrame(pScrn, pDRIPriv, x, y); +} + +/* + * DRIMoveBuffersHelper swaps the regions rects in place leaving you + * a region with the rects in the order that you need to blit them, + * but it is possibly (likely) an invalid region afterwards. If you + * need to use the region again for anything you have to call + * REGION_VALIDATE on it, or better yet, save a copy first. + */ + +void +DRIMoveBuffersHelper( + ScreenPtr pScreen, + int dx, + int dy, + int *xdir, + int *ydir, + RegionPtr reg +) +{ + BoxPtr extents, pbox, firstBox, lastBox; + BoxRec tmpBox; + int y, nbox; + + extents = RegionExtents(reg); + nbox = RegionNumRects(reg); + pbox = RegionRects(reg); + + if((dy > 0) && (dy < (extents->y2 - extents->y1))) { + *ydir = -1; + if(nbox > 1) { + firstBox = pbox; + lastBox = pbox + nbox - 1; + while((unsigned long)firstBox < (unsigned long)lastBox) { + tmpBox = *firstBox; + *firstBox = *lastBox; + *lastBox = tmpBox; + firstBox++; + lastBox--; + } + } + } else *ydir = 1; + + if((dx > 0) && (dx < (extents->x2 - extents->x1))) { + *xdir = -1; + if(nbox > 1) { + firstBox = lastBox = pbox; + y = pbox->y1; + while(--nbox) { + pbox++; + if(pbox->y1 == y) lastBox++; + else { + while((unsigned long)firstBox < (unsigned long)lastBox) { + tmpBox = *firstBox; + *firstBox = *lastBox; + *lastBox = tmpBox; + firstBox++; + lastBox--; + } + + firstBox = lastBox = pbox; + y = pbox->y1; + } + } + while((unsigned long)firstBox < (unsigned long)lastBox) { + tmpBox = *firstBox; + *firstBox = *lastBox; + *lastBox = tmpBox; + firstBox++; + lastBox--; + } + } + } else *xdir = 1; + +} + +char * +DRICreatePCIBusID(const struct pci_device * dev) +{ + char *busID; + + if (asprintf(&busID, "pci:%04x:%02x:%02x.%d", + dev->domain, dev->bus, dev->dev, dev->func) == -1) + return NULL; + + return busID; +} + +static void drmSIGIOHandler(int interrupt, void *closure) +{ + unsigned long key; + void *value; + ssize_t count; + drm_ctx_t ctx; + typedef void (*_drmCallback)(int, void *, void *); + char buf[256]; + drm_context_t old; + drm_context_t new; + void *oldctx; + void *newctx; + char *pt; + drmHashEntry *entry; + void *hash_table; + + hash_table = drmGetHashTable(); + + if (!hash_table) return; + if (drmHashFirst(hash_table, &key, &value)) { + entry = value; + do { +#if 0 + fprintf(stderr, "Trying %d\n", entry->fd); +#endif + if ((count = read(entry->fd, buf, sizeof(buf) - 1)) > 0) { + buf[count] = '\0'; +#if 0 + fprintf(stderr, "Got %s\n", buf); +#endif + + for (pt = buf; *pt != ' '; ++pt); /* Find first space */ + ++pt; + old = strtol(pt, &pt, 0); + new = strtol(pt, NULL, 0); + oldctx = drmGetContextTag(entry->fd, old); + newctx = drmGetContextTag(entry->fd, new); +#if 0 + fprintf(stderr, "%d %d %p %p\n", old, new, oldctx, newctx); +#endif + ((_drmCallback)entry->f)(entry->fd, oldctx, newctx); + ctx.handle = new; + ioctl(entry->fd, DRM_IOCTL_NEW_CTX, &ctx); + } + } while (drmHashNext(hash_table, &key, &value)); + } +} + + +int drmInstallSIGIOHandler(int fd, void (*f)(int, void *, void *)) +{ + drmHashEntry *entry; + + entry = drmGetEntry(fd); + entry->f = f; + + return xf86InstallSIGIOHandler(fd, drmSIGIOHandler, 0); +} + +int drmRemoveSIGIOHandler(int fd) +{ + drmHashEntry *entry = drmGetEntry(fd); + + entry->f = NULL; + + return xf86RemoveSIGIOHandler(fd); +} diff --git a/xorg-server/hw/xquartz/applewm.c b/xorg-server/hw/xquartz/applewm.c index d81032aa9..2f26e61d9 100644 --- a/xorg-server/hw/xquartz/applewm.c +++ b/xorg-server/hw/xquartz/applewm.c @@ -1,736 +1,736 @@ -/**************************************************************************
-
-Copyright (c) 2002-2007 Apple Inc. All Rights Reserved.
-Copyright (c) 2003 Torrey T. Lyons. 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, sub license, 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:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
-IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
-ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-#include "sanitizedCarbon.h"
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "quartzCommon.h"
-
-#include "misc.h"
-#include "dixstruct.h"
-#include "globals.h"
-#include "extnsionst.h"
-#include "colormapst.h"
-#include "cursorstr.h"
-#include "scrnintstr.h"
-#include "windowstr.h"
-#include "servermd.h"
-#include "swaprep.h"
-#include "propertyst.h"
-#include <X11/Xatom.h>
-#include "darwin.h"
-#define _APPLEWM_SERVER_
-#include <X11/extensions/applewmproto.h>
-#include "applewmExt.h"
-#include "X11Application.h"
-#include "protocol-versions.h"
-
-#define DEFINE_ATOM_HELPER(func,atom_name) \
-static Atom func (void) { \
- static int generation; \
- static Atom atom; \
- if (generation != serverGeneration) { \
- generation = serverGeneration; \
- atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \
- } \
- return atom; \
-}
-
-DEFINE_ATOM_HELPER(xa_native_screen_origin, "_NATIVE_SCREEN_ORIGIN")
-DEFINE_ATOM_HELPER (xa_apple_no_order_in, "_APPLE_NO_ORDER_IN")
-
-static AppleWMProcsPtr appleWMProcs;
-
-static int WMErrorBase;
-
-
-static unsigned char WMReqCode = 0;
-static int WMEventBase = 0;
-
-static RESTYPE ClientType, EventType; /* resource types for event masks */
-static XID eventResource;
-
-/* Currently selected events */
-static unsigned int eventMask = 0;
-
-static int WMFreeClient (pointer data, XID id);
-static int WMFreeEvents (pointer data, XID id);
-static void SNotifyEvent(xAppleWMNotifyEvent *from, xAppleWMNotifyEvent *to);
-
-typedef struct _WMEvent *WMEventPtr;
-typedef struct _WMEvent {
- WMEventPtr next;
- ClientPtr client;
- XID clientResource;
- unsigned int mask;
-} WMEventRec;
-
-static inline BoxRec
-make_box (int x, int y, int w, int h)
-{
- BoxRec r;
- r.x1 = x;
- r.y1 = y;
- r.x2 = x + w;
- r.y2 = y + h;
- return r;
-}
-
-/* Updates the _NATIVE_SCREEN_ORIGIN property on the given root window. */
-void
-AppleWMSetScreenOrigin(
- WindowPtr pWin
-)
-{
- int32_t data[2];
-
- data[0] = pWin->drawable.pScreen->x + darwinMainScreenX;
- data[1] = pWin->drawable.pScreen->y + darwinMainScreenY;
-
- dixChangeWindowProperty(serverClient, pWin, xa_native_screen_origin(),
- XA_INTEGER, 32, PropModeReplace, 2, data, TRUE);
-}
-
-/* Window managers can set the _APPLE_NO_ORDER_IN property on windows
- that are being genie-restored from the Dock. We want them to
- be mapped but remain ordered-out until the animation
- completes (when the Dock will order them in). */
-Bool
-AppleWMDoReorderWindow(
- WindowPtr pWin
-)
-{
- Atom atom;
- PropertyPtr prop;
- int rc;
-
- atom = xa_apple_no_order_in();
- rc = dixLookupProperty(&prop, pWin, atom, serverClient, DixReadAccess);
-
- if(Success == rc && prop->type == atom)
- return 0;
-
- return 1;
-}
-
-
-static int
-ProcAppleWMQueryVersion(
- register ClientPtr client
-)
-{
- xAppleWMQueryVersionReply rep;
- register int n;
-
- REQUEST_SIZE_MATCH(xAppleWMQueryVersionReq);
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- rep.majorVersion = SERVER_APPLEWM_MAJOR_VERSION;
- rep.minorVersion = SERVER_APPLEWM_MINOR_VERSION;
- rep.patchVersion = SERVER_APPLEWM_PATCH_VERSION;
- if (client->swapped) {
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- }
- WriteToClient(client, sizeof(xAppleWMQueryVersionReply), (char *)&rep);
- return Success;
-}
-
-
-/* events */
-
-static inline void
-updateEventMask (WMEventPtr *pHead)
-{
- WMEventPtr pCur;
-
- eventMask = 0;
- for (pCur = *pHead; pCur != NULL; pCur = pCur->next)
- eventMask |= pCur->mask;
-}
-
-/*ARGSUSED*/
-static int
-WMFreeClient (pointer data, XID id) {
- WMEventPtr pEvent;
- WMEventPtr *pHead, pCur, pPrev;
- int i;
-
- pEvent = (WMEventPtr) data;
- i = dixLookupResourceByType((pointer *)&pHead, eventResource, EventType, serverClient, DixReadAccess | DixWriteAccess | DixDestroyAccess);
- if (i == Success && pHead) {
- pPrev = 0;
- for (pCur = *pHead; pCur && pCur != pEvent; pCur=pCur->next)
- pPrev = pCur;
- if (pCur) {
- if (pPrev)
- pPrev->next = pEvent->next;
- else
- *pHead = pEvent->next;
- }
- updateEventMask (pHead);
- }
- free((pointer) pEvent);
- return 1;
-}
-
-/*ARGSUSED*/
-static int
-WMFreeEvents (pointer data, XID id) {
- WMEventPtr *pHead, pCur, pNext;
-
- pHead = (WMEventPtr *) data;
- for (pCur = *pHead; pCur; pCur = pNext) {
- pNext = pCur->next;
- FreeResource (pCur->clientResource, ClientType);
- free((pointer) pCur);
- }
- free((pointer) pHead);
- eventMask = 0;
- return 1;
-}
-
-static int
-ProcAppleWMSelectInput (register ClientPtr client)
-{
- REQUEST(xAppleWMSelectInputReq);
- WMEventPtr pEvent, pNewEvent, *pHead;
- XID clientResource;
- int i;
-
- REQUEST_SIZE_MATCH (xAppleWMSelectInputReq);
- i = dixLookupResourceByType((pointer *)&pHead, eventResource, EventType, client, DixWriteAccess);
- if (stuff->mask != 0) {
- if (i == Success && pHead) {
- /* check for existing entry. */
- for (pEvent = *pHead; pEvent; pEvent = pEvent->next)
- {
- if (pEvent->client == client)
- {
- pEvent->mask = stuff->mask;
- updateEventMask (pHead);
- return Success;
- }
- }
- }
-
- /* build the entry */
- pNewEvent = (WMEventPtr) malloc(sizeof (WMEventRec));
- if (!pNewEvent)
- return BadAlloc;
- pNewEvent->next = 0;
- pNewEvent->client = client;
- pNewEvent->mask = stuff->mask;
- /*
- * add a resource that will be deleted when
- * the client goes away
- */
- clientResource = FakeClientID (client->index);
- pNewEvent->clientResource = clientResource;
- if (!AddResource (clientResource, ClientType, (pointer)pNewEvent))
- return BadAlloc;
- /*
- * create a resource to contain a pointer to the list
- * of clients selecting input. This must be indirect as
- * the list may be arbitrarily rearranged which cannot be
- * done through the resource database.
- */
- if (i != Success || !pHead)
- {
- pHead = (WMEventPtr *) malloc(sizeof (WMEventPtr));
- if (!pHead ||
- !AddResource (eventResource, EventType, (pointer)pHead))
- {
- FreeResource (clientResource, RT_NONE);
- return BadAlloc;
- }
- *pHead = 0;
- }
- pNewEvent->next = *pHead;
- *pHead = pNewEvent;
- updateEventMask (pHead);
- } else if (stuff->mask == 0) {
- /* delete the interest */
- if (i == Success && pHead) {
- pNewEvent = 0;
- for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
- if (pEvent->client == client)
- break;
- pNewEvent = pEvent;
- }
- if (pEvent) {
- FreeResource (pEvent->clientResource, ClientType);
- if (pNewEvent)
- pNewEvent->next = pEvent->next;
- else
- *pHead = pEvent->next;
- free(pEvent);
- updateEventMask (pHead);
- }
- }
- } else {
- client->errorValue = stuff->mask;
- return BadValue;
- }
- return Success;
-}
-
-/*
- * deliver the event
- */
-
-void
-AppleWMSendEvent (int type, unsigned int mask, int which, int arg) {
- WMEventPtr *pHead, pEvent;
- xAppleWMNotifyEvent se;
- int i;
-
- i = dixLookupResourceByType((pointer *)&pHead, eventResource, EventType, serverClient, DixReadAccess);
- if (i != Success || !pHead)
- return;
- for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
- if ((pEvent->mask & mask) == 0)
- continue;
- se.type = type + WMEventBase;
- se.kind = which;
- se.arg = arg;
- se.time = currentTime.milliseconds;
- WriteEventsToClient (pEvent->client, 1, (xEvent *) &se);
- }
-}
-
-/* Safe to call from any thread. */
-unsigned int
-AppleWMSelectedEvents (void)
-{
- return eventMask;
-}
-
-
-/* general utility functions */
-
-static int
-ProcAppleWMDisableUpdate(
- register ClientPtr client
-)
-{
- REQUEST_SIZE_MATCH(xAppleWMDisableUpdateReq);
-
- appleWMProcs->DisableUpdate();
-
- return Success;
-}
-
-static int
-ProcAppleWMReenableUpdate(
- register ClientPtr client
-)
-{
- REQUEST_SIZE_MATCH(xAppleWMReenableUpdateReq);
-
- appleWMProcs->EnableUpdate();
-
- return Success;
-}
-
-
-/* window functions */
-
-static int
-ProcAppleWMSetWindowMenu(
- register ClientPtr client
-)
-{
- const char *bytes, **items;
- char *shortcuts;
- int max_len, nitems, i, j;
- REQUEST(xAppleWMSetWindowMenuReq);
-
- REQUEST_AT_LEAST_SIZE(xAppleWMSetWindowMenuReq);
-
- nitems = stuff->nitems;
- items = malloc(sizeof (char *) * nitems);
- shortcuts = malloc(sizeof (char) * nitems);
-
- max_len = (stuff->length << 2) - sizeof(xAppleWMSetWindowMenuReq);
- bytes = (char *) &stuff[1];
-
- for (i = j = 0; i < max_len && j < nitems;)
- {
- shortcuts[j] = bytes[i++];
- items[j++] = bytes + i;
-
- while (i < max_len)
- {
- if (bytes[i++] == 0)
- break;
- }
- }
- X11ApplicationSetWindowMenu (nitems, items, shortcuts);
- free(items);
- free(shortcuts);
-
- return Success;
-}
-
-static int
-ProcAppleWMSetWindowMenuCheck(
- register ClientPtr client
-)
-{
- REQUEST(xAppleWMSetWindowMenuCheckReq);
-
- REQUEST_SIZE_MATCH(xAppleWMSetWindowMenuCheckReq);
- X11ApplicationSetWindowMenuCheck(stuff->index);
- return Success;
-}
-
-static int
-ProcAppleWMSetFrontProcess(
- register ClientPtr client
-)
-{
- REQUEST_SIZE_MATCH(xAppleWMSetFrontProcessReq);
-
- X11ApplicationSetFrontProcess();
- return Success;
-}
-
-static int
-ProcAppleWMSetWindowLevel(register ClientPtr client)
-{
- REQUEST(xAppleWMSetWindowLevelReq);
- WindowPtr pWin;
- int err;
-
- REQUEST_SIZE_MATCH(xAppleWMSetWindowLevelReq);
-
- if (Success != dixLookupWindow(&pWin, stuff->window, client,
- DixReadAccess))
- return BadValue;
-
- if (stuff->level < 0 || stuff->level >= AppleWMNumWindowLevels) {
- return BadValue;
- }
-
- err = appleWMProcs->SetWindowLevel(pWin, stuff->level);
- if (err != Success) {
- return err;
- }
-
- return Success;
-}
-
-static int
-ProcAppleWMSendPSN(register ClientPtr client)
-{
- REQUEST(xAppleWMSendPSNReq);
- int err;
-
- REQUEST_SIZE_MATCH(xAppleWMSendPSNReq);
-
- if(!appleWMProcs->SendPSN)
- return BadRequest;
-
- err = appleWMProcs->SendPSN(stuff->psn_hi, stuff->psn_lo);
- if (err != Success) {
- return err;
- }
-
- return Success;
-}
-
-static int
-ProcAppleWMAttachTransient(register ClientPtr client)
-{
- WindowPtr pWinChild, pWinParent;
- REQUEST(xAppleWMAttachTransientReq);
- int err;
-
- REQUEST_SIZE_MATCH(xAppleWMAttachTransientReq);
-
- if(!appleWMProcs->AttachTransient)
- return BadRequest;
-
- if (Success != dixLookupWindow(&pWinChild, stuff->child, client, DixReadAccess))
- return BadValue;
-
- if(stuff->parent) {
- if(Success != dixLookupWindow(&pWinParent, stuff->parent, client, DixReadAccess))
- return BadValue;
- } else {
- pWinParent = NULL;
- }
-
- err = appleWMProcs->AttachTransient(pWinChild, pWinParent);
- if (err != Success) {
- return err;
- }
-
- return Success;
-}
-
-static int
-ProcAppleWMSetCanQuit(
- register ClientPtr client
-)
-{
- REQUEST(xAppleWMSetCanQuitReq);
-
- REQUEST_SIZE_MATCH(xAppleWMSetCanQuitReq);
-
- X11ApplicationSetCanQuit(stuff->state);
- return Success;
-}
-
-
-/* frame functions */
-
-static int
-ProcAppleWMFrameGetRect(
- register ClientPtr client
-)
-{
- xAppleWMFrameGetRectReply rep;
- BoxRec ir, or, rr;
- REQUEST(xAppleWMFrameGetRectReq);
-
- REQUEST_SIZE_MATCH(xAppleWMFrameGetRectReq);
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
-
- ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih);
- or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh);
-
- if (appleWMProcs->FrameGetRect(stuff->frame_rect,
- stuff->frame_class,
- &or, &ir, &rr) != Success)
- {
- return BadValue;
- }
-
- rep.x = rr.x1;
- rep.y = rr.y1;
- rep.w = rr.x2 - rr.x1;
- rep.h = rr.y2 - rr.y1;
-
- WriteToClient(client, sizeof(xAppleWMFrameGetRectReply), (char *)&rep);
- return Success;
-}
-
-static int
-ProcAppleWMFrameHitTest(
- register ClientPtr client
-)
-{
- xAppleWMFrameHitTestReply rep;
- BoxRec ir, or;
- int ret;
- REQUEST(xAppleWMFrameHitTestReq);
-
- REQUEST_SIZE_MATCH(xAppleWMFrameHitTestReq);
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
-
- ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih);
- or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh);
-
- if (appleWMProcs->FrameHitTest(stuff->frame_class, stuff->px,
- stuff->py, &or, &ir, &ret) != Success)
- {
- return BadValue;
- }
-
- rep.ret = ret;
-
- WriteToClient(client, sizeof(xAppleWMFrameHitTestReply), (char *)&rep);
- return Success;
-}
-
-static int
-ProcAppleWMFrameDraw(
- register ClientPtr client
-)
-{
- BoxRec ir, or;
- unsigned int title_length, title_max;
- unsigned char *title_bytes;
- REQUEST(xAppleWMFrameDrawReq);
- WindowPtr pWin;
-
- REQUEST_AT_LEAST_SIZE(xAppleWMFrameDrawReq);
-
- if (Success != dixLookupWindow(&pWin, stuff->window, client,
- DixReadAccess))
- return BadValue;
-
- ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih);
- or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh);
-
- title_length = stuff->title_length;
- title_max = (stuff->length << 2) - sizeof(xAppleWMFrameDrawReq);
-
- if (title_max < title_length)
- return BadValue;
-
- title_bytes = (unsigned char *) &stuff[1];
-
- errno = appleWMProcs->FrameDraw(pWin, stuff->frame_class,
- stuff->frame_attr, &or, &ir,
- title_length, title_bytes);
- if (errno != Success) {
- return errno;
- }
-
- return Success;
-}
-
-
-/* dispatch */
-
-static int
-ProcAppleWMDispatch (
- register ClientPtr client
-)
-{
- REQUEST(xReq);
-
- switch (stuff->data)
- {
- case X_AppleWMQueryVersion:
- return ProcAppleWMQueryVersion(client);
- }
-
- if (!LocalClient(client))
- return WMErrorBase + AppleWMClientNotLocal;
-
- switch (stuff->data)
- {
- case X_AppleWMSelectInput:
- return ProcAppleWMSelectInput(client);
- case X_AppleWMDisableUpdate:
- return ProcAppleWMDisableUpdate(client);
- case X_AppleWMReenableUpdate:
- return ProcAppleWMReenableUpdate(client);
- case X_AppleWMSetWindowMenu:
- return ProcAppleWMSetWindowMenu(client);
- case X_AppleWMSetWindowMenuCheck:
- return ProcAppleWMSetWindowMenuCheck(client);
- case X_AppleWMSetFrontProcess:
- return ProcAppleWMSetFrontProcess(client);
- case X_AppleWMSetWindowLevel:
- return ProcAppleWMSetWindowLevel(client);
- case X_AppleWMSetCanQuit:
- return ProcAppleWMSetCanQuit(client);
- case X_AppleWMFrameGetRect:
- return ProcAppleWMFrameGetRect(client);
- case X_AppleWMFrameHitTest:
- return ProcAppleWMFrameHitTest(client);
- case X_AppleWMFrameDraw:
- return ProcAppleWMFrameDraw(client);
- case X_AppleWMSendPSN:
- return ProcAppleWMSendPSN(client);
- case X_AppleWMAttachTransient:
- return ProcAppleWMAttachTransient(client);
- default:
- return BadRequest;
- }
-}
-
-static void
-SNotifyEvent(xAppleWMNotifyEvent *from, xAppleWMNotifyEvent *to) {
- to->type = from->type;
- to->kind = from->kind;
- cpswaps (from->sequenceNumber, to->sequenceNumber);
- cpswapl (from->time, to->time);
- cpswapl (from->arg, to->arg);
-}
-
-static int
-SProcAppleWMQueryVersion(
- register ClientPtr client
-)
-{
- register int n;
- REQUEST(xAppleWMQueryVersionReq);
- swaps(&stuff->length, n);
- return ProcAppleWMQueryVersion(client);
-}
-
-static int
-SProcAppleWMDispatch (
- register ClientPtr client
-)
-{
- REQUEST(xReq);
-
- /* It is bound to be non-local when there is byte swapping */
- if (!LocalClient(client))
- return WMErrorBase + AppleWMClientNotLocal;
-
- /* only local clients are allowed WM access */
- switch (stuff->data)
- {
- case X_AppleWMQueryVersion:
- return SProcAppleWMQueryVersion(client);
- default:
- return BadRequest;
- }
-}
-
-void
-AppleWMExtensionInit(
- AppleWMProcsPtr procsPtr)
-{
- ExtensionEntry* extEntry;
-
- ClientType = CreateNewResourceType(WMFreeClient, "WMClient");
- EventType = CreateNewResourceType(WMFreeEvents, "WMEvent");
- eventResource = FakeClientID(0);
-
- if (ClientType && EventType &&
- (extEntry = AddExtension(APPLEWMNAME,
- AppleWMNumberEvents,
- AppleWMNumberErrors,
- ProcAppleWMDispatch,
- SProcAppleWMDispatch,
- NULL,
- StandardMinorOpcode)))
- {
- WMReqCode = (unsigned char)extEntry->base;
- WMErrorBase = extEntry->errorBase;
- WMEventBase = extEntry->eventBase;
- EventSwapVector[WMEventBase] = (EventSwapPtr) SNotifyEvent;
- appleWMProcs = procsPtr;
- }
-}
+/************************************************************************** + +Copyright (c) 2002-2007 Apple Inc. All Rights Reserved. +Copyright (c) 2003 Torrey T. Lyons. 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, sub license, 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: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include "sanitizedCarbon.h" + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "quartzCommon.h" + +#include "misc.h" +#include "dixstruct.h" +#include "globals.h" +#include "extnsionst.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "servermd.h" +#include "swaprep.h" +#include "propertyst.h" +#include <X11/Xatom.h> +#include "darwin.h" +#define _APPLEWM_SERVER_ +#include <X11/extensions/applewmproto.h> +#include "applewmExt.h" +#include "X11Application.h" +#include "protocol-versions.h" + +#define DEFINE_ATOM_HELPER(func,atom_name) \ +static Atom func (void) { \ + static int generation; \ + static Atom atom; \ + if (generation != serverGeneration) { \ + generation = serverGeneration; \ + atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \ + } \ + return atom; \ +} + +DEFINE_ATOM_HELPER(xa_native_screen_origin, "_NATIVE_SCREEN_ORIGIN") +DEFINE_ATOM_HELPER (xa_apple_no_order_in, "_APPLE_NO_ORDER_IN") + +static AppleWMProcsPtr appleWMProcs; + +static int WMErrorBase; + + +static unsigned char WMReqCode = 0; +static int WMEventBase = 0; + +static RESTYPE ClientType, EventType; /* resource types for event masks */ +static XID eventResource; + +/* Currently selected events */ +static unsigned int eventMask = 0; + +static int WMFreeClient (pointer data, XID id); +static int WMFreeEvents (pointer data, XID id); +static void SNotifyEvent(xAppleWMNotifyEvent *from, xAppleWMNotifyEvent *to); + +typedef struct _WMEvent *WMEventPtr; +typedef struct _WMEvent { + WMEventPtr next; + ClientPtr client; + XID clientResource; + unsigned int mask; +} WMEventRec; + +static inline BoxRec +make_box (int x, int y, int w, int h) +{ + BoxRec r; + r.x1 = x; + r.y1 = y; + r.x2 = x + w; + r.y2 = y + h; + return r; +} + +/* Updates the _NATIVE_SCREEN_ORIGIN property on the given root window. */ +void +AppleWMSetScreenOrigin( + WindowPtr pWin +) +{ + int32_t data[2]; + + data[0] = pWin->drawable.pScreen->x + darwinMainScreenX; + data[1] = pWin->drawable.pScreen->y + darwinMainScreenY; + + dixChangeWindowProperty(serverClient, pWin, xa_native_screen_origin(), + XA_INTEGER, 32, PropModeReplace, 2, data, TRUE); +} + +/* Window managers can set the _APPLE_NO_ORDER_IN property on windows + that are being genie-restored from the Dock. We want them to + be mapped but remain ordered-out until the animation + completes (when the Dock will order them in). */ +Bool +AppleWMDoReorderWindow( + WindowPtr pWin +) +{ + Atom atom; + PropertyPtr prop; + int rc; + + atom = xa_apple_no_order_in(); + rc = dixLookupProperty(&prop, pWin, atom, serverClient, DixReadAccess); + + if(Success == rc && prop->type == atom) + return 0; + + return 1; +} + + +static int +ProcAppleWMQueryVersion( + register ClientPtr client +) +{ + xAppleWMQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xAppleWMQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = SERVER_APPLEWM_MAJOR_VERSION; + rep.minorVersion = SERVER_APPLEWM_MINOR_VERSION; + rep.patchVersion = SERVER_APPLEWM_PATCH_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + WriteToClient(client, sizeof(xAppleWMQueryVersionReply), (char *)&rep); + return Success; +} + + +/* events */ + +static inline void +updateEventMask (WMEventPtr *pHead) +{ + WMEventPtr pCur; + + eventMask = 0; + for (pCur = *pHead; pCur != NULL; pCur = pCur->next) + eventMask |= pCur->mask; +} + +/*ARGSUSED*/ +static int +WMFreeClient (pointer data, XID id) { + WMEventPtr pEvent; + WMEventPtr *pHead, pCur, pPrev; + int i; + + pEvent = (WMEventPtr) data; + i = dixLookupResourceByType((pointer *)&pHead, eventResource, EventType, serverClient, DixReadAccess | DixWriteAccess | DixDestroyAccess); + if (i == Success && pHead) { + pPrev = 0; + for (pCur = *pHead; pCur && pCur != pEvent; pCur=pCur->next) + pPrev = pCur; + if (pCur) { + if (pPrev) + pPrev->next = pEvent->next; + else + *pHead = pEvent->next; + } + updateEventMask (pHead); + } + free((pointer) pEvent); + return 1; +} + +/*ARGSUSED*/ +static int +WMFreeEvents (pointer data, XID id) { + WMEventPtr *pHead, pCur, pNext; + + pHead = (WMEventPtr *) data; + for (pCur = *pHead; pCur; pCur = pNext) { + pNext = pCur->next; + FreeResource (pCur->clientResource, ClientType); + free((pointer) pCur); + } + free((pointer) pHead); + eventMask = 0; + return 1; +} + +static int +ProcAppleWMSelectInput (register ClientPtr client) +{ + REQUEST(xAppleWMSelectInputReq); + WMEventPtr pEvent, pNewEvent, *pHead; + XID clientResource; + int i; + + REQUEST_SIZE_MATCH (xAppleWMSelectInputReq); + i = dixLookupResourceByType((pointer *)&pHead, eventResource, EventType, client, DixWriteAccess); + if (stuff->mask != 0) { + if (i == Success && pHead) { + /* check for existing entry. */ + for (pEvent = *pHead; pEvent; pEvent = pEvent->next) + { + if (pEvent->client == client) + { + pEvent->mask = stuff->mask; + updateEventMask (pHead); + return Success; + } + } + } + + /* build the entry */ + pNewEvent = (WMEventPtr) malloc(sizeof (WMEventRec)); + if (!pNewEvent) + return BadAlloc; + pNewEvent->next = 0; + pNewEvent->client = client; + pNewEvent->mask = stuff->mask; + /* + * add a resource that will be deleted when + * the client goes away + */ + clientResource = FakeClientID (client->index); + pNewEvent->clientResource = clientResource; + if (!AddResource (clientResource, ClientType, (pointer)pNewEvent)) + return BadAlloc; + /* + * create a resource to contain a pointer to the list + * of clients selecting input. This must be indirect as + * the list may be arbitrarily rearranged which cannot be + * done through the resource database. + */ + if (i != Success || !pHead) + { + pHead = (WMEventPtr *) malloc(sizeof (WMEventPtr)); + if (!pHead || + !AddResource (eventResource, EventType, (pointer)pHead)) + { + FreeResource (clientResource, RT_NONE); + return BadAlloc; + } + *pHead = 0; + } + pNewEvent->next = *pHead; + *pHead = pNewEvent; + updateEventMask (pHead); + } else if (stuff->mask == 0) { + /* delete the interest */ + if (i == Success && pHead) { + pNewEvent = 0; + for (pEvent = *pHead; pEvent; pEvent = pEvent->next) { + if (pEvent->client == client) + break; + pNewEvent = pEvent; + } + if (pEvent) { + FreeResource (pEvent->clientResource, ClientType); + if (pNewEvent) + pNewEvent->next = pEvent->next; + else + *pHead = pEvent->next; + free(pEvent); + updateEventMask (pHead); + } + } + } else { + client->errorValue = stuff->mask; + return BadValue; + } + return Success; +} + +/* + * deliver the event + */ + +void +AppleWMSendEvent (int type, unsigned int mask, int which, int arg) { + WMEventPtr *pHead, pEvent; + xAppleWMNotifyEvent se; + int i; + + i = dixLookupResourceByType((pointer *)&pHead, eventResource, EventType, serverClient, DixReadAccess); + if (i != Success || !pHead) + return; + for (pEvent = *pHead; pEvent; pEvent = pEvent->next) { + if ((pEvent->mask & mask) == 0) + continue; + se.type = type + WMEventBase; + se.kind = which; + se.arg = arg; + se.time = currentTime.milliseconds; + WriteEventsToClient (pEvent->client, 1, (xEvent *) &se); + } +} + +/* Safe to call from any thread. */ +unsigned int +AppleWMSelectedEvents (void) +{ + return eventMask; +} + + +/* general utility functions */ + +static int +ProcAppleWMDisableUpdate( + register ClientPtr client +) +{ + REQUEST_SIZE_MATCH(xAppleWMDisableUpdateReq); + + appleWMProcs->DisableUpdate(); + + return Success; +} + +static int +ProcAppleWMReenableUpdate( + register ClientPtr client +) +{ + REQUEST_SIZE_MATCH(xAppleWMReenableUpdateReq); + + appleWMProcs->EnableUpdate(); + + return Success; +} + + +/* window functions */ + +static int +ProcAppleWMSetWindowMenu( + register ClientPtr client +) +{ + const char *bytes, **items; + char *shortcuts; + int max_len, nitems, i, j; + REQUEST(xAppleWMSetWindowMenuReq); + + REQUEST_AT_LEAST_SIZE(xAppleWMSetWindowMenuReq); + + nitems = stuff->nitems; + items = malloc(sizeof (char *) * nitems); + shortcuts = malloc(sizeof (char) * nitems); + + max_len = (stuff->length << 2) - sizeof(xAppleWMSetWindowMenuReq); + bytes = (char *) &stuff[1]; + + for (i = j = 0; i < max_len && j < nitems;) + { + shortcuts[j] = bytes[i++]; + items[j++] = bytes + i; + + while (i < max_len) + { + if (bytes[i++] == 0) + break; + } + } + X11ApplicationSetWindowMenu (nitems, items, shortcuts); + free(items); + free(shortcuts); + + return Success; +} + +static int +ProcAppleWMSetWindowMenuCheck( + register ClientPtr client +) +{ + REQUEST(xAppleWMSetWindowMenuCheckReq); + + REQUEST_SIZE_MATCH(xAppleWMSetWindowMenuCheckReq); + X11ApplicationSetWindowMenuCheck(stuff->index); + return Success; +} + +static int +ProcAppleWMSetFrontProcess( + register ClientPtr client +) +{ + REQUEST_SIZE_MATCH(xAppleWMSetFrontProcessReq); + + X11ApplicationSetFrontProcess(); + return Success; +} + +static int +ProcAppleWMSetWindowLevel(register ClientPtr client) +{ + REQUEST(xAppleWMSetWindowLevelReq); + WindowPtr pWin; + int err; + + REQUEST_SIZE_MATCH(xAppleWMSetWindowLevelReq); + + if (Success != dixLookupWindow(&pWin, stuff->window, client, + DixReadAccess)) + return BadValue; + + if (stuff->level >= AppleWMNumWindowLevels) { + return BadValue; + } + + err = appleWMProcs->SetWindowLevel(pWin, stuff->level); + if (err != Success) { + return err; + } + + return Success; +} + +static int +ProcAppleWMSendPSN(register ClientPtr client) +{ + REQUEST(xAppleWMSendPSNReq); + int err; + + REQUEST_SIZE_MATCH(xAppleWMSendPSNReq); + + if(!appleWMProcs->SendPSN) + return BadRequest; + + err = appleWMProcs->SendPSN(stuff->psn_hi, stuff->psn_lo); + if (err != Success) { + return err; + } + + return Success; +} + +static int +ProcAppleWMAttachTransient(register ClientPtr client) +{ + WindowPtr pWinChild, pWinParent; + REQUEST(xAppleWMAttachTransientReq); + int err; + + REQUEST_SIZE_MATCH(xAppleWMAttachTransientReq); + + if(!appleWMProcs->AttachTransient) + return BadRequest; + + if (Success != dixLookupWindow(&pWinChild, stuff->child, client, DixReadAccess)) + return BadValue; + + if(stuff->parent) { + if(Success != dixLookupWindow(&pWinParent, stuff->parent, client, DixReadAccess)) + return BadValue; + } else { + pWinParent = NULL; + } + + err = appleWMProcs->AttachTransient(pWinChild, pWinParent); + if (err != Success) { + return err; + } + + return Success; +} + +static int +ProcAppleWMSetCanQuit( + register ClientPtr client +) +{ + REQUEST(xAppleWMSetCanQuitReq); + + REQUEST_SIZE_MATCH(xAppleWMSetCanQuitReq); + + X11ApplicationSetCanQuit(stuff->state); + return Success; +} + + +/* frame functions */ + +static int +ProcAppleWMFrameGetRect( + register ClientPtr client +) +{ + xAppleWMFrameGetRectReply rep; + BoxRec ir, or, rr; + REQUEST(xAppleWMFrameGetRectReq); + + REQUEST_SIZE_MATCH(xAppleWMFrameGetRectReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih); + or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh); + + if (appleWMProcs->FrameGetRect(stuff->frame_rect, + stuff->frame_class, + &or, &ir, &rr) != Success) + { + return BadValue; + } + + rep.x = rr.x1; + rep.y = rr.y1; + rep.w = rr.x2 - rr.x1; + rep.h = rr.y2 - rr.y1; + + WriteToClient(client, sizeof(xAppleWMFrameGetRectReply), (char *)&rep); + return Success; +} + +static int +ProcAppleWMFrameHitTest( + register ClientPtr client +) +{ + xAppleWMFrameHitTestReply rep; + BoxRec ir, or; + int ret; + REQUEST(xAppleWMFrameHitTestReq); + + REQUEST_SIZE_MATCH(xAppleWMFrameHitTestReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih); + or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh); + + if (appleWMProcs->FrameHitTest(stuff->frame_class, stuff->px, + stuff->py, &or, &ir, &ret) != Success) + { + return BadValue; + } + + rep.ret = ret; + + WriteToClient(client, sizeof(xAppleWMFrameHitTestReply), (char *)&rep); + return Success; +} + +static int +ProcAppleWMFrameDraw( + register ClientPtr client +) +{ + BoxRec ir, or; + unsigned int title_length, title_max; + unsigned char *title_bytes; + REQUEST(xAppleWMFrameDrawReq); + WindowPtr pWin; + + REQUEST_AT_LEAST_SIZE(xAppleWMFrameDrawReq); + + if (Success != dixLookupWindow(&pWin, stuff->window, client, + DixReadAccess)) + return BadValue; + + ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih); + or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh); + + title_length = stuff->title_length; + title_max = (stuff->length << 2) - sizeof(xAppleWMFrameDrawReq); + + if (title_max < title_length) + return BadValue; + + title_bytes = (unsigned char *) &stuff[1]; + + errno = appleWMProcs->FrameDraw(pWin, stuff->frame_class, + stuff->frame_attr, &or, &ir, + title_length, title_bytes); + if (errno != Success) { + return errno; + } + + return Success; +} + + +/* dispatch */ + +static int +ProcAppleWMDispatch ( + register ClientPtr client +) +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_AppleWMQueryVersion: + return ProcAppleWMQueryVersion(client); + } + + if (!LocalClient(client)) + return WMErrorBase + AppleWMClientNotLocal; + + switch (stuff->data) + { + case X_AppleWMSelectInput: + return ProcAppleWMSelectInput(client); + case X_AppleWMDisableUpdate: + return ProcAppleWMDisableUpdate(client); + case X_AppleWMReenableUpdate: + return ProcAppleWMReenableUpdate(client); + case X_AppleWMSetWindowMenu: + return ProcAppleWMSetWindowMenu(client); + case X_AppleWMSetWindowMenuCheck: + return ProcAppleWMSetWindowMenuCheck(client); + case X_AppleWMSetFrontProcess: + return ProcAppleWMSetFrontProcess(client); + case X_AppleWMSetWindowLevel: + return ProcAppleWMSetWindowLevel(client); + case X_AppleWMSetCanQuit: + return ProcAppleWMSetCanQuit(client); + case X_AppleWMFrameGetRect: + return ProcAppleWMFrameGetRect(client); + case X_AppleWMFrameHitTest: + return ProcAppleWMFrameHitTest(client); + case X_AppleWMFrameDraw: + return ProcAppleWMFrameDraw(client); + case X_AppleWMSendPSN: + return ProcAppleWMSendPSN(client); + case X_AppleWMAttachTransient: + return ProcAppleWMAttachTransient(client); + default: + return BadRequest; + } +} + +static void +SNotifyEvent(xAppleWMNotifyEvent *from, xAppleWMNotifyEvent *to) { + to->type = from->type; + to->kind = from->kind; + cpswaps (from->sequenceNumber, to->sequenceNumber); + cpswapl (from->time, to->time); + cpswapl (from->arg, to->arg); +} + +static int +SProcAppleWMQueryVersion( + register ClientPtr client +) +{ + register int n; + REQUEST(xAppleWMQueryVersionReq); + swaps(&stuff->length, n); + return ProcAppleWMQueryVersion(client); +} + +static int +SProcAppleWMDispatch ( + register ClientPtr client +) +{ + REQUEST(xReq); + + /* It is bound to be non-local when there is byte swapping */ + if (!LocalClient(client)) + return WMErrorBase + AppleWMClientNotLocal; + + /* only local clients are allowed WM access */ + switch (stuff->data) + { + case X_AppleWMQueryVersion: + return SProcAppleWMQueryVersion(client); + default: + return BadRequest; + } +} + +void +AppleWMExtensionInit( + AppleWMProcsPtr procsPtr) +{ + ExtensionEntry* extEntry; + + ClientType = CreateNewResourceType(WMFreeClient, "WMClient"); + EventType = CreateNewResourceType(WMFreeEvents, "WMEvent"); + eventResource = FakeClientID(0); + + if (ClientType && EventType && + (extEntry = AddExtension(APPLEWMNAME, + AppleWMNumberEvents, + AppleWMNumberErrors, + ProcAppleWMDispatch, + SProcAppleWMDispatch, + NULL, + StandardMinorOpcode))) + { + WMReqCode = (unsigned char)extEntry->base; + WMErrorBase = extEntry->errorBase; + WMEventBase = extEntry->eventBase; + EventSwapVector[WMEventBase] = (EventSwapPtr) SNotifyEvent; + appleWMProcs = procsPtr; + } +} diff --git a/xorg-server/hw/xquartz/darwin.c b/xorg-server/hw/xquartz/darwin.c index 56021ed0a..3b6f0a29e 100644 --- a/xorg-server/hw/xquartz/darwin.c +++ b/xorg-server/hw/xquartz/darwin.c @@ -1,881 +1,769 @@ -/**************************************************************
- *
- * Xquartz initialization code
- *
- * Copyright (c) 2007-2008 Apple Inc.
- * Copyright (c) 2001-2004 Torrey T. Lyons. 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:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name(s) of the above copyright
- * holders shall not be used in advertising or otherwise to promote the sale,
- * use or other dealings in this Software without prior written authorization.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "os.h"
-#include "servermd.h"
-#include "inputstr.h"
-#include "scrnintstr.h"
-#include "mibstore.h" // mi backing store implementation
-#include "mipointer.h" // mi software cursor
-#include "micmap.h" // mi colormap code
-#include "fb.h" // fb framebuffer code
-#include "site.h"
-#include "globals.h"
-#include "dix.h"
-#include "xkbsrv.h"
-
-#include <X11/extensions/XI.h>
-#include <X11/extensions/XIproto.h>
-#include "exevents.h"
-#include "extinit.h"
-
-#include "xserver-properties.h"
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/syslimits.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#define HAS_UTSNAME 1
-#include <sys/utsname.h>
-
-#define NO_CFPLUGIN
-#include <IOKit/hidsystem/IOHIDLib.h>
-
-#ifdef MITSHM
-#include "shmint.h"
-#endif
-
-#include "darwin.h"
-#include "darwinEvents.h"
-#include "quartzKeyboard.h"
-#include "quartz.h"
-
-#ifdef ENABLE_DEBUG_LOG
-FILE *debug_log_fp = NULL;
-#endif
-
-/*
- * X server shared global variables
- */
-int darwinScreensFound = 0;
-DevPrivateKeyRec darwinScreenKeyRec;
-io_connect_t darwinParamConnect = 0;
-int darwinEventReadFD = -1;
-int darwinEventWriteFD = -1;
-// int darwinMouseAccelChange = 1;
-int darwinFakeButtons = 0;
-
-// location of X11's (0,0) point in global screen coordinates
-int darwinMainScreenX = 0;
-int darwinMainScreenY = 0;
-
-// parameters read from the command line or user preferences
-int darwinDesiredDepth = -1;
-int darwinSyncKeymap = FALSE;
-
-// modifier masks for faking mouse buttons - ANY of these bits trigger it (not all)
-#ifdef NX_DEVICELCMDKEYMASK
-int darwinFakeMouse2Mask = NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK;
-int darwinFakeMouse3Mask = NX_DEVICELCMDKEYMASK | NX_DEVICERCMDKEYMASK;
-#else
-int darwinFakeMouse2Mask = NX_ALTERNATEMASK;
-int darwinFakeMouse3Mask = NX_COMMANDMASK;
-#endif
-
-// Modifier mask for overriding event delivery to appkit (might be useful to set this to rcommand for input menu
-unsigned int darwinAppKitModMask = 0; // Any of these bits
-
-// Modifier mask for items in the Window menu (0 and -1 cause shortcuts to be disabled)
-unsigned int windowItemModMask = NX_COMMANDMASK;
-
-// devices
-DeviceIntPtr darwinKeyboard = NULL;
-DeviceIntPtr darwinPointer = NULL;
-DeviceIntPtr darwinTabletCurrent = NULL;
-DeviceIntPtr darwinTabletStylus = NULL;
-DeviceIntPtr darwinTabletCursor = NULL;
-DeviceIntPtr darwinTabletEraser = NULL;
-
-// Common pixmap formats
-static PixmapFormatRec formats[] = {
- { 1, 1, BITMAP_SCANLINE_PAD },
- { 4, 8, BITMAP_SCANLINE_PAD },
- { 8, 8, BITMAP_SCANLINE_PAD },
- { 15, 16, BITMAP_SCANLINE_PAD },
- { 16, 16, BITMAP_SCANLINE_PAD },
- { 24, 32, BITMAP_SCANLINE_PAD },
- { 32, 32, BITMAP_SCANLINE_PAD }
-};
-const int NUMFORMATS = sizeof(formats)/sizeof(formats[0]);
-
-#ifndef OSNAME
-#define OSNAME " Darwin"
-#endif
-#ifndef OSVENDOR
-#define OSVENDOR ""
-#endif
-#ifndef PRE_RELEASE
-#define PRE_RELEASE XORG_VERSION_SNAP
-#endif
-#ifndef BUILD_DATE
-#define BUILD_DATE ""
-#endif
-#ifndef XORG_RELEASE
-#define XORG_RELEASE "?"
-#endif
-
-void
-DarwinPrintBanner(void)
-{
- // this should change depending on which specific server we are building
- ErrorF("Xquartz starting:\n");
- ErrorF("X.Org X Server %s\nBuild Date: %s\n", XSERVER_VERSION, BUILD_DATE );
-}
-
-
-/*
- * DarwinSaveScreen
- * X screensaver support. Not implemented.
- */
-static Bool DarwinSaveScreen(ScreenPtr pScreen, int on)
-{
- // FIXME
- if (on == SCREEN_SAVER_FORCER) {
- } else if (on == SCREEN_SAVER_ON) {
- } else {
- }
- return TRUE;
-}
-
-/*
- * DarwinScreenInit
- * This is a callback from dix during AddScreen() from InitOutput().
- * Initialize the screen and communicate information about it back to dix.
- */
-static Bool DarwinScreenInit(int index, ScreenPtr pScreen, int argc, char **argv) {
- int dpi;
- static int foundIndex = 0;
- Bool ret;
- DarwinFramebufferPtr dfb;
-
- if (!dixRegisterPrivateKey(&darwinScreenKeyRec, PRIVATE_SCREEN, 0))
- return FALSE;
-
- // reset index of found screens for each server generation
- if (index == 0) {
- foundIndex = 0;
-
- // reset the visual list
- miClearVisualTypes();
- }
-
- // allocate space for private per screen storage
- dfb = malloc(sizeof(DarwinFramebufferRec));
-
- // SCREEN_PRIV(pScreen) = dfb;
- dixSetPrivate(&pScreen->devPrivates, darwinScreenKey, dfb);
-
- // setup hardware/mode specific details
- ret = QuartzAddScreen(foundIndex, pScreen);
- foundIndex++;
- if (! ret)
- return FALSE;
-
- // setup a single visual appropriate for our pixel type
- if(!miSetVisualTypesAndMasks(dfb->depth, dfb->visuals, dfb->bitsPerRGB,
- dfb->preferredCVC, dfb->redMask,
- dfb->greenMask, dfb->blueMask)) {
- return FALSE;
- }
-
-// TODO: Make PseudoColor visuals not suck in TrueColor mode
-// if(dfb->depth > 8)
-// miSetVisualTypesAndMasks(8, PseudoColorMask, 8, PseudoColor, 0, 0, 0);
- if(dfb->depth > 15)
- miSetVisualTypesAndMasks(15, TrueColorMask, 5, TrueColor, RM_ARGB(0,5,5,5), GM_ARGB(0,5,5,5), BM_ARGB(0,5,5,5));
- if(dfb->depth > 24)
- miSetVisualTypesAndMasks(24, TrueColorMask, 8, TrueColor, RM_ARGB(0,8,8,8), GM_ARGB(0,8,8,8), BM_ARGB(0,8,8,8));
-
- miSetPixmapDepths();
-
- // machine independent screen init
- // setup _Screen structure in pScreen
- if (monitorResolution)
- dpi = monitorResolution;
- else
- dpi = 96;
-
- // initialize fb
- if (! fbScreenInit(pScreen,
- dfb->framebuffer, // pointer to screen bitmap
- dfb->width, dfb->height, // screen size in pixels
- dpi, dpi, // dots per inch
- dfb->pitch/(dfb->bitsPerPixel/8), // pixel width of framebuffer
- dfb->bitsPerPixel)) // bits per pixel for screen
- {
- return FALSE;
- }
-
- if (! fbPictureInit(pScreen, 0, 0)) {
- return FALSE;
- }
-
-#ifdef MITSHM
- ShmRegisterFbFuncs(pScreen);
-#endif
-
- // this must be initialized (why doesn't X have a default?)
- pScreen->SaveScreen = DarwinSaveScreen;
-
- // finish mode dependent screen setup including cursor support
- if (!QuartzSetupScreen(index, pScreen)) {
- return FALSE;
- }
-
- // create and install the default colormap and
- // set pScreen->blackPixel / pScreen->white
- if (!miCreateDefColormap( pScreen )) {
- return FALSE;
- }
-
- pScreen->x = dfb->x;
- pScreen->y = dfb->y;
-
- /* ErrorF("Screen %d added: %dx%d @ (%d,%d)\n",
- index, dfb->width, dfb->height, dfb->x, dfb->y); */
-
- return TRUE;
-}
-
-/*
- =============================================================================
-
- mouse and keyboard callbacks
-
- =============================================================================
-*/
-
-/*
- * DarwinMouseProc: Handle the initialization, etc. of a mouse
- */
-static int DarwinMouseProc(DeviceIntPtr pPointer, int what) {
-#define NBUTTONS 7
-#define NAXES 2
- // 7 buttons: left, right, middle, then four scroll wheel "buttons"
- CARD8 map[NBUTTONS + 1] = {0, 1, 2, 3, 4, 5, 6, 7};
- Atom btn_labels[NBUTTONS] = {0};
- Atom axes_labels[NAXES] = {0};
-
- switch (what) {
- case DEVICE_INIT:
- pPointer->public.on = FALSE;
-
- btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
- btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
- btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
- btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
- btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
- btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
- btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
-
- axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
- axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
-
-
- // Set button map.
- InitPointerDeviceStruct((DevicePtr)pPointer, map, NBUTTONS,
- btn_labels,
- (PtrCtrlProcPtr)NoopDDA,
- GetMotionHistorySize(), NAXES,
- axes_labels);
- InitAbsoluteClassDeviceStruct(pPointer);
-// InitValuatorAxisStruct(pPointer, 0, 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, Absolute);
-// InitValuatorAxisStruct(pPointer, 1, 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, Absolute);
- break;
- case DEVICE_ON:
- pPointer->public.on = TRUE;
- AddEnabledDevice( darwinEventReadFD );
- return Success;
- case DEVICE_CLOSE:
- case DEVICE_OFF:
- pPointer->public.on = FALSE;
- RemoveEnabledDevice(darwinEventReadFD);
- return Success;
- }
-
- return Success;
-#undef NBUTTONS
-#undef NAXES
-}
-
-static int DarwinTabletProc(DeviceIntPtr pPointer, int what) {
-#define NBUTTONS 3
-#define NAXES 5
- CARD8 map[NBUTTONS + 1] = {0, 1, 2, 3};
- Atom btn_labels[NBUTTONS] = {0};
- Atom axes_labels[NAXES] = {0};
-
- switch (what) {
- case DEVICE_INIT:
- pPointer->public.on = FALSE;
-
- btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
- btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
- btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
-
- axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X);
- axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y);
- axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE);
- axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_X);
- axes_labels[4] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_Y);
-
- // Set button map.
- InitPointerDeviceStruct((DevicePtr)pPointer, map, NBUTTONS,
- btn_labels,
- (PtrCtrlProcPtr)NoopDDA,
- GetMotionHistorySize(), NAXES,
- axes_labels);
- InitProximityClassDeviceStruct(pPointer);
- InitAbsoluteClassDeviceStruct(pPointer);
-
- InitValuatorAxisStruct(pPointer, 0, axes_labels[0], 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, Absolute);
- InitValuatorAxisStruct(pPointer, 1, axes_labels[1], 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, Absolute);
- InitValuatorAxisStruct(pPointer, 2, axes_labels[2], 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, Absolute);
- InitValuatorAxisStruct(pPointer, 3, axes_labels[3], -XQUARTZ_VALUATOR_LIMIT, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, Absolute);
- InitValuatorAxisStruct(pPointer, 4, axes_labels[4], -XQUARTZ_VALUATOR_LIMIT, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, Absolute);
-// pPointer->use = IsXExtensionDevice;
- break;
- case DEVICE_ON:
- pPointer->public.on = TRUE;
- AddEnabledDevice( darwinEventReadFD );
- return Success;
- case DEVICE_CLOSE:
- case DEVICE_OFF:
- pPointer->public.on = FALSE;
- RemoveEnabledDevice(darwinEventReadFD);
- return Success;
- }
- return Success;
-#undef NBUTTONS
-#undef NAXES
-}
-
-/*
- * DarwinKeybdProc
- * Callback from X
- */
-static int DarwinKeybdProc( DeviceIntPtr pDev, int onoff )
-{
- switch ( onoff ) {
- case DEVICE_INIT:
- DarwinKeyboardInit( pDev );
- break;
- case DEVICE_ON:
- pDev->public.on = TRUE;
- AddEnabledDevice( darwinEventReadFD );
- break;
- case DEVICE_OFF:
- pDev->public.on = FALSE;
- RemoveEnabledDevice( darwinEventReadFD );
- break;
- case DEVICE_CLOSE:
- break;
- }
-
- return Success;
-}
-
-/*
-===========================================================================
-
- Utility routines
-
-===========================================================================
-*/
-
-/*
- * DarwinParseModifierList
- * Parse a list of modifier names and return a corresponding modifier mask
- */
-int DarwinParseModifierList(const char *constmodifiers, int separatelr)
-{
- int result = 0;
-
- if (constmodifiers) {
- char *modifiers = strdup(constmodifiers);
- char *modifier;
- int nxkey;
- char *p = modifiers;
-
- while (p) {
- modifier = strsep(&p, " ,+&|/"); // allow lots of separators
- nxkey = DarwinModifierStringToNXMask(modifier, separatelr);
- if(nxkey)
- result |= nxkey;
- else
- ErrorF("fakebuttons: Unknown modifier \"%s\"\n", modifier);
- }
- free(modifiers);
- }
- return result;
-}
-
-/*
-===========================================================================
-
- Functions needed to link against device independent X
-
-===========================================================================
-*/
-
-/*
- * InitInput
- * Register the keyboard and mouse devices
- */
-void InitInput( int argc, char **argv )
-{
- XkbRMLVOSet rmlvo = { .rules = "base", .model = "empty", .layout = "empty",
- .variant = NULL, .options = NULL };
- /* We need to really have rules... or something... */
- XkbSetRulesDflts(&rmlvo);
-
- darwinKeyboard = AddInputDevice(serverClient, DarwinKeybdProc, TRUE);
- darwinKeyboard->name = strdup("keyboard");
-
- /* here's the snippet from the current gdk sources:
- if (!strcmp (tmp_name, "pointer"))
- gdkdev->info.source = GDK_SOURCE_MOUSE;
- else if (!strcmp (tmp_name, "wacom") ||
- !strcmp (tmp_name, "pen"))
- gdkdev->info.source = GDK_SOURCE_PEN;
- else if (!strcmp (tmp_name, "eraser"))
- gdkdev->info.source = GDK_SOURCE_ERASER;
- else if (!strcmp (tmp_name, "cursor"))
- gdkdev->info.source = GDK_SOURCE_CURSOR;
- else
- gdkdev->info.source = GDK_SOURCE_PEN;
- */
-
- darwinPointer = AddInputDevice(serverClient, DarwinMouseProc, TRUE);
- darwinPointer->name = strdup("pointer");
-
- darwinTabletStylus = AddInputDevice(serverClient, DarwinTabletProc, TRUE);
- darwinTabletStylus->name = strdup("pen");
-
- darwinTabletCursor = AddInputDevice(serverClient, DarwinTabletProc, TRUE);
- darwinTabletCursor->name = strdup("cursor");
-
- darwinTabletEraser = AddInputDevice(serverClient, DarwinTabletProc, TRUE);
- darwinTabletEraser->name = strdup("eraser");
-
- darwinTabletCurrent = darwinTabletStylus;
-
- DarwinEQInit();
-
- QuartzInitInput(argc, argv);
-}
-
-
-/*
- * DarwinAdjustScreenOrigins
- * Shift all screens so the X11 (0, 0) coordinate is at the top
- * left of the global screen coordinates.
- *
- * Screens can be arranged so the top left isn't on any screen, so
- * instead use the top left of the leftmost screen as (0,0). This
- * may mean some screen space is in -y, but it's better that (0,0)
- * be onscreen, or else default xterms disappear. It's better that
- * -y be used than -x, because when popup menus are forced
- * "onscreen" by dumb window managers like twm, they'll shift the
- * menus down instead of left, which still looks funny but is an
- * easier target to hit.
- */
-void
-DarwinAdjustScreenOrigins(ScreenInfo *pScreenInfo)
-{
- int i, left, top;
-
- left = pScreenInfo->screens[0]->x;
- top = pScreenInfo->screens[0]->y;
-
- /* Find leftmost screen. If there's a tie, take the topmost of the two. */
- for (i = 1; i < pScreenInfo->numScreens; i++) {
- if (pScreenInfo->screens[i]->x < left ||
- (pScreenInfo->screens[i]->x == left && pScreenInfo->screens[i]->y < top))
- {
- left = pScreenInfo->screens[i]->x;
- top = pScreenInfo->screens[i]->y;
- }
- }
-
- darwinMainScreenX = left;
- darwinMainScreenY = top;
-
- DEBUG_LOG("top = %d, left=%d\n", top, left);
-
- /* Shift all screens so that there is a screen whose top left
- * is at X11 (0,0) and at global screen coordinate
- * (darwinMainScreenX, darwinMainScreenY).
- */
-
- if (darwinMainScreenX != 0 || darwinMainScreenY != 0) {
- for (i = 0; i < pScreenInfo->numScreens; i++) {
- pScreenInfo->screens[i]->x -= darwinMainScreenX;
- pScreenInfo->screens[i]->y -= darwinMainScreenY;
- DEBUG_LOG("Screen %d placed at X11 coordinate (%d,%d).\n",
- i, pScreenInfo->screens[i]->x, pScreenInfo->screens[i]->y);
- }
- }
-}
-
-
-/*
- * InitOutput
- * Initialize screenInfo for all actually accessible framebuffers.
- *
- * The display mode dependent code gets called three times. The mode
- * specific InitOutput routines are expected to discover the number
- * of potentially useful screens and cache routes to them internally.
- * Inside DarwinScreenInit are two other mode specific calls.
- * A mode specific AddScreen routine is called for each screen to
- * actually initialize the screen with the ScreenPtr structure.
- * After other screen setup has been done, a mode specific
- * SetupScreen function can be called to finalize screen setup.
- */
-void InitOutput( ScreenInfo *pScreenInfo, int argc, char **argv )
-{
- int i;
-
- pScreenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
- pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
- pScreenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
- pScreenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
-
- // List how we want common pixmap formats to be padded
- pScreenInfo->numPixmapFormats = NUMFORMATS;
- for (i = 0; i < NUMFORMATS; i++)
- pScreenInfo->formats[i] = formats[i];
-
- // Discover screens and do mode specific initialization
- QuartzInitOutput(argc, argv);
-
- // Add screens
- for (i = 0; i < darwinScreensFound; i++) {
- AddScreen(DarwinScreenInit, argc, argv);
- }
-
- DarwinAdjustScreenOrigins(pScreenInfo);
-}
-
-
-/*
- * OsVendorFatalError
- */
-void OsVendorFatalError( void )
-{
- ErrorF( " OsVendorFatalError\n" );
-}
-
-
-/*
- * OsVendorInit
- * Initialization of Darwin OS support.
- */
-void OsVendorInit(void)
-{
- if (serverGeneration == 1) {
- DarwinPrintBanner();
-#ifdef ENABLE_DEBUG_LOG
- {
- char *home_dir=NULL, *log_file_path=NULL;
- home_dir = getenv("HOME");
- if (home_dir) asprintf(&log_file_path, "%s/%s", home_dir, DEBUG_LOG_NAME);
- if (log_file_path) {
- if (!access(log_file_path, F_OK)) {
- debug_log_fp = fopen(log_file_path, "a");
- if (debug_log_fp) ErrorF("Debug logging enabled to %s\n", log_file_path);
- }
- free(log_file_path);
- }
- }
-#endif
- }
-}
-
-
-/*
- * ddxProcessArgument
- * Process device-dependent command line args. Returns 0 if argument is
- * not device dependent, otherwise Count of number of elements of argv
- * that are part of a device dependent commandline option.
- */
-int ddxProcessArgument( int argc, char *argv[], int i )
-{
-// if ( !strcmp( argv[i], "-fullscreen" ) ) {
-// ErrorF( "Running full screen in parallel with Mac OS X Quartz window server.\n" );
-// return 1;
-// }
-
-// if ( !strcmp( argv[i], "-rootless" ) ) {
-// ErrorF( "Running rootless inside Mac OS X window server.\n" );
-// return 1;
-// }
-
- // This command line arg is passed when launched from the Aqua GUI.
- if ( !strncmp( argv[i], "-psn_", 5 ) ) {
- return 1;
- }
-
- if ( !strcmp( argv[i], "-fakebuttons" ) ) {
- darwinFakeButtons = TRUE;
- ErrorF( "Faking a three button mouse\n" );
- return 1;
- }
-
- if ( !strcmp( argv[i], "-nofakebuttons" ) ) {
- darwinFakeButtons = FALSE;
- ErrorF( "Not faking a three button mouse\n" );
- return 1;
- }
-
- if (!strcmp( argv[i], "-fakemouse2" ) ) {
- if ( i == argc-1 ) {
- FatalError( "-fakemouse2 must be followed by a modifer list\n" );
- }
- if (!strcasecmp(argv[i+1], "none") || !strcmp(argv[i+1], ""))
- darwinFakeMouse2Mask = 0;
- else
- darwinFakeMouse2Mask = DarwinParseModifierList(argv[i+1], 1);
- ErrorF("Modifier mask to fake mouse button 2 = 0x%x\n",
- darwinFakeMouse2Mask);
- return 2;
- }
-
- if (!strcmp( argv[i], "-fakemouse3" ) ) {
- if ( i == argc-1 ) {
- FatalError( "-fakemouse3 must be followed by a modifer list\n" );
- }
- if (!strcasecmp(argv[i+1], "none") || !strcmp(argv[i+1], ""))
- darwinFakeMouse3Mask = 0;
- else
- darwinFakeMouse3Mask = DarwinParseModifierList(argv[i+1], 1);
- ErrorF("Modifier mask to fake mouse button 3 = 0x%x\n",
- darwinFakeMouse3Mask);
- return 2;
- }
-
- if ( !strcmp( argv[i], "+synckeymap" ) ) {
- darwinSyncKeymap = TRUE;
- return 1;
- }
-
- if ( !strcmp( argv[i], "-synckeymap" ) ) {
- darwinSyncKeymap = FALSE;
- return 1;
- }
-
- if ( !strcmp( argv[i], "-depth" ) ) {
- if ( i == argc-1 ) {
- FatalError( "-depth must be followed by a number\n" );
- }
- darwinDesiredDepth = atoi( argv[i+1] );
- if(darwinDesiredDepth != -1 &&
- darwinDesiredDepth != 8 &&
- darwinDesiredDepth != 15 &&
- darwinDesiredDepth != 24) {
- FatalError( "Unsupported pixel depth. Use 8, 15, or 24 bits\n" );
- }
-
- ErrorF( "Attempting to use pixel depth of %i\n", darwinDesiredDepth );
- return 2;
- }
-
- if (!strcmp( argv[i], "-showconfig" ) || !strcmp( argv[i], "-version" )) {
- DarwinPrintBanner();
- exit(0);
- }
-
- return 0;
-}
-
-
-/*
- * ddxUseMsg --
- * Print out correct use of device dependent commandline options.
- * Maybe the user now knows what really to do ...
- */
-void ddxUseMsg( void )
-{
- ErrorF("\n");
- ErrorF("\n");
- ErrorF("Device Dependent Usage:\n");
- ErrorF("\n");
- ErrorF("-depth <8,15,24> : use this bit depth.\n");
- ErrorF("-fakebuttons : fake a three button mouse with Command and Option keys.\n");
- ErrorF("-nofakebuttons : don't fake a three button mouse.\n");
- ErrorF("-fakemouse2 <modifiers> : fake middle mouse button with modifier keys.\n");
- ErrorF("-fakemouse3 <modifiers> : fake right mouse button with modifier keys.\n");
- ErrorF(" ex: -fakemouse2 \"option,shift\" = option-shift-click is middle button.\n");
- ErrorF("-version : show the server version.\n");
- ErrorF("\n");
-}
-
-
-/*
- * ddxGiveUp --
- * Device dependent cleanup. Called by dix before normal server death.
- */
-void ddxGiveUp( void )
-{
- ErrorF( "Quitting Xquartz\n" );
-}
-
-
-/*
- * AbortDDX --
- * DDX - specific abort routine. Called by AbortServer(). The attempt is
- * made to restore all original setting of the displays. Also all devices
- * are closed.
- */
-void AbortDDX( void )
-{
- ErrorF( " AbortDDX\n" );
- OsAbort();
-}
-
-#include "mivalidate.h" // for union _Validate used by windowstr.h
-#include "windowstr.h" // for struct _Window
-#include "scrnintstr.h" // for struct _Screen
-
-// This is copied from Xserver/hw/xfree86/common/xf86Helper.c.
-// Quartz mode uses this when switching in and out of Quartz.
-// Quartz or IOKit can use this when waking from sleep.
-// Copyright (c) 1997-1998 by The XFree86 Project, Inc.
-
-/*
- * xf86SetRootClip --
- * Enable or disable rendering to the screen by
- * setting the root clip list and revalidating
- * all of the windows
- */
-
-void
-xf86SetRootClip (ScreenPtr pScreen, int enable)
-{
- WindowPtr pWin = pScreen->root;
- WindowPtr pChild;
- Bool WasViewable = (Bool)(pWin->viewable);
- Bool anyMarked = TRUE;
- RegionPtr pOldClip = NULL;
- WindowPtr pLayerWin;
- BoxRec box;
-
- 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 = RegionCreate(NullBox, 1);
- RegionSubtract(borderVisible,
- &pWin->borderClip, &pWin->winSize);
- pWin->valdata->before.borderVisible = borderVisible;
- }
- pWin->valdata->before.resized = TRUE;
- }
- }
-
- /*
- * Use REGION_BREAK to avoid optimizations in ValidateTree
- * that assume the root borderClip can't change well, normally
- * it doesn't...)
- */
- if (enable)
- {
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = pScreen->width;
- box.y2 = pScreen->height;
- RegionReset(&pWin->borderClip, &box);
- RegionBreak(&pWin->clipList);
- }
- else
- {
- RegionEmpty(&pWin->borderClip);
- RegionBreak(&pWin->clipList);
- }
-
- ResizeChildrenWinSize (pWin, 0, 0, 0, 0);
-
- if (WasViewable)
- {
- if (pWin->backStorage)
- {
- pOldClip = RegionCreate(NullBox, 1);
- RegionCopy(pOldClip, &pWin->clipList);
- }
-
- 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 ();
- FlushAllOutput ();
-}
+/************************************************************** + * + * Xquartz initialization code + * + * Copyright (c) 2007-2008 Apple Inc. + * Copyright (c) 2001-2004 Torrey T. Lyons. 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: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "os.h" +#include "servermd.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "mibstore.h" // mi backing store implementation +#include "mipointer.h" // mi software cursor +#include "micmap.h" // mi colormap code +#include "fb.h" // fb framebuffer code +#include "site.h" +#include "globals.h" +#include "dix.h" +#include "xkbsrv.h" + +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include "exevents.h" +#include "extinit.h" + +#include "xserver-properties.h" + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/syslimits.h> +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> + +#define HAS_UTSNAME 1 +#include <sys/utsname.h> + +#define NO_CFPLUGIN +#include <IOKit/hidsystem/IOHIDLib.h> + +#ifdef MITSHM +#include "shmint.h" +#endif + +#include "darwin.h" +#include "darwinEvents.h" +#include "quartzKeyboard.h" +#include "quartz.h" + +#ifdef ENABLE_DEBUG_LOG +FILE *debug_log_fp = NULL; +#endif + +/* + * X server shared global variables + */ +int darwinScreensFound = 0; +DevPrivateKeyRec darwinScreenKeyRec; +io_connect_t darwinParamConnect = 0; +int darwinEventReadFD = -1; +int darwinEventWriteFD = -1; +// int darwinMouseAccelChange = 1; +int darwinFakeButtons = 0; + +// location of X11's (0,0) point in global screen coordinates +int darwinMainScreenX = 0; +int darwinMainScreenY = 0; + +// parameters read from the command line or user preferences +int darwinDesiredDepth = -1; +int darwinSyncKeymap = FALSE; + +// modifier masks for faking mouse buttons - ANY of these bits trigger it (not all) +#ifdef NX_DEVICELCMDKEYMASK +int darwinFakeMouse2Mask = NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK; +int darwinFakeMouse3Mask = NX_DEVICELCMDKEYMASK | NX_DEVICERCMDKEYMASK; +#else +int darwinFakeMouse2Mask = NX_ALTERNATEMASK; +int darwinFakeMouse3Mask = NX_COMMANDMASK; +#endif + +// Modifier mask for overriding event delivery to appkit (might be useful to set this to rcommand for input menu +unsigned int darwinAppKitModMask = 0; // Any of these bits + +// Modifier mask for items in the Window menu (0 and -1 cause shortcuts to be disabled) +unsigned int windowItemModMask = NX_COMMANDMASK; + +// devices +DeviceIntPtr darwinKeyboard = NULL; +DeviceIntPtr darwinPointer = NULL; +DeviceIntPtr darwinTabletCurrent = NULL; +DeviceIntPtr darwinTabletStylus = NULL; +DeviceIntPtr darwinTabletCursor = NULL; +DeviceIntPtr darwinTabletEraser = NULL; + +// Common pixmap formats +static PixmapFormatRec formats[] = { + { 1, 1, BITMAP_SCANLINE_PAD }, + { 4, 8, BITMAP_SCANLINE_PAD }, + { 8, 8, BITMAP_SCANLINE_PAD }, + { 15, 16, BITMAP_SCANLINE_PAD }, + { 16, 16, BITMAP_SCANLINE_PAD }, + { 24, 32, BITMAP_SCANLINE_PAD }, + { 32, 32, BITMAP_SCANLINE_PAD } +}; +const int NUMFORMATS = sizeof(formats)/sizeof(formats[0]); + +#ifndef OSNAME +#define OSNAME " Darwin" +#endif +#ifndef OSVENDOR +#define OSVENDOR "" +#endif +#ifndef PRE_RELEASE +#define PRE_RELEASE XORG_VERSION_SNAP +#endif +#ifndef BUILD_DATE +#define BUILD_DATE "" +#endif +#ifndef XORG_RELEASE +#define XORG_RELEASE "?" +#endif + +void +DarwinPrintBanner(void) +{ + // this should change depending on which specific server we are building + ErrorF("Xquartz starting:\n"); + ErrorF("X.Org X Server %s\nBuild Date: %s\n", XSERVER_VERSION, BUILD_DATE ); +} + + +/* + * DarwinSaveScreen + * X screensaver support. Not implemented. + */ +static Bool DarwinSaveScreen(ScreenPtr pScreen, int on) +{ + // FIXME + if (on == SCREEN_SAVER_FORCER) { + } else if (on == SCREEN_SAVER_ON) { + } else { + } + return TRUE; +} + +/* + * DarwinScreenInit + * This is a callback from dix during AddScreen() from InitOutput(). + * Initialize the screen and communicate information about it back to dix. + */ +static Bool DarwinScreenInit(int index, ScreenPtr pScreen, int argc, char **argv) { + int dpi; + static int foundIndex = 0; + Bool ret; + DarwinFramebufferPtr dfb; + + if (!dixRegisterPrivateKey(&darwinScreenKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + // reset index of found screens for each server generation + if (index == 0) { + foundIndex = 0; + + // reset the visual list + miClearVisualTypes(); + } + + // allocate space for private per screen storage + dfb = malloc(sizeof(DarwinFramebufferRec)); + + // SCREEN_PRIV(pScreen) = dfb; + dixSetPrivate(&pScreen->devPrivates, darwinScreenKey, dfb); + + // setup hardware/mode specific details + ret = QuartzAddScreen(foundIndex, pScreen); + foundIndex++; + if (! ret) + return FALSE; + + // setup a single visual appropriate for our pixel type + if(!miSetVisualTypesAndMasks(dfb->depth, dfb->visuals, dfb->bitsPerRGB, + dfb->preferredCVC, dfb->redMask, + dfb->greenMask, dfb->blueMask)) { + return FALSE; + } + +// TODO: Make PseudoColor visuals not suck in TrueColor mode +// if(dfb->depth > 8) +// miSetVisualTypesAndMasks(8, PseudoColorMask, 8, PseudoColor, 0, 0, 0); + if(dfb->depth > 15) + miSetVisualTypesAndMasks(15, TrueColorMask, 5, TrueColor, RM_ARGB(0,5,5,5), GM_ARGB(0,5,5,5), BM_ARGB(0,5,5,5)); + if(dfb->depth > 24) + miSetVisualTypesAndMasks(24, TrueColorMask, 8, TrueColor, RM_ARGB(0,8,8,8), GM_ARGB(0,8,8,8), BM_ARGB(0,8,8,8)); + + miSetPixmapDepths(); + + // machine independent screen init + // setup _Screen structure in pScreen + if (monitorResolution) + dpi = monitorResolution; + else + dpi = 96; + + // initialize fb + if (! fbScreenInit(pScreen, + dfb->framebuffer, // pointer to screen bitmap + dfb->width, dfb->height, // screen size in pixels + dpi, dpi, // dots per inch + dfb->pitch/(dfb->bitsPerPixel/8), // pixel width of framebuffer + dfb->bitsPerPixel)) // bits per pixel for screen + { + return FALSE; + } + + if (! fbPictureInit(pScreen, 0, 0)) { + return FALSE; + } + +#ifdef MITSHM + ShmRegisterFbFuncs(pScreen); +#endif + + // this must be initialized (why doesn't X have a default?) + pScreen->SaveScreen = DarwinSaveScreen; + + // finish mode dependent screen setup including cursor support + if (!QuartzSetupScreen(index, pScreen)) { + return FALSE; + } + + // create and install the default colormap and + // set pScreen->blackPixel / pScreen->white + if (!miCreateDefColormap( pScreen )) { + return FALSE; + } + + pScreen->x = dfb->x; + pScreen->y = dfb->y; + + /* ErrorF("Screen %d added: %dx%d @ (%d,%d)\n", + index, dfb->width, dfb->height, dfb->x, dfb->y); */ + + return TRUE; +} + +/* + ============================================================================= + + mouse and keyboard callbacks + + ============================================================================= +*/ + +/* + * DarwinMouseProc: Handle the initialization, etc. of a mouse + */ +static int DarwinMouseProc(DeviceIntPtr pPointer, int what) { +#define NBUTTONS 7 +#define NAXES 2 + // 7 buttons: left, right, middle, then four scroll wheel "buttons" + CARD8 map[NBUTTONS + 1] = {0, 1, 2, 3, 4, 5, 6, 7}; + Atom btn_labels[NBUTTONS] = {0}; + Atom axes_labels[NAXES] = {0}; + + switch (what) { + case DEVICE_INIT: + pPointer->public.on = FALSE; + + btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); + btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); + btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); + btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP); + btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN); + btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT); + btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT); + + axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); + axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); + + + // Set button map. + InitPointerDeviceStruct((DevicePtr)pPointer, map, NBUTTONS, + btn_labels, + (PtrCtrlProcPtr)NoopDDA, + GetMotionHistorySize(), NAXES, + axes_labels); +// InitValuatorAxisStruct(pPointer, 0, 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, Absolute); +// InitValuatorAxisStruct(pPointer, 1, 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, Absolute); + break; + case DEVICE_ON: + pPointer->public.on = TRUE; + AddEnabledDevice( darwinEventReadFD ); + return Success; + case DEVICE_CLOSE: + case DEVICE_OFF: + pPointer->public.on = FALSE; + RemoveEnabledDevice(darwinEventReadFD); + return Success; + } + + return Success; +#undef NBUTTONS +#undef NAXES +} + +static int DarwinTabletProc(DeviceIntPtr pPointer, int what) { +#define NBUTTONS 3 +#define NAXES 5 + CARD8 map[NBUTTONS + 1] = {0, 1, 2, 3}; + Atom btn_labels[NBUTTONS] = {0}; + Atom axes_labels[NAXES] = {0}; + + switch (what) { + case DEVICE_INIT: + pPointer->public.on = FALSE; + + btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); + btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); + btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); + + axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X); + axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y); + axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE); + axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_X); + axes_labels[4] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_Y); + + // Set button map. + InitPointerDeviceStruct((DevicePtr)pPointer, map, NBUTTONS, + btn_labels, + (PtrCtrlProcPtr)NoopDDA, + GetMotionHistorySize(), NAXES, + axes_labels); + InitProximityClassDeviceStruct(pPointer); + + InitValuatorAxisStruct(pPointer, 0, axes_labels[0], 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, Absolute); + InitValuatorAxisStruct(pPointer, 1, axes_labels[1], 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, Absolute); + InitValuatorAxisStruct(pPointer, 2, axes_labels[2], 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, Absolute); + InitValuatorAxisStruct(pPointer, 3, axes_labels[3], -XQUARTZ_VALUATOR_LIMIT, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, Absolute); + InitValuatorAxisStruct(pPointer, 4, axes_labels[4], -XQUARTZ_VALUATOR_LIMIT, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, Absolute); +// pPointer->use = IsXExtensionDevice; + break; + case DEVICE_ON: + pPointer->public.on = TRUE; + AddEnabledDevice( darwinEventReadFD ); + return Success; + case DEVICE_CLOSE: + case DEVICE_OFF: + pPointer->public.on = FALSE; + RemoveEnabledDevice(darwinEventReadFD); + return Success; + } + return Success; +#undef NBUTTONS +#undef NAXES +} + +/* + * DarwinKeybdProc + * Callback from X + */ +static int DarwinKeybdProc( DeviceIntPtr pDev, int onoff ) +{ + switch ( onoff ) { + case DEVICE_INIT: + DarwinKeyboardInit( pDev ); + break; + case DEVICE_ON: + pDev->public.on = TRUE; + AddEnabledDevice( darwinEventReadFD ); + break; + case DEVICE_OFF: + pDev->public.on = FALSE; + RemoveEnabledDevice( darwinEventReadFD ); + break; + case DEVICE_CLOSE: + break; + } + + return Success; +} + +/* +=========================================================================== + + Utility routines + +=========================================================================== +*/ + +/* + * DarwinParseModifierList + * Parse a list of modifier names and return a corresponding modifier mask + */ +int DarwinParseModifierList(const char *constmodifiers, int separatelr) +{ + int result = 0; + + if (constmodifiers) { + char *modifiers = strdup(constmodifiers); + char *modifier; + int nxkey; + char *p = modifiers; + + while (p) { + modifier = strsep(&p, " ,+&|/"); // allow lots of separators + nxkey = DarwinModifierStringToNXMask(modifier, separatelr); + if(nxkey) + result |= nxkey; + else + ErrorF("fakebuttons: Unknown modifier \"%s\"\n", modifier); + } + free(modifiers); + } + return result; +} + +/* +=========================================================================== + + Functions needed to link against device independent X + +=========================================================================== +*/ + +/* + * InitInput + * Register the keyboard and mouse devices + */ +void InitInput( int argc, char **argv ) +{ + XkbRMLVOSet rmlvo = { .rules = "base", .model = "empty", .layout = "empty", + .variant = NULL, .options = NULL }; + /* We need to really have rules... or something... */ + XkbSetRulesDflts(&rmlvo); + + darwinKeyboard = AddInputDevice(serverClient, DarwinKeybdProc, TRUE); + darwinKeyboard->name = strdup("keyboard"); + + /* here's the snippet from the current gdk sources: + if (!strcmp (tmp_name, "pointer")) + gdkdev->info.source = GDK_SOURCE_MOUSE; + else if (!strcmp (tmp_name, "wacom") || + !strcmp (tmp_name, "pen")) + gdkdev->info.source = GDK_SOURCE_PEN; + else if (!strcmp (tmp_name, "eraser")) + gdkdev->info.source = GDK_SOURCE_ERASER; + else if (!strcmp (tmp_name, "cursor")) + gdkdev->info.source = GDK_SOURCE_CURSOR; + else + gdkdev->info.source = GDK_SOURCE_PEN; + */ + + darwinPointer = AddInputDevice(serverClient, DarwinMouseProc, TRUE); + darwinPointer->name = strdup("pointer"); + + darwinTabletStylus = AddInputDevice(serverClient, DarwinTabletProc, TRUE); + darwinTabletStylus->name = strdup("pen"); + + darwinTabletCursor = AddInputDevice(serverClient, DarwinTabletProc, TRUE); + darwinTabletCursor->name = strdup("cursor"); + + darwinTabletEraser = AddInputDevice(serverClient, DarwinTabletProc, TRUE); + darwinTabletEraser->name = strdup("eraser"); + + darwinTabletCurrent = darwinTabletStylus; + + DarwinEQInit(); + + QuartzInitInput(argc, argv); +} + + +/* + * DarwinAdjustScreenOrigins + * Shift all screens so the X11 (0, 0) coordinate is at the top + * left of the global screen coordinates. + * + * Screens can be arranged so the top left isn't on any screen, so + * instead use the top left of the leftmost screen as (0,0). This + * may mean some screen space is in -y, but it's better that (0,0) + * be onscreen, or else default xterms disappear. It's better that + * -y be used than -x, because when popup menus are forced + * "onscreen" by dumb window managers like twm, they'll shift the + * menus down instead of left, which still looks funny but is an + * easier target to hit. + */ +void +DarwinAdjustScreenOrigins(ScreenInfo *pScreenInfo) +{ + int i, left, top; + + left = pScreenInfo->screens[0]->x; + top = pScreenInfo->screens[0]->y; + + /* Find leftmost screen. If there's a tie, take the topmost of the two. */ + for (i = 1; i < pScreenInfo->numScreens; i++) { + if (pScreenInfo->screens[i]->x < left || + (pScreenInfo->screens[i]->x == left && pScreenInfo->screens[i]->y < top)) + { + left = pScreenInfo->screens[i]->x; + top = pScreenInfo->screens[i]->y; + } + } + + darwinMainScreenX = left; + darwinMainScreenY = top; + + DEBUG_LOG("top = %d, left=%d\n", top, left); + + /* Shift all screens so that there is a screen whose top left + * is at X11 (0,0) and at global screen coordinate + * (darwinMainScreenX, darwinMainScreenY). + */ + + if (darwinMainScreenX != 0 || darwinMainScreenY != 0) { + for (i = 0; i < pScreenInfo->numScreens; i++) { + pScreenInfo->screens[i]->x -= darwinMainScreenX; + pScreenInfo->screens[i]->y -= darwinMainScreenY; + DEBUG_LOG("Screen %d placed at X11 coordinate (%d,%d).\n", + i, pScreenInfo->screens[i]->x, pScreenInfo->screens[i]->y); + } + } +} + + +/* + * InitOutput + * Initialize screenInfo for all actually accessible framebuffers. + * + * The display mode dependent code gets called three times. The mode + * specific InitOutput routines are expected to discover the number + * of potentially useful screens and cache routes to them internally. + * Inside DarwinScreenInit are two other mode specific calls. + * A mode specific AddScreen routine is called for each screen to + * actually initialize the screen with the ScreenPtr structure. + * After other screen setup has been done, a mode specific + * SetupScreen function can be called to finalize screen setup. + */ +void InitOutput( ScreenInfo *pScreenInfo, int argc, char **argv ) +{ + int i; + + pScreenInfo->imageByteOrder = IMAGE_BYTE_ORDER; + pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; + pScreenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD; + pScreenInfo->bitmapBitOrder = BITMAP_BIT_ORDER; + + // List how we want common pixmap formats to be padded + pScreenInfo->numPixmapFormats = NUMFORMATS; + for (i = 0; i < NUMFORMATS; i++) + pScreenInfo->formats[i] = formats[i]; + + // Discover screens and do mode specific initialization + QuartzInitOutput(argc, argv); + + // Add screens + for (i = 0; i < darwinScreensFound; i++) { + AddScreen(DarwinScreenInit, argc, argv); + } + + DarwinAdjustScreenOrigins(pScreenInfo); +} + + +/* + * OsVendorFatalError + */ +void OsVendorFatalError( void ) +{ + ErrorF( " OsVendorFatalError\n" ); +} + + +/* + * OsVendorInit + * Initialization of Darwin OS support. + */ +void OsVendorInit(void) +{ + if (serverGeneration == 1) { + DarwinPrintBanner(); +#ifdef ENABLE_DEBUG_LOG + { + char *home_dir=NULL, *log_file_path=NULL; + home_dir = getenv("HOME"); + if (home_dir) asprintf(&log_file_path, "%s/%s", home_dir, DEBUG_LOG_NAME); + if (log_file_path) { + if (!access(log_file_path, F_OK)) { + debug_log_fp = fopen(log_file_path, "a"); + if (debug_log_fp) ErrorF("Debug logging enabled to %s\n", log_file_path); + } + free(log_file_path); + } + } +#endif + } +} + + +/* + * ddxProcessArgument + * Process device-dependent command line args. Returns 0 if argument is + * not device dependent, otherwise Count of number of elements of argv + * that are part of a device dependent commandline option. + */ +int ddxProcessArgument( int argc, char *argv[], int i ) +{ +// if ( !strcmp( argv[i], "-fullscreen" ) ) { +// ErrorF( "Running full screen in parallel with Mac OS X Quartz window server.\n" ); +// return 1; +// } + +// if ( !strcmp( argv[i], "-rootless" ) ) { +// ErrorF( "Running rootless inside Mac OS X window server.\n" ); +// return 1; +// } + + // This command line arg is passed when launched from the Aqua GUI. + if ( !strncmp( argv[i], "-psn_", 5 ) ) { + return 1; + } + + if ( !strcmp( argv[i], "-fakebuttons" ) ) { + darwinFakeButtons = TRUE; + ErrorF( "Faking a three button mouse\n" ); + return 1; + } + + if ( !strcmp( argv[i], "-nofakebuttons" ) ) { + darwinFakeButtons = FALSE; + ErrorF( "Not faking a three button mouse\n" ); + return 1; + } + + if (!strcmp( argv[i], "-fakemouse2" ) ) { + if ( i == argc-1 ) { + FatalError( "-fakemouse2 must be followed by a modifer list\n" ); + } + if (!strcasecmp(argv[i+1], "none") || !strcmp(argv[i+1], "")) + darwinFakeMouse2Mask = 0; + else + darwinFakeMouse2Mask = DarwinParseModifierList(argv[i+1], 1); + ErrorF("Modifier mask to fake mouse button 2 = 0x%x\n", + darwinFakeMouse2Mask); + return 2; + } + + if (!strcmp( argv[i], "-fakemouse3" ) ) { + if ( i == argc-1 ) { + FatalError( "-fakemouse3 must be followed by a modifer list\n" ); + } + if (!strcasecmp(argv[i+1], "none") || !strcmp(argv[i+1], "")) + darwinFakeMouse3Mask = 0; + else + darwinFakeMouse3Mask = DarwinParseModifierList(argv[i+1], 1); + ErrorF("Modifier mask to fake mouse button 3 = 0x%x\n", + darwinFakeMouse3Mask); + return 2; + } + + if ( !strcmp( argv[i], "+synckeymap" ) ) { + darwinSyncKeymap = TRUE; + return 1; + } + + if ( !strcmp( argv[i], "-synckeymap" ) ) { + darwinSyncKeymap = FALSE; + return 1; + } + + if ( !strcmp( argv[i], "-depth" ) ) { + if ( i == argc-1 ) { + FatalError( "-depth must be followed by a number\n" ); + } + darwinDesiredDepth = atoi( argv[i+1] ); + if(darwinDesiredDepth != -1 && + darwinDesiredDepth != 8 && + darwinDesiredDepth != 15 && + darwinDesiredDepth != 24) { + FatalError( "Unsupported pixel depth. Use 8, 15, or 24 bits\n" ); + } + + ErrorF( "Attempting to use pixel depth of %i\n", darwinDesiredDepth ); + return 2; + } + + if (!strcmp( argv[i], "-showconfig" ) || !strcmp( argv[i], "-version" )) { + DarwinPrintBanner(); + exit(0); + } + + return 0; +} + + +/* + * ddxUseMsg -- + * Print out correct use of device dependent commandline options. + * Maybe the user now knows what really to do ... + */ +void ddxUseMsg( void ) +{ + ErrorF("\n"); + ErrorF("\n"); + ErrorF("Device Dependent Usage:\n"); + ErrorF("\n"); + ErrorF("-depth <8,15,24> : use this bit depth.\n"); + ErrorF("-fakebuttons : fake a three button mouse with Command and Option keys.\n"); + ErrorF("-nofakebuttons : don't fake a three button mouse.\n"); + ErrorF("-fakemouse2 <modifiers> : fake middle mouse button with modifier keys.\n"); + ErrorF("-fakemouse3 <modifiers> : fake right mouse button with modifier keys.\n"); + ErrorF(" ex: -fakemouse2 \"option,shift\" = option-shift-click is middle button.\n"); + ErrorF("-version : show the server version.\n"); + ErrorF("\n"); +} + + +/* + * ddxGiveUp -- + * Device dependent cleanup. Called by dix before normal server death. + */ +void ddxGiveUp( void ) +{ + ErrorF( "Quitting Xquartz\n" ); +} + + +/* + * AbortDDX -- + * DDX - specific abort routine. Called by AbortServer(). The attempt is + * made to restore all original setting of the displays. Also all devices + * are closed. + */ +void AbortDDX( void ) +{ + ErrorF( " AbortDDX\n" ); + OsAbort(); +} + diff --git a/xorg-server/hw/xquartz/darwin.h b/xorg-server/hw/xquartz/darwin.h index 7cd4336cd..e874af24c 100644 --- a/xorg-server/hw/xquartz/darwin.h +++ b/xorg-server/hw/xquartz/darwin.h @@ -1,92 +1,91 @@ -/*
- * Copyright (C) 2008 Apple, Inc.
- * Copyright (c) 2001-2004 Torrey T. Lyons. 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:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name(s) of the above copyright
- * holders shall not be used in advertising or otherwise to promote the sale,
- * use or other dealings in this Software without prior written authorization.
- */
-
-#ifndef _DARWIN_H
-#define _DARWIN_H
-
-#include <IOKit/IOTypes.h>
-#include "inputstr.h"
-#include "scrnintstr.h"
-#include <X11/extensions/XKB.h>
-#include <assert.h>
-
-#include "threadSafety.h"
-
-#include "darwinfb.h"
-
-// From darwin.c
-void DarwinPrintBanner(void);
-int DarwinParseModifierList(const char *constmodifiers, int separatelr);
-void DarwinAdjustScreenOrigins(ScreenInfo *pScreenInfo);
-void xf86SetRootClip (ScreenPtr pScreen, int enable);
-
-#define SCREEN_PRIV(pScreen) ((DarwinFramebufferPtr) \
- dixLookupPrivate(&pScreen->devPrivates, darwinScreenKey))
-
-/*
- * Global variables from darwin.c
- */
-extern DevPrivateKeyRec darwinScreenKeyRec;
-#define darwinScreenKey (&darwinScreenKeyRec)
-extern int darwinScreensFound;
-extern io_connect_t darwinParamConnect;
-extern int darwinEventReadFD;
-extern int darwinEventWriteFD;
-extern DeviceIntPtr darwinPointer;
-extern DeviceIntPtr darwinTabletCurrent;
-extern DeviceIntPtr darwinTabletCursor;
-extern DeviceIntPtr darwinTabletStylus;
-extern DeviceIntPtr darwinTabletEraser;
-extern DeviceIntPtr darwinKeyboard;
-
-// User preferences
-extern int darwinMouseAccelChange;
-extern int darwinFakeButtons;
-extern int darwinFakeMouse2Mask;
-extern int darwinFakeMouse3Mask;
-extern unsigned int darwinAppKitModMask;
-extern unsigned int windowItemModMask;
-extern int darwinSyncKeymap;
-extern int darwinDesiredDepth;
-
-// location of X11's (0,0) point in global screen coordinates
-extern int darwinMainScreenX;
-extern int darwinMainScreenY;
-
-#define ENABLE_DEBUG_LOG 1
-
-#ifdef ENABLE_DEBUG_LOG
-extern FILE *debug_log_fp;
-#define DEBUG_LOG_NAME "x11-debug.txt"
-#define DEBUG_LOG(msg, args...) if (debug_log_fp) fprintf(debug_log_fp, "%s:%s:%s:%d " msg, threadSafetyID(pthread_self()), __FILE__, __FUNCTION__, __LINE__, ##args ); fflush(debug_log_fp);
-#else
-#define DEBUG_LOG(msg, args...)
-#endif
-
-#define TRACE() DEBUG_LOG("\n")
-
-#endif /* _DARWIN_H */
+/* + * Copyright (C) 2008 Apple, Inc. + * Copyright (c) 2001-2004 Torrey T. Lyons. 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: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + +#ifndef _DARWIN_H +#define _DARWIN_H + +#include <IOKit/IOTypes.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include <X11/extensions/XKB.h> +#include <assert.h> + +#include "threadSafety.h" + +#include "darwinfb.h" + +// From darwin.c +void DarwinPrintBanner(void); +int DarwinParseModifierList(const char *constmodifiers, int separatelr); +void DarwinAdjustScreenOrigins(ScreenInfo *pScreenInfo); + +#define SCREEN_PRIV(pScreen) ((DarwinFramebufferPtr) \ + dixLookupPrivate(&pScreen->devPrivates, darwinScreenKey)) + +/* + * Global variables from darwin.c + */ +extern DevPrivateKeyRec darwinScreenKeyRec; +#define darwinScreenKey (&darwinScreenKeyRec) +extern int darwinScreensFound; +extern io_connect_t darwinParamConnect; +extern int darwinEventReadFD; +extern int darwinEventWriteFD; +extern DeviceIntPtr darwinPointer; +extern DeviceIntPtr darwinTabletCurrent; +extern DeviceIntPtr darwinTabletCursor; +extern DeviceIntPtr darwinTabletStylus; +extern DeviceIntPtr darwinTabletEraser; +extern DeviceIntPtr darwinKeyboard; + +// User preferences +extern int darwinMouseAccelChange; +extern int darwinFakeButtons; +extern int darwinFakeMouse2Mask; +extern int darwinFakeMouse3Mask; +extern unsigned int darwinAppKitModMask; +extern unsigned int windowItemModMask; +extern int darwinSyncKeymap; +extern int darwinDesiredDepth; + +// location of X11's (0,0) point in global screen coordinates +extern int darwinMainScreenX; +extern int darwinMainScreenY; + +#define ENABLE_DEBUG_LOG 1 + +#ifdef ENABLE_DEBUG_LOG +extern FILE *debug_log_fp; +#define DEBUG_LOG_NAME "x11-debug.txt" +#define DEBUG_LOG(msg, args...) if (debug_log_fp) fprintf(debug_log_fp, "%s:%s:%s:%d " msg, threadSafetyID(pthread_self()), __FILE__, __FUNCTION__, __LINE__, ##args ); fflush(debug_log_fp); +#else +#define DEBUG_LOG(msg, args...) +#endif + +#define TRACE() DEBUG_LOG("\n") + +#endif /* _DARWIN_H */ diff --git a/xorg-server/hw/xquartz/darwinXinput.c b/xorg-server/hw/xquartz/darwinXinput.c index 527c5bcff..3ef34fec0 100644 --- a/xorg-server/hw/xquartz/darwinXinput.c +++ b/xorg-server/hw/xquartz/darwinXinput.c @@ -1,166 +1,156 @@ -/*
- * X server support of the XINPUT extension for xquartz
- *
- * This is currently a copy of Xi/stubs.c, but eventually this
- * should include more complete XINPUT support.
- */
-
-/************************************************************
-
-Copyright 1989, 1998 The Open Group
-
-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.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group 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 Open Group.
-
-Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-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 Hewlett-Packard not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-HEWLETT-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_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "inputstr.h"
-#include <X11/extensions/XI.h>
-#include <X11/extensions/XIproto.h>
-#include "XIstubs.h"
-#include "darwin.h"
-
-/****************************************************************************
- *
- * Caller: ProcXSetDeviceMode
- *
- * Change the mode of an extension device.
- * This function is used to change the mode of a device from reporting
- * relative motion to reporting absolute positional information, and
- * vice versa.
- * The default implementation below is that no such devices are supported.
- *
- */
-
-int
-SetDeviceMode(ClientPtr client, DeviceIntPtr dev, int mode)
-{
- DEBUG_LOG("SetDeviceMode(%p, %p, %d)\n", client, dev, mode);
- return BadMatch;
-}
-
-/****************************************************************************
- *
- * Caller: ProcXSetDeviceValuators
- *
- * Set the value of valuators on an extension input device.
- * This function is used to set the initial value of valuators on
- * those input devices that are capable of reporting either relative
- * motion or an absolute position, and allow an initial position to be set.
- * The default implementation below is that no such devices are supported.
- *
- */
-
-int
-SetDeviceValuators(ClientPtr client, DeviceIntPtr dev,
- int *valuators, int first_valuator, int num_valuators)
-{
- DEBUG_LOG("SetDeviceValuators(%p, %p, %p, %d, %d)\n", client,
- dev, valuators, first_valuator, num_valuators);
- return BadMatch;
-}
-
-/****************************************************************************
- *
- * Caller: ProcXChangeDeviceControl
- *
- * Change the specified device controls on an extension input device.
- *
- */
-
-int
-ChangeDeviceControl(ClientPtr client, DeviceIntPtr dev,
- xDeviceCtl * control)
-{
-
- DEBUG_LOG("ChangeDeviceControl(%p, %p, %p)\n", client, dev, control);
- switch (control->control) {
- case DEVICE_RESOLUTION:
- return BadMatch;
- case DEVICE_ABS_CALIB:
- case DEVICE_ABS_AREA:
- return BadMatch;
- case DEVICE_CORE:
- return BadMatch;
- default:
- return BadMatch;
- }
-}
-
-
-/****************************************************************************
- *
- * Caller: configAddDevice (and others)
- *
- * Add a new device with the specified options.
- *
- */
-int
-NewInputDeviceRequest(InputOption *options, InputAttributes *attrs,
- DeviceIntPtr *pdev)
-{
- DEBUG_LOG("NewInputDeviceRequest(%p, %p)\n", options, pdev);
- return BadValue;
-}
-
-/****************************************************************************
- *
- * Caller: configRemoveDevice (and others)
- *
- * Remove the specified device previously added.
- *
- */
-void
-DeleteInputDeviceRequest(DeviceIntPtr dev)
-{
- DEBUG_LOG("DeleteInputDeviceRequest(%p)\n", dev);
-}
-
-void
-CloseInput (void)
-{
-}
-
+/* + * X server support of the XINPUT extension for xquartz + * + * This is currently a copy of Xi/stubs.c, but eventually this + * should include more complete XINPUT support. + */ + +/************************************************************ + +Copyright 1989, 1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group 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 Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +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 Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-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_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "inputstr.h" +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include "XIstubs.h" +#include "darwin.h" + +/**************************************************************************** + * + * Caller: ProcXSetDeviceMode + * + * Change the mode of an extension device. + * This function is used to change the mode of a device from reporting + * relative motion to reporting absolute positional information, and + * vice versa. + * The default implementation below is that no such devices are supported. + * + */ + +int +SetDeviceMode(ClientPtr client, DeviceIntPtr dev, int mode) +{ + DEBUG_LOG("SetDeviceMode(%p, %p, %d)\n", client, dev, mode); + return BadMatch; +} + +/**************************************************************************** + * + * Caller: ProcXSetDeviceValuators + * + * Set the value of valuators on an extension input device. + * This function is used to set the initial value of valuators on + * those input devices that are capable of reporting either relative + * motion or an absolute position, and allow an initial position to be set. + * The default implementation below is that no such devices are supported. + * + */ + +int +SetDeviceValuators(ClientPtr client, DeviceIntPtr dev, + int *valuators, int first_valuator, int num_valuators) +{ + DEBUG_LOG("SetDeviceValuators(%p, %p, %p, %d, %d)\n", client, + dev, valuators, first_valuator, num_valuators); + return BadMatch; +} + +/**************************************************************************** + * + * Caller: ProcXChangeDeviceControl + * + * Change the specified device controls on an extension input device. + * + */ + +int +ChangeDeviceControl(ClientPtr client, DeviceIntPtr dev, + xDeviceCtl * control) +{ + + DEBUG_LOG("ChangeDeviceControl(%p, %p, %p)\n", client, dev, control); + return BadMatch; +} + + +/**************************************************************************** + * + * Caller: configAddDevice (and others) + * + * Add a new device with the specified options. + * + */ +int +NewInputDeviceRequest(InputOption *options, InputAttributes *attrs, + DeviceIntPtr *pdev) +{ + DEBUG_LOG("NewInputDeviceRequest(%p, %p)\n", options, pdev); + return BadValue; +} + +/**************************************************************************** + * + * Caller: configRemoveDevice (and others) + * + * Remove the specified device previously added. + * + */ +void +DeleteInputDeviceRequest(DeviceIntPtr dev) +{ + DEBUG_LOG("DeleteInputDeviceRequest(%p)\n", dev); +} + +void +CloseInput (void) +{ +} + diff --git a/xorg-server/hw/xquartz/quartz.c b/xorg-server/hw/xquartz/quartz.c index 11e5a74d7..4b72a89d3 100644 --- a/xorg-server/hw/xquartz/quartz.c +++ b/xorg-server/hw/xquartz/quartz.c @@ -442,7 +442,7 @@ void QuartzSetRootClip( for (i = 0; i < screenInfo.numScreens; i++) { if (screenInfo.screens[i]) { - xf86SetRootClip(screenInfo.screens[i], enable); + SetRootClip(screenInfo.screens[i], enable); } } } diff --git a/xorg-server/hw/xquartz/threadSafety.h b/xorg-server/hw/xquartz/threadSafety.h index 7b009103a..3ff9eaf7e 100644 --- a/xorg-server/hw/xquartz/threadSafety.h +++ b/xorg-server/hw/xquartz/threadSafety.h @@ -53,4 +53,4 @@ const char *threadSafetyID(pthread_t tid); #define TA_APPKIT() #endif -#endif _XQ_THREAD_SAFETY_H_ +#endif /* _XQ_THREAD_SAFETY_H_ */ diff --git a/xorg-server/hw/xquartz/xpr/xprScreen.c b/xorg-server/hw/xquartz/xpr/xprScreen.c index 972278b75..f6a712906 100644 --- a/xorg-server/hw/xquartz/xpr/xprScreen.c +++ b/xorg-server/hw/xquartz/xpr/xprScreen.c @@ -326,7 +326,9 @@ xprAddScreen(int index, ScreenPtr pScreen) #endif } +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 have_depth: +#endif switch(depth) { case 8: // pseudo-working dfb->visuals = PseudoColorMask; diff --git a/xorg-server/hw/xwin/winrandr.c b/xorg-server/hw/xwin/winrandr.c index 248404800..c58119360 100644 --- a/xorg-server/hw/xwin/winrandr.c +++ b/xorg-server/hw/xwin/winrandr.c @@ -63,106 +63,6 @@ winRandRGetInfo (ScreenPtr pScreen, Rotation *pRotations) return TRUE; } - -/* - Copied from the xfree86 DDX - - Why can't this be in DIX? - Does union _Validate vary depending on DDX?? - */ -static void -xf86SetRootClip (ScreenPtr pScreen, Bool enable) -{ - WindowPtr pWin = pScreen->root; - WindowPtr pChild; - Bool WasViewable = (Bool)(pWin->viewable); - Bool anyMarked = FALSE; - WindowPtr pLayerWin; - BoxRec box; - - 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; - } - } - - /* - * Use REGION_BREAK to avoid optimizations in ValidateTree - * that assume the root borderClip can't change well, normally - * it doesn't...) - */ - if (enable) - { - box.x1 = 0; - box.y1 = 0; - box.x2 = pScreen->width; - box.y2 = pScreen->height; - REGION_INIT (pScreen, &pWin->winSize, &box, 1); - REGION_INIT (pScreen, &pWin->borderSize, &box, 1); - if (WasViewable) - REGION_RESET(pScreen, &pWin->borderClip, &box); - pWin->drawable.width = pScreen->width; - pWin->drawable.height = pScreen->height; - 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->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 (); - FlushAllOutput (); -} - /* */ @@ -178,7 +78,7 @@ winDoRandRScreenSetSize (ScreenPtr pScreen, WindowPtr pRoot = pScreen->root; // Prevent screen updates while we change things around - xf86SetRootClip(pScreen, FALSE); + SetRootClip(pScreen, FALSE); /* Update the screen size as requested */ pScreenInfo->dwWidth = width; @@ -205,7 +105,7 @@ winDoRandRScreenSetSize (ScreenPtr pScreen, // does this emit a ConfigureNotify?? // Restore the ability to update screen, now with new dimensions - xf86SetRootClip(pScreen, TRUE); + SetRootClip(pScreen, TRUE); // and arrange for it to be repainted miPaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND); |